diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 144a7af5..dac6a793 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -49,6 +49,8 @@ jobs: - name: Format and lint run: | + python -m pip install --upgrade pip + pip install hatch pytest pytest-cov uv run ruff check uv run ruff format --check @@ -63,6 +65,12 @@ jobs: uv run mypy uv run --with pytest-cov pytest --cov-report=term-missing --color=yes --cov=pkg + - name: Build and test Schema Wrapper + run: | + cd packages/schema_wrapper + pip install -e . + pytest test/ --cov=schema_wrapper --cov-report=term-missing + rust: name: Test in Rust diff --git a/packages/schema_wrapper/README.md b/packages/schema_wrapper/README.md new file mode 100644 index 00000000..1333ed77 --- /dev/null +++ b/packages/schema_wrapper/README.md @@ -0,0 +1 @@ +TODO diff --git a/packages/schema_wrapper/__init__.py b/packages/schema_wrapper/__init__.py new file mode 100644 index 00000000..9b1c6c73 --- /dev/null +++ b/packages/schema_wrapper/__init__.py @@ -0,0 +1,4 @@ +from .src.generate_schema_wrapper import generate_schema_wrapper +from .src.utils import jsonschema_to_python_types + +__all__ = ['generate_schema_wrapper', 'jsonschema_to_python_types'] \ No newline at end of file diff --git a/packages/schema_wrapper/__pycache__/__init__.cpython-39.pyc b/packages/schema_wrapper/__pycache__/__init__.cpython-39.pyc new file mode 100644 index 00000000..8042be7b Binary files /dev/null and b/packages/schema_wrapper/__pycache__/__init__.cpython-39.pyc differ diff --git a/packages/schema_wrapper/__pycache__/generate_schema_wrapper.cpython-39.pyc b/packages/schema_wrapper/__pycache__/generate_schema_wrapper.cpython-39.pyc new file mode 100644 index 00000000..de910fa4 Binary files /dev/null and b/packages/schema_wrapper/__pycache__/generate_schema_wrapper.cpython-39.pyc differ diff --git a/packages/schema_wrapper/__pycache__/utils.cpython-39.pyc b/packages/schema_wrapper/__pycache__/utils.cpython-39.pyc new file mode 100644 index 00000000..2b178138 Binary files /dev/null and b/packages/schema_wrapper/__pycache__/utils.cpython-39.pyc differ diff --git a/packages/schema_wrapper/generated_classes.py b/packages/schema_wrapper/generated_classes.py new file mode 100644 index 00000000..6736ffdd --- /dev/null +++ b/packages/schema_wrapper/generated_classes.py @@ -0,0 +1,5441 @@ +from typing import List, Dict, Any, Union + +class AggregateExpression: + def __init__(self, agg: str, label: str = None): + self.agg = agg + self.label = label + + +class AggregateTransform: + def __init__(self, value: Union["Argmin", "Product", "Quantile", "StddevPop", "Mode", "Avg", "VarPop", "Stddev", "Sum", "Variance", "Min", "First", "Last", "Argmax", "Max", "Count", "Median"]): + self.value = value + + +class ChannelValue: + def __init__(self, value: Union[List[Any], float, "Transform", str, "AggregateExpression", "SQLExpression", bool, Any]): + self.value = value + + +class PlotMarkData: + def __init__(self, value: Union["PlotDataInline", "PlotFrom"]): + self.value = value + + +class ChannelValueSpec: + def __init__(self, value: Union[Dict[str, Any], "ChannelValue"]): + self.value = value + + +class SelectFilter: + def __init__(self): + pass + + +class Argmax: + def __init__(self, argmax: List[Union[str, float, bool]], distinct: bool = None, orderby: Union["TransformField", List["TransformField"]] = None, partitionby: Union["TransformField", List["TransformField"]] = None, range: Union[List[Union[float, Any]], "ParamRef"] = None, rows: Union[List[Union[float, Any]], "ParamRef"] = None): + self.argmax = argmax + self.distinct = distinct + self.orderby = orderby + self.partitionby = partitionby + self.range = range + self.rows = rows + + +class Argmin: + def __init__(self, argmin: List[Union[str, float, bool]], distinct: bool = None, orderby: Union["TransformField", List["TransformField"]] = None, partitionby: Union["TransformField", List["TransformField"]] = None, range: Union[List[Union[float, Any]], "ParamRef"] = None, rows: Union[List[Union[float, Any]], "ParamRef"] = None): + self.argmin = argmin + self.distinct = distinct + self.orderby = orderby + self.partitionby = partitionby + self.range = range + self.rows = rows + + +class Avg: + def __init__(self, avg: Union[Union[str, float, bool], List[Union[str, float, bool]]], distinct: bool = None, orderby: Union["TransformField", List["TransformField"]] = None, partitionby: Union["TransformField", List["TransformField"]] = None, range: Union[List[Union[float, Any]], "ParamRef"] = None, rows: Union[List[Union[float, Any]], "ParamRef"] = None): + self.avg = avg + self.distinct = distinct + self.orderby = orderby + self.partitionby = partitionby + self.range = range + self.rows = rows + + +class ChannelValueIntervalSpec: + def __init__(self, value: Union["ChannelValueSpec", Dict[str, Any]]): + self.value = value + + +class BinInterval: + def __init__(self): + pass + + +class BrushStyles: + def __init__(self, fill: str = None, fillOpacity: float = None, opacity: float = None, stroke: str = None, strokeOpacity: float = None): + self.fill = fill + self.fillOpacity = fillOpacity + self.opacity = opacity + self.stroke = stroke + self.strokeOpacity = strokeOpacity + + +class CSSStyles: + def __init__(self, accentColor: str = None, alignContent: str = None, alignItems: str = None, alignSelf: str = None, alignmentBaseline: str = None, all: str = None, animation: str = None, animationComposition: str = None, animationDelay: str = None, animationDirection: str = None, animationDuration: str = None, animationFillMode: str = None, animationIterationCount: str = None, animationName: str = None, animationPlayState: str = None, animationTimingFunction: str = None, appearance: str = None, aspectRatio: str = None, backdropFilter: str = None, backfaceVisibility: str = None, background: str = None, backgroundAttachment: str = None, backgroundBlendMode: str = None, backgroundClip: str = None, backgroundColor: str = None, backgroundImage: str = None, backgroundOrigin: str = None, backgroundPosition: str = None, backgroundPositionX: str = None, backgroundPositionY: str = None, backgroundRepeat: str = None, backgroundSize: str = None, baselineShift: str = None, baselineSource: str = None, blockSize: str = None, border: str = None, borderBlock: str = None, borderBlockColor: str = None, borderBlockEnd: str = None, borderBlockEndColor: str = None, borderBlockEndStyle: str = None, borderBlockEndWidth: str = None, borderBlockStart: str = None, borderBlockStartColor: str = None, borderBlockStartStyle: str = None, borderBlockStartWidth: str = None, borderBlockStyle: str = None, borderBlockWidth: str = None, borderBottom: str = None, borderBottomColor: str = None, borderBottomLeftRadius: str = None, borderBottomRightRadius: str = None, borderBottomStyle: str = None, borderBottomWidth: str = None, borderCollapse: str = None, borderColor: str = None, borderEndEndRadius: str = None, borderEndStartRadius: str = None, borderImage: str = None, borderImageOutset: str = None, borderImageRepeat: str = None, borderImageSlice: str = None, borderImageSource: str = None, borderImageWidth: str = None, borderInline: str = None, borderInlineColor: str = None, borderInlineEnd: str = None, borderInlineEndColor: str = None, borderInlineEndStyle: str = None, borderInlineEndWidth: str = None, borderInlineStart: str = None, borderInlineStartColor: str = None, borderInlineStartStyle: str = None, borderInlineStartWidth: str = None, borderInlineStyle: str = None, borderInlineWidth: str = None, borderLeft: str = None, borderLeftColor: str = None, borderLeftStyle: str = None, borderLeftWidth: str = None, borderRadius: str = None, borderRight: str = None, borderRightColor: str = None, borderRightStyle: str = None, borderRightWidth: str = None, borderSpacing: str = None, borderStartEndRadius: str = None, borderStartStartRadius: str = None, borderStyle: str = None, borderTop: str = None, borderTopColor: str = None, borderTopLeftRadius: str = None, borderTopRightRadius: str = None, borderTopStyle: str = None, borderTopWidth: str = None, borderWidth: str = None, bottom: str = None, boxShadow: str = None, boxSizing: str = None, breakAfter: str = None, breakBefore: str = None, breakInside: str = None, captionSide: str = None, caretColor: str = None, clear: str = None, clip: str = None, clipPath: str = None, clipRule: str = None, color: str = None, colorInterpolation: str = None, colorInterpolationFilters: str = None, colorScheme: str = None, columnCount: str = None, columnFill: str = None, columnGap: str = None, columnRule: str = None, columnRuleColor: str = None, columnRuleStyle: str = None, columnRuleWidth: str = None, columnSpan: str = None, columnWidth: str = None, columns: str = None, contain: str = None, containIntrinsicBlockSize: str = None, containIntrinsicHeight: str = None, containIntrinsicInlineSize: str = None, containIntrinsicSize: str = None, containIntrinsicWidth: str = None, container: str = None, containerName: str = None, containerType: str = None, content: str = None, contentVisibility: str = None, counterIncrement: str = None, counterReset: str = None, counterSet: str = None, cssFloat: str = None, cssText: str = None, cursor: str = None, cx: str = None, cy: str = None, d: str = None, direction: str = None, display: str = None, dominantBaseline: str = None, emptyCells: str = None, fill: str = None, fillOpacity: str = None, fillRule: str = None, filter: str = None, flex: str = None, flexBasis: str = None, flexDirection: str = None, flexFlow: str = None, flexGrow: str = None, flexShrink: str = None, flexWrap: str = None, float: str = None, floodColor: str = None, floodOpacity: str = None, font: str = None, fontFamily: str = None, fontFeatureSettings: str = None, fontKerning: str = None, fontOpticalSizing: str = None, fontPalette: str = None, fontSize: str = None, fontSizeAdjust: str = None, fontStretch: str = None, fontStyle: str = None, fontSynthesis: str = None, fontSynthesisSmallCaps: str = None, fontSynthesisStyle: str = None, fontSynthesisWeight: str = None, fontVariant: str = None, fontVariantAlternates: str = None, fontVariantCaps: str = None, fontVariantEastAsian: str = None, fontVariantLigatures: str = None, fontVariantNumeric: str = None, fontVariantPosition: str = None, fontVariationSettings: str = None, fontWeight: str = None, forcedColorAdjust: str = None, gap: str = None, grid: str = None, gridArea: str = None, gridAutoColumns: str = None, gridAutoFlow: str = None, gridAutoRows: str = None, gridColumn: str = None, gridColumnEnd: str = None, gridColumnGap: str = None, gridColumnStart: str = None, gridGap: str = None, gridRow: str = None, gridRowEnd: str = None, gridRowGap: str = None, gridRowStart: str = None, gridTemplate: str = None, gridTemplateAreas: str = None, gridTemplateColumns: str = None, gridTemplateRows: str = None, height: str = None, hyphenateCharacter: str = None, hyphens: str = None, imageOrientation: str = None, imageRendering: str = None, inlineSize: str = None, inset: str = None, insetBlock: str = None, insetBlockEnd: str = None, insetBlockStart: str = None, insetInline: str = None, insetInlineEnd: str = None, insetInlineStart: str = None, isolation: str = None, justifyContent: str = None, justifyItems: str = None, justifySelf: str = None, left: str = None, length: float = None, letterSpacing: str = None, lightingColor: str = None, lineBreak: str = None, lineHeight: str = None, listStyle: str = None, listStyleImage: str = None, listStylePosition: str = None, listStyleType: str = None, margin: str = None, marginBlock: str = None, marginBlockEnd: str = None, marginBlockStart: str = None, marginBottom: str = None, marginInline: str = None, marginInlineEnd: str = None, marginInlineStart: str = None, marginLeft: str = None, marginRight: str = None, marginTop: str = None, marker: str = None, markerEnd: str = None, markerMid: str = None, markerStart: str = None, mask: str = None, maskClip: str = None, maskComposite: str = None, maskImage: str = None, maskMode: str = None, maskOrigin: str = None, maskPosition: str = None, maskRepeat: str = None, maskSize: str = None, maskType: str = None, mathDepth: str = None, mathStyle: str = None, maxBlockSize: str = None, maxHeight: str = None, maxInlineSize: str = None, maxWidth: str = None, minBlockSize: str = None, minHeight: str = None, minInlineSize: str = None, minWidth: str = None, mixBlendMode: str = None, objectFit: str = None, objectPosition: str = None, offset: str = None, offsetAnchor: str = None, offsetDistance: str = None, offsetPath: str = None, offsetPosition: str = None, offsetRotate: str = None, opacity: str = None, order: str = None, orphans: str = None, outline: str = None, outlineColor: str = None, outlineOffset: str = None, outlineStyle: str = None, outlineWidth: str = None, overflow: str = None, overflowAnchor: str = None, overflowClipMargin: str = None, overflowWrap: str = None, overflowX: str = None, overflowY: str = None, overscrollBehavior: str = None, overscrollBehaviorBlock: str = None, overscrollBehaviorInline: str = None, overscrollBehaviorX: str = None, overscrollBehaviorY: str = None, padding: str = None, paddingBlock: str = None, paddingBlockEnd: str = None, paddingBlockStart: str = None, paddingBottom: str = None, paddingInline: str = None, paddingInlineEnd: str = None, paddingInlineStart: str = None, paddingLeft: str = None, paddingRight: str = None, paddingTop: str = None, page: str = None, pageBreakAfter: str = None, pageBreakBefore: str = None, pageBreakInside: str = None, paintOrder: str = None, perspective: str = None, perspectiveOrigin: str = None, placeContent: str = None, placeItems: str = None, placeSelf: str = None, pointerEvents: str = None, position: str = None, printColorAdjust: str = None, quotes: str = None, r: str = None, resize: str = None, right: str = None, rotate: str = None, rowGap: str = None, rubyPosition: str = None, rx: str = None, ry: str = None, scale: str = None, scrollBehavior: str = None, scrollMargin: str = None, scrollMarginBlock: str = None, scrollMarginBlockEnd: str = None, scrollMarginBlockStart: str = None, scrollMarginBottom: str = None, scrollMarginInline: str = None, scrollMarginInlineEnd: str = None, scrollMarginInlineStart: str = None, scrollMarginLeft: str = None, scrollMarginRight: str = None, scrollMarginTop: str = None, scrollPadding: str = None, scrollPaddingBlock: str = None, scrollPaddingBlockEnd: str = None, scrollPaddingBlockStart: str = None, scrollPaddingBottom: str = None, scrollPaddingInline: str = None, scrollPaddingInlineEnd: str = None, scrollPaddingInlineStart: str = None, scrollPaddingLeft: str = None, scrollPaddingRight: str = None, scrollPaddingTop: str = None, scrollSnapAlign: str = None, scrollSnapStop: str = None, scrollSnapType: str = None, scrollbarColor: str = None, scrollbarGutter: str = None, scrollbarWidth: str = None, shapeImageThreshold: str = None, shapeMargin: str = None, shapeOutside: str = None, shapeRendering: str = None, stopColor: str = None, stopOpacity: str = None, stroke: str = None, strokeDasharray: str = None, strokeDashoffset: str = None, strokeLinecap: str = None, strokeLinejoin: str = None, strokeMiterlimit: str = None, strokeOpacity: str = None, strokeWidth: str = None, tabSize: str = None, tableLayout: str = None, textAlign: str = None, textAlignLast: str = None, textAnchor: str = None, textCombineUpright: str = None, textDecoration: str = None, textDecorationColor: str = None, textDecorationLine: str = None, textDecorationSkipInk: str = None, textDecorationStyle: str = None, textDecorationThickness: str = None, textEmphasis: str = None, textEmphasisColor: str = None, textEmphasisPosition: str = None, textEmphasisStyle: str = None, textIndent: str = None, textOrientation: str = None, textOverflow: str = None, textRendering: str = None, textShadow: str = None, textTransform: str = None, textUnderlineOffset: str = None, textUnderlinePosition: str = None, textWrap: str = None, textWrapMode: str = None, textWrapStyle: str = None, top: str = None, touchAction: str = None, transform: str = None, transformBox: str = None, transformOrigin: str = None, transformStyle: str = None, transition: str = None, transitionBehavior: str = None, transitionDelay: str = None, transitionDuration: str = None, transitionProperty: str = None, transitionTimingFunction: str = None, translate: str = None, unicodeBidi: str = None, userSelect: str = None, vectorEffect: str = None, verticalAlign: str = None, visibility: str = None, webkitAlignContent: str = None, webkitAlignItems: str = None, webkitAlignSelf: str = None, webkitAnimation: str = None, webkitAnimationDelay: str = None, webkitAnimationDirection: str = None, webkitAnimationDuration: str = None, webkitAnimationFillMode: str = None, webkitAnimationIterationCount: str = None, webkitAnimationName: str = None, webkitAnimationPlayState: str = None, webkitAnimationTimingFunction: str = None, webkitAppearance: str = None, webkitBackfaceVisibility: str = None, webkitBackgroundClip: str = None, webkitBackgroundOrigin: str = None, webkitBackgroundSize: str = None, webkitBorderBottomLeftRadius: str = None, webkitBorderBottomRightRadius: str = None, webkitBorderRadius: str = None, webkitBorderTopLeftRadius: str = None, webkitBorderTopRightRadius: str = None, webkitBoxAlign: str = None, webkitBoxFlex: str = None, webkitBoxOrdinalGroup: str = None, webkitBoxOrient: str = None, webkitBoxPack: str = None, webkitBoxShadow: str = None, webkitBoxSizing: str = None, webkitFilter: str = None, webkitFlex: str = None, webkitFlexBasis: str = None, webkitFlexDirection: str = None, webkitFlexFlow: str = None, webkitFlexGrow: str = None, webkitFlexShrink: str = None, webkitFlexWrap: str = None, webkitJustifyContent: str = None, webkitLineClamp: str = None, webkitMask: str = None, webkitMaskBoxImage: str = None, webkitMaskBoxImageOutset: str = None, webkitMaskBoxImageRepeat: str = None, webkitMaskBoxImageSlice: str = None, webkitMaskBoxImageSource: str = None, webkitMaskBoxImageWidth: str = None, webkitMaskClip: str = None, webkitMaskComposite: str = None, webkitMaskImage: str = None, webkitMaskOrigin: str = None, webkitMaskPosition: str = None, webkitMaskRepeat: str = None, webkitMaskSize: str = None, webkitOrder: str = None, webkitPerspective: str = None, webkitPerspectiveOrigin: str = None, webkitTextFillColor: str = None, webkitTextSizeAdjust: str = None, webkitTextStroke: str = None, webkitTextStrokeColor: str = None, webkitTextStrokeWidth: str = None, webkitTransform: str = None, webkitTransformOrigin: str = None, webkitTransformStyle: str = None, webkitTransition: str = None, webkitTransitionDelay: str = None, webkitTransitionDuration: str = None, webkitTransitionProperty: str = None, webkitTransitionTimingFunction: str = None, webkitUserSelect: str = None, whiteSpace: str = None, whiteSpaceCollapse: str = None, widows: str = None, width: str = None, willChange: str = None, wordBreak: str = None, wordSpacing: str = None, wordWrap: str = None, writingMode: str = None, x: str = None, y: str = None, zIndex: str = None, zoom: str = None): + self.accentColor = accentColor + self.alignContent = alignContent + self.alignItems = alignItems + self.alignSelf = alignSelf + self.alignmentBaseline = alignmentBaseline + self.all = all + self.animation = animation + self.animationComposition = animationComposition + self.animationDelay = animationDelay + self.animationDirection = animationDirection + self.animationDuration = animationDuration + self.animationFillMode = animationFillMode + self.animationIterationCount = animationIterationCount + self.animationName = animationName + self.animationPlayState = animationPlayState + self.animationTimingFunction = animationTimingFunction + self.appearance = appearance + self.aspectRatio = aspectRatio + self.backdropFilter = backdropFilter + self.backfaceVisibility = backfaceVisibility + self.background = background + self.backgroundAttachment = backgroundAttachment + self.backgroundBlendMode = backgroundBlendMode + self.backgroundClip = backgroundClip + self.backgroundColor = backgroundColor + self.backgroundImage = backgroundImage + self.backgroundOrigin = backgroundOrigin + self.backgroundPosition = backgroundPosition + self.backgroundPositionX = backgroundPositionX + self.backgroundPositionY = backgroundPositionY + self.backgroundRepeat = backgroundRepeat + self.backgroundSize = backgroundSize + self.baselineShift = baselineShift + self.baselineSource = baselineSource + self.blockSize = blockSize + self.border = border + self.borderBlock = borderBlock + self.borderBlockColor = borderBlockColor + self.borderBlockEnd = borderBlockEnd + self.borderBlockEndColor = borderBlockEndColor + self.borderBlockEndStyle = borderBlockEndStyle + self.borderBlockEndWidth = borderBlockEndWidth + self.borderBlockStart = borderBlockStart + self.borderBlockStartColor = borderBlockStartColor + self.borderBlockStartStyle = borderBlockStartStyle + self.borderBlockStartWidth = borderBlockStartWidth + self.borderBlockStyle = borderBlockStyle + self.borderBlockWidth = borderBlockWidth + self.borderBottom = borderBottom + self.borderBottomColor = borderBottomColor + self.borderBottomLeftRadius = borderBottomLeftRadius + self.borderBottomRightRadius = borderBottomRightRadius + self.borderBottomStyle = borderBottomStyle + self.borderBottomWidth = borderBottomWidth + self.borderCollapse = borderCollapse + self.borderColor = borderColor + self.borderEndEndRadius = borderEndEndRadius + self.borderEndStartRadius = borderEndStartRadius + self.borderImage = borderImage + self.borderImageOutset = borderImageOutset + self.borderImageRepeat = borderImageRepeat + self.borderImageSlice = borderImageSlice + self.borderImageSource = borderImageSource + self.borderImageWidth = borderImageWidth + self.borderInline = borderInline + self.borderInlineColor = borderInlineColor + self.borderInlineEnd = borderInlineEnd + self.borderInlineEndColor = borderInlineEndColor + self.borderInlineEndStyle = borderInlineEndStyle + self.borderInlineEndWidth = borderInlineEndWidth + self.borderInlineStart = borderInlineStart + self.borderInlineStartColor = borderInlineStartColor + self.borderInlineStartStyle = borderInlineStartStyle + self.borderInlineStartWidth = borderInlineStartWidth + self.borderInlineStyle = borderInlineStyle + self.borderInlineWidth = borderInlineWidth + self.borderLeft = borderLeft + self.borderLeftColor = borderLeftColor + self.borderLeftStyle = borderLeftStyle + self.borderLeftWidth = borderLeftWidth + self.borderRadius = borderRadius + self.borderRight = borderRight + self.borderRightColor = borderRightColor + self.borderRightStyle = borderRightStyle + self.borderRightWidth = borderRightWidth + self.borderSpacing = borderSpacing + self.borderStartEndRadius = borderStartEndRadius + self.borderStartStartRadius = borderStartStartRadius + self.borderStyle = borderStyle + self.borderTop = borderTop + self.borderTopColor = borderTopColor + self.borderTopLeftRadius = borderTopLeftRadius + self.borderTopRightRadius = borderTopRightRadius + self.borderTopStyle = borderTopStyle + self.borderTopWidth = borderTopWidth + self.borderWidth = borderWidth + self.bottom = bottom + self.boxShadow = boxShadow + self.boxSizing = boxSizing + self.breakAfter = breakAfter + self.breakBefore = breakBefore + self.breakInside = breakInside + self.captionSide = captionSide + self.caretColor = caretColor + self.clear = clear + self.clip = clip + self.clipPath = clipPath + self.clipRule = clipRule + self.color = color + self.colorInterpolation = colorInterpolation + self.colorInterpolationFilters = colorInterpolationFilters + self.colorScheme = colorScheme + self.columnCount = columnCount + self.columnFill = columnFill + self.columnGap = columnGap + self.columnRule = columnRule + self.columnRuleColor = columnRuleColor + self.columnRuleStyle = columnRuleStyle + self.columnRuleWidth = columnRuleWidth + self.columnSpan = columnSpan + self.columnWidth = columnWidth + self.columns = columns + self.contain = contain + self.containIntrinsicBlockSize = containIntrinsicBlockSize + self.containIntrinsicHeight = containIntrinsicHeight + self.containIntrinsicInlineSize = containIntrinsicInlineSize + self.containIntrinsicSize = containIntrinsicSize + self.containIntrinsicWidth = containIntrinsicWidth + self.container = container + self.containerName = containerName + self.containerType = containerType + self.content = content + self.contentVisibility = contentVisibility + self.counterIncrement = counterIncrement + self.counterReset = counterReset + self.counterSet = counterSet + self.cssFloat = cssFloat + self.cssText = cssText + self.cursor = cursor + self.cx = cx + self.cy = cy + self.d = d + self.direction = direction + self.display = display + self.dominantBaseline = dominantBaseline + self.emptyCells = emptyCells + self.fill = fill + self.fillOpacity = fillOpacity + self.fillRule = fillRule + self.filter = filter + self.flex = flex + self.flexBasis = flexBasis + self.flexDirection = flexDirection + self.flexFlow = flexFlow + self.flexGrow = flexGrow + self.flexShrink = flexShrink + self.flexWrap = flexWrap + self.float = float + self.floodColor = floodColor + self.floodOpacity = floodOpacity + self.font = font + self.fontFamily = fontFamily + self.fontFeatureSettings = fontFeatureSettings + self.fontKerning = fontKerning + self.fontOpticalSizing = fontOpticalSizing + self.fontPalette = fontPalette + self.fontSize = fontSize + self.fontSizeAdjust = fontSizeAdjust + self.fontStretch = fontStretch + self.fontStyle = fontStyle + self.fontSynthesis = fontSynthesis + self.fontSynthesisSmallCaps = fontSynthesisSmallCaps + self.fontSynthesisStyle = fontSynthesisStyle + self.fontSynthesisWeight = fontSynthesisWeight + self.fontVariant = fontVariant + self.fontVariantAlternates = fontVariantAlternates + self.fontVariantCaps = fontVariantCaps + self.fontVariantEastAsian = fontVariantEastAsian + self.fontVariantLigatures = fontVariantLigatures + self.fontVariantNumeric = fontVariantNumeric + self.fontVariantPosition = fontVariantPosition + self.fontVariationSettings = fontVariationSettings + self.fontWeight = fontWeight + self.forcedColorAdjust = forcedColorAdjust + self.gap = gap + self.grid = grid + self.gridArea = gridArea + self.gridAutoColumns = gridAutoColumns + self.gridAutoFlow = gridAutoFlow + self.gridAutoRows = gridAutoRows + self.gridColumn = gridColumn + self.gridColumnEnd = gridColumnEnd + self.gridColumnGap = gridColumnGap + self.gridColumnStart = gridColumnStart + self.gridGap = gridGap + self.gridRow = gridRow + self.gridRowEnd = gridRowEnd + self.gridRowGap = gridRowGap + self.gridRowStart = gridRowStart + self.gridTemplate = gridTemplate + self.gridTemplateAreas = gridTemplateAreas + self.gridTemplateColumns = gridTemplateColumns + self.gridTemplateRows = gridTemplateRows + self.height = height + self.hyphenateCharacter = hyphenateCharacter + self.hyphens = hyphens + self.imageOrientation = imageOrientation + self.imageRendering = imageRendering + self.inlineSize = inlineSize + self.inset = inset + self.insetBlock = insetBlock + self.insetBlockEnd = insetBlockEnd + self.insetBlockStart = insetBlockStart + self.insetInline = insetInline + self.insetInlineEnd = insetInlineEnd + self.insetInlineStart = insetInlineStart + self.isolation = isolation + self.justifyContent = justifyContent + self.justifyItems = justifyItems + self.justifySelf = justifySelf + self.left = left + self.length = length + self.letterSpacing = letterSpacing + self.lightingColor = lightingColor + self.lineBreak = lineBreak + self.lineHeight = lineHeight + self.listStyle = listStyle + self.listStyleImage = listStyleImage + self.listStylePosition = listStylePosition + self.listStyleType = listStyleType + self.margin = margin + self.marginBlock = marginBlock + self.marginBlockEnd = marginBlockEnd + self.marginBlockStart = marginBlockStart + self.marginBottom = marginBottom + self.marginInline = marginInline + self.marginInlineEnd = marginInlineEnd + self.marginInlineStart = marginInlineStart + self.marginLeft = marginLeft + self.marginRight = marginRight + self.marginTop = marginTop + self.marker = marker + self.markerEnd = markerEnd + self.markerMid = markerMid + self.markerStart = markerStart + self.mask = mask + self.maskClip = maskClip + self.maskComposite = maskComposite + self.maskImage = maskImage + self.maskMode = maskMode + self.maskOrigin = maskOrigin + self.maskPosition = maskPosition + self.maskRepeat = maskRepeat + self.maskSize = maskSize + self.maskType = maskType + self.mathDepth = mathDepth + self.mathStyle = mathStyle + self.maxBlockSize = maxBlockSize + self.maxHeight = maxHeight + self.maxInlineSize = maxInlineSize + self.maxWidth = maxWidth + self.minBlockSize = minBlockSize + self.minHeight = minHeight + self.minInlineSize = minInlineSize + self.minWidth = minWidth + self.mixBlendMode = mixBlendMode + self.objectFit = objectFit + self.objectPosition = objectPosition + self.offset = offset + self.offsetAnchor = offsetAnchor + self.offsetDistance = offsetDistance + self.offsetPath = offsetPath + self.offsetPosition = offsetPosition + self.offsetRotate = offsetRotate + self.opacity = opacity + self.order = order + self.orphans = orphans + self.outline = outline + self.outlineColor = outlineColor + self.outlineOffset = outlineOffset + self.outlineStyle = outlineStyle + self.outlineWidth = outlineWidth + self.overflow = overflow + self.overflowAnchor = overflowAnchor + self.overflowClipMargin = overflowClipMargin + self.overflowWrap = overflowWrap + self.overflowX = overflowX + self.overflowY = overflowY + self.overscrollBehavior = overscrollBehavior + self.overscrollBehaviorBlock = overscrollBehaviorBlock + self.overscrollBehaviorInline = overscrollBehaviorInline + self.overscrollBehaviorX = overscrollBehaviorX + self.overscrollBehaviorY = overscrollBehaviorY + self.padding = padding + self.paddingBlock = paddingBlock + self.paddingBlockEnd = paddingBlockEnd + self.paddingBlockStart = paddingBlockStart + self.paddingBottom = paddingBottom + self.paddingInline = paddingInline + self.paddingInlineEnd = paddingInlineEnd + self.paddingInlineStart = paddingInlineStart + self.paddingLeft = paddingLeft + self.paddingRight = paddingRight + self.paddingTop = paddingTop + self.page = page + self.pageBreakAfter = pageBreakAfter + self.pageBreakBefore = pageBreakBefore + self.pageBreakInside = pageBreakInside + self.paintOrder = paintOrder + self.perspective = perspective + self.perspectiveOrigin = perspectiveOrigin + self.placeContent = placeContent + self.placeItems = placeItems + self.placeSelf = placeSelf + self.pointerEvents = pointerEvents + self.position = position + self.printColorAdjust = printColorAdjust + self.quotes = quotes + self.r = r + self.resize = resize + self.right = right + self.rotate = rotate + self.rowGap = rowGap + self.rubyPosition = rubyPosition + self.rx = rx + self.ry = ry + self.scale = scale + self.scrollBehavior = scrollBehavior + self.scrollMargin = scrollMargin + self.scrollMarginBlock = scrollMarginBlock + self.scrollMarginBlockEnd = scrollMarginBlockEnd + self.scrollMarginBlockStart = scrollMarginBlockStart + self.scrollMarginBottom = scrollMarginBottom + self.scrollMarginInline = scrollMarginInline + self.scrollMarginInlineEnd = scrollMarginInlineEnd + self.scrollMarginInlineStart = scrollMarginInlineStart + self.scrollMarginLeft = scrollMarginLeft + self.scrollMarginRight = scrollMarginRight + self.scrollMarginTop = scrollMarginTop + self.scrollPadding = scrollPadding + self.scrollPaddingBlock = scrollPaddingBlock + self.scrollPaddingBlockEnd = scrollPaddingBlockEnd + self.scrollPaddingBlockStart = scrollPaddingBlockStart + self.scrollPaddingBottom = scrollPaddingBottom + self.scrollPaddingInline = scrollPaddingInline + self.scrollPaddingInlineEnd = scrollPaddingInlineEnd + self.scrollPaddingInlineStart = scrollPaddingInlineStart + self.scrollPaddingLeft = scrollPaddingLeft + self.scrollPaddingRight = scrollPaddingRight + self.scrollPaddingTop = scrollPaddingTop + self.scrollSnapAlign = scrollSnapAlign + self.scrollSnapStop = scrollSnapStop + self.scrollSnapType = scrollSnapType + self.scrollbarColor = scrollbarColor + self.scrollbarGutter = scrollbarGutter + self.scrollbarWidth = scrollbarWidth + self.shapeImageThreshold = shapeImageThreshold + self.shapeMargin = shapeMargin + self.shapeOutside = shapeOutside + self.shapeRendering = shapeRendering + self.stopColor = stopColor + self.stopOpacity = stopOpacity + self.stroke = stroke + self.strokeDasharray = strokeDasharray + self.strokeDashoffset = strokeDashoffset + self.strokeLinecap = strokeLinecap + self.strokeLinejoin = strokeLinejoin + self.strokeMiterlimit = strokeMiterlimit + self.strokeOpacity = strokeOpacity + self.strokeWidth = strokeWidth + self.tabSize = tabSize + self.tableLayout = tableLayout + self.textAlign = textAlign + self.textAlignLast = textAlignLast + self.textAnchor = textAnchor + self.textCombineUpright = textCombineUpright + self.textDecoration = textDecoration + self.textDecorationColor = textDecorationColor + self.textDecorationLine = textDecorationLine + self.textDecorationSkipInk = textDecorationSkipInk + self.textDecorationStyle = textDecorationStyle + self.textDecorationThickness = textDecorationThickness + self.textEmphasis = textEmphasis + self.textEmphasisColor = textEmphasisColor + self.textEmphasisPosition = textEmphasisPosition + self.textEmphasisStyle = textEmphasisStyle + self.textIndent = textIndent + self.textOrientation = textOrientation + self.textOverflow = textOverflow + self.textRendering = textRendering + self.textShadow = textShadow + self.textTransform = textTransform + self.textUnderlineOffset = textUnderlineOffset + self.textUnderlinePosition = textUnderlinePosition + self.textWrap = textWrap + self.textWrapMode = textWrapMode + self.textWrapStyle = textWrapStyle + self.top = top + self.touchAction = touchAction + self.transform = transform + self.transformBox = transformBox + self.transformOrigin = transformOrigin + self.transformStyle = transformStyle + self.transition = transition + self.transitionBehavior = transitionBehavior + self.transitionDelay = transitionDelay + self.transitionDuration = transitionDuration + self.transitionProperty = transitionProperty + self.transitionTimingFunction = transitionTimingFunction + self.translate = translate + self.unicodeBidi = unicodeBidi + self.userSelect = userSelect + self.vectorEffect = vectorEffect + self.verticalAlign = verticalAlign + self.visibility = visibility + self.webkitAlignContent = webkitAlignContent + self.webkitAlignItems = webkitAlignItems + self.webkitAlignSelf = webkitAlignSelf + self.webkitAnimation = webkitAnimation + self.webkitAnimationDelay = webkitAnimationDelay + self.webkitAnimationDirection = webkitAnimationDirection + self.webkitAnimationDuration = webkitAnimationDuration + self.webkitAnimationFillMode = webkitAnimationFillMode + self.webkitAnimationIterationCount = webkitAnimationIterationCount + self.webkitAnimationName = webkitAnimationName + self.webkitAnimationPlayState = webkitAnimationPlayState + self.webkitAnimationTimingFunction = webkitAnimationTimingFunction + self.webkitAppearance = webkitAppearance + self.webkitBackfaceVisibility = webkitBackfaceVisibility + self.webkitBackgroundClip = webkitBackgroundClip + self.webkitBackgroundOrigin = webkitBackgroundOrigin + self.webkitBackgroundSize = webkitBackgroundSize + self.webkitBorderBottomLeftRadius = webkitBorderBottomLeftRadius + self.webkitBorderBottomRightRadius = webkitBorderBottomRightRadius + self.webkitBorderRadius = webkitBorderRadius + self.webkitBorderTopLeftRadius = webkitBorderTopLeftRadius + self.webkitBorderTopRightRadius = webkitBorderTopRightRadius + self.webkitBoxAlign = webkitBoxAlign + self.webkitBoxFlex = webkitBoxFlex + self.webkitBoxOrdinalGroup = webkitBoxOrdinalGroup + self.webkitBoxOrient = webkitBoxOrient + self.webkitBoxPack = webkitBoxPack + self.webkitBoxShadow = webkitBoxShadow + self.webkitBoxSizing = webkitBoxSizing + self.webkitFilter = webkitFilter + self.webkitFlex = webkitFlex + self.webkitFlexBasis = webkitFlexBasis + self.webkitFlexDirection = webkitFlexDirection + self.webkitFlexFlow = webkitFlexFlow + self.webkitFlexGrow = webkitFlexGrow + self.webkitFlexShrink = webkitFlexShrink + self.webkitFlexWrap = webkitFlexWrap + self.webkitJustifyContent = webkitJustifyContent + self.webkitLineClamp = webkitLineClamp + self.webkitMask = webkitMask + self.webkitMaskBoxImage = webkitMaskBoxImage + self.webkitMaskBoxImageOutset = webkitMaskBoxImageOutset + self.webkitMaskBoxImageRepeat = webkitMaskBoxImageRepeat + self.webkitMaskBoxImageSlice = webkitMaskBoxImageSlice + self.webkitMaskBoxImageSource = webkitMaskBoxImageSource + self.webkitMaskBoxImageWidth = webkitMaskBoxImageWidth + self.webkitMaskClip = webkitMaskClip + self.webkitMaskComposite = webkitMaskComposite + self.webkitMaskImage = webkitMaskImage + self.webkitMaskOrigin = webkitMaskOrigin + self.webkitMaskPosition = webkitMaskPosition + self.webkitMaskRepeat = webkitMaskRepeat + self.webkitMaskSize = webkitMaskSize + self.webkitOrder = webkitOrder + self.webkitPerspective = webkitPerspective + self.webkitPerspectiveOrigin = webkitPerspectiveOrigin + self.webkitTextFillColor = webkitTextFillColor + self.webkitTextSizeAdjust = webkitTextSizeAdjust + self.webkitTextStroke = webkitTextStroke + self.webkitTextStrokeColor = webkitTextStrokeColor + self.webkitTextStrokeWidth = webkitTextStrokeWidth + self.webkitTransform = webkitTransform + self.webkitTransformOrigin = webkitTransformOrigin + self.webkitTransformStyle = webkitTransformStyle + self.webkitTransition = webkitTransition + self.webkitTransitionDelay = webkitTransitionDelay + self.webkitTransitionDuration = webkitTransitionDuration + self.webkitTransitionProperty = webkitTransitionProperty + self.webkitTransitionTimingFunction = webkitTransitionTimingFunction + self.webkitUserSelect = webkitUserSelect + self.whiteSpace = whiteSpace + self.whiteSpaceCollapse = whiteSpaceCollapse + self.widows = widows + self.width = width + self.willChange = willChange + self.wordBreak = wordBreak + self.wordSpacing = wordSpacing + self.wordWrap = wordWrap + self.writingMode = writingMode + self.x = x + self.y = y + self.zIndex = zIndex + self.zoom = zoom + + +class Centroid: + def __init__(self, centroid: Union[Union[str, float, bool], List[Union[str, float, bool]]]): + self.centroid = centroid + + +class CentroidX: + def __init__(self, centroidX: Union[Union[str, float, bool], List[Union[str, float, bool]]]): + self.centroidX = centroidX + + +class CentroidY: + def __init__(self, centroidY: Union[Union[str, float, bool], List[Union[str, float, bool]]]): + self.centroidY = centroidY + + +class ChannelDomainValueSpec: + def __init__(self, value: Union["ChannelDomainValue", Dict[str, Any]]): + self.value = value + + +class ChannelDomainValue: + def __init__(self, value: Union[str, Union[str, "ChannelName"], Any]): + self.value = value + + +class ChannelName: + def __init__(self): + pass + + +class ColorScaleType: + def __init__(self): + pass + + +class ColorScheme: + def __init__(self, value: Union[str, Dict[str, Any]]): + self.value = value + + +class ColumnTransform: + def __init__(self, value: Union["Centroid", "GeoJSON", "CentroidY", "DateDay", "DateMonth", "Bin", "DateMonthDay", "CentroidX"]): + self.value = value + + +class Component: + def __init__(self, value: Union["Search", "HSpace", "VSpace", "HConcat", "PlotMark", "Plot", "VConcat", "Slider", "Table", "Legend", "Menu"]): + self.value = value + + +class Config: + def __init__(self, extensions: Union[str, List[str]] = None): + self.extensions = extensions + + +class ContinuousScaleType: + def __init__(self): + pass + + +class Count: + def __init__(self, count: Union[Any, Union[Union[str, float, bool], List[Union[str, float, bool]]]], distinct: bool = None, orderby: Union["TransformField", List["TransformField"]] = None, partitionby: Union["TransformField", List["TransformField"]] = None, range: Union[List[Union[float, Any]], "ParamRef"] = None, rows: Union[List[Union[float, Any]], "ParamRef"] = None): + self.count = count + self.distinct = distinct + self.orderby = orderby + self.partitionby = partitionby + self.range = range + self.rows = rows + + +class CumeDist: + def __init__(self, cume_dist: Union[Any, Any], orderby: Union["TransformField", List["TransformField"]] = None, partitionby: Union["TransformField", List["TransformField"]] = None, range: Union[List[Union[float, Any]], "ParamRef"] = None, rows: Union[List[Union[float, Any]], "ParamRef"] = None): + self.cume_dist = cume_dist + self.orderby = orderby + self.partitionby = partitionby + self.range = range + self.rows = rows + + +class CurveName: + def __init__(self): + pass + + +class DataDefinition: + def __init__(self, value: Union["DataFile", "DataSpatial", "DataArray", "DataJSONObjects", "DataTable", "DataJSON", "DataCSV", "DataParquet", "DataQuery"]): + self.value = value + + +class DataArray: + def __init__(self): + pass + + +class DataCSV: + def __init__(self, file: str, type: str, delimiter: str = None, replace: bool = None, sample_size: float = None, select: List[str] = None, temp: bool = None, view: bool = None, where: Union[str, List[str]] = None): + self.delimiter = delimiter + self.file = file + self.replace = replace + self.sample_size = sample_size + self.select = select + self.temp = temp + self.type = type + self.view = view + self.where = where + + +class DataFile: + def __init__(self, file: str, replace: bool = None, select: List[str] = None, temp: bool = None, view: bool = None, where: Union[str, List[str]] = None): + self.file = file + self.replace = replace + self.select = select + self.temp = temp + self.view = view + self.where = where + + +class DataJSON: + def __init__(self, file: str, type: str, replace: bool = None, select: List[str] = None, temp: bool = None, view: bool = None, where: Union[str, List[str]] = None): + self.file = file + self.replace = replace + self.select = select + self.temp = temp + self.type = type + self.view = view + self.where = where + + +class DataJSONObjects: + def __init__(self, data: List[Dict[str, Any]], replace: bool = None, select: List[str] = None, temp: bool = None, type: str = None, view: bool = None, where: Union[str, List[str]] = None): + self.data = data + self.replace = replace + self.select = select + self.temp = temp + self.type = type + self.view = view + self.where = where + + +class DataParquet: + def __init__(self, file: str, type: str, replace: bool = None, select: List[str] = None, temp: bool = None, view: bool = None, where: Union[str, List[str]] = None): + self.file = file + self.replace = replace + self.select = select + self.temp = temp + self.type = type + self.view = view + self.where = where + + +class DataQuery: + def __init__(self): + pass + + +class DataSpatial: + def __init__(self, file: str, type: str, layer: str = None, replace: bool = None, select: List[str] = None, temp: bool = None, view: bool = None, where: Union[str, List[str]] = None): + self.file = file + self.layer = layer + self.replace = replace + self.select = select + self.temp = temp + self.type = type + self.view = view + self.where = where + + +class DataTable: + def __init__(self, query: str, type: str, replace: bool = None, select: List[str] = None, temp: bool = None, view: bool = None, where: Union[str, List[str]] = None): + self.query = query + self.replace = replace + self.select = select + self.temp = temp + self.type = type + self.view = view + self.where = where + + +class DateDay: + def __init__(self, dateDay: Union[Union[str, float, bool], List[Union[str, float, bool]]]): + self.dateDay = dateDay + + +class DateMonth: + def __init__(self, dateMonth: Union[Union[str, float, bool], List[Union[str, float, bool]]]): + self.dateMonth = dateMonth + + +class DateMonthDay: + def __init__(self, dateMonthDay: Union[Union[str, float, bool], List[Union[str, float, bool]]]): + self.dateMonthDay = dateMonthDay + + +class DenseRank: + def __init__(self, dense_rank: Union[Any, Any], orderby: Union["TransformField", List["TransformField"]] = None, partitionby: Union["TransformField", List["TransformField"]] = None, range: Union[List[Union[float, Any]], "ParamRef"] = None, rows: Union[List[Union[float, Any]], "ParamRef"] = None): + self.dense_rank = dense_rank + self.orderby = orderby + self.partitionby = partitionby + self.range = range + self.rows = rows + + +class DensityX: + def __init__(self, value: Dict[str, Any]): + self.value = value + + +class DensityY: + def __init__(self, value: Dict[str, Any]): + self.value = value + + +class DiscreteScaleType: + def __init__(self): + pass + + +class First: + def __init__(self, first: Union[Union[str, float, bool], List[Union[str, float, bool]]], distinct: bool = None, orderby: Union["TransformField", List["TransformField"]] = None, partitionby: Union["TransformField", List["TransformField"]] = None, range: Union[List[Union[float, Any]], "ParamRef"] = None, rows: Union[List[Union[float, Any]], "ParamRef"] = None): + self.distinct = distinct + self.first = first + self.orderby = orderby + self.partitionby = partitionby + self.range = range + self.rows = rows + + +class FirstValue: + def __init__(self, first_value: Union[Union[str, float, bool], List[Union[str, float, bool]]], orderby: Union["TransformField", List["TransformField"]] = None, partitionby: Union["TransformField", List["TransformField"]] = None, range: Union[List[Union[float, Any]], "ParamRef"] = None, rows: Union[List[Union[float, Any]], "ParamRef"] = None): + self.first_value = first_value + self.orderby = orderby + self.partitionby = partitionby + self.range = range + self.rows = rows + + +class Fixed: + def __init__(self): + pass + + +class FrameAnchor: + def __init__(self): + pass + + +class GeoJSON: + def __init__(self, geojson: Union[Union[str, float, bool], List[Union[str, float, bool]]]): + self.geojson = geojson + + +class GridInterpolate: + def __init__(self): + pass + + +class HSpace: + def __init__(self, hspace: Union[float, str]): + self.hspace = hspace + + +class ParamRef: + def __init__(self): + pass + + +class Interpolate: + def __init__(self): + pass + + +class LiteralTimeInterval: + def __init__(self, value: Union[str, "TimeIntervalName"]): + self.value = value + + +class LabelArrow: + def __init__(self): + pass + + +class Lag: + def __init__(self, lag: Union[Union[str, float, bool], List[Union[str, float, bool]]], orderby: Union["TransformField", List["TransformField"]] = None, partitionby: Union["TransformField", List["TransformField"]] = None, range: Union[List[Union[float, Any]], "ParamRef"] = None, rows: Union[List[Union[float, Any]], "ParamRef"] = None): + self.lag = lag + self.orderby = orderby + self.partitionby = partitionby + self.range = range + self.rows = rows + + +class Last: + def __init__(self, last: Union[Union[str, float, bool], List[Union[str, float, bool]]], distinct: bool = None, orderby: Union["TransformField", List["TransformField"]] = None, partitionby: Union["TransformField", List["TransformField"]] = None, range: Union[List[Union[float, Any]], "ParamRef"] = None, rows: Union[List[Union[float, Any]], "ParamRef"] = None): + self.distinct = distinct + self.last = last + self.orderby = orderby + self.partitionby = partitionby + self.range = range + self.rows = rows + + +class LastValue: + def __init__(self, last_value: Union[Union[str, float, bool], List[Union[str, float, bool]]], orderby: Union["TransformField", List["TransformField"]] = None, partitionby: Union["TransformField", List["TransformField"]] = None, range: Union[List[Union[float, Any]], "ParamRef"] = None, rows: Union[List[Union[float, Any]], "ParamRef"] = None): + self.last_value = last_value + self.orderby = orderby + self.partitionby = partitionby + self.range = range + self.rows = rows + + +class Lead: + def __init__(self, lag: Union[Union[str, float, bool], List[Union[str, float, bool]]], orderby: Union["TransformField", List["TransformField"]] = None, partitionby: Union["TransformField", List["TransformField"]] = None, range: Union[List[Union[float, Any]], "ParamRef"] = None, rows: Union[List[Union[float, Any]], "ParamRef"] = None): + self.lag = lag + self.orderby = orderby + self.partitionby = partitionby + self.range = range + self.rows = rows + + +class MarkerName: + def __init__(self): + pass + + +class Max: + def __init__(self, max: Union[Union[str, float, bool], List[Union[str, float, bool]]], distinct: bool = None, orderby: Union["TransformField", List["TransformField"]] = None, partitionby: Union["TransformField", List["TransformField"]] = None, range: Union[List[Union[float, Any]], "ParamRef"] = None, rows: Union[List[Union[float, Any]], "ParamRef"] = None): + self.distinct = distinct + self.max = max + self.orderby = orderby + self.partitionby = partitionby + self.range = range + self.rows = rows + + +class Median: + def __init__(self, median: Union[Union[str, float, bool], List[Union[str, float, bool]]], distinct: bool = None, orderby: Union["TransformField", List["TransformField"]] = None, partitionby: Union["TransformField", List["TransformField"]] = None, range: Union[List[Union[float, Any]], "ParamRef"] = None, rows: Union[List[Union[float, Any]], "ParamRef"] = None): + self.distinct = distinct + self.median = median + self.orderby = orderby + self.partitionby = partitionby + self.range = range + self.rows = rows + + +class Meta: + def __init__(self, credit: str = None, description: str = None, title: str = None): + self.credit = credit + self.description = description + self.title = title + + +class Min: + def __init__(self, min: Union[Union[str, float, bool], List[Union[str, float, bool]]], distinct: bool = None, orderby: Union["TransformField", List["TransformField"]] = None, partitionby: Union["TransformField", List["TransformField"]] = None, range: Union[List[Union[float, Any]], "ParamRef"] = None, rows: Union[List[Union[float, Any]], "ParamRef"] = None): + self.distinct = distinct + self.min = min + self.orderby = orderby + self.partitionby = partitionby + self.range = range + self.rows = rows + + +class Mode: + def __init__(self, mode: Union[Union[str, float, bool], List[Union[str, float, bool]]], distinct: bool = None, orderby: Union["TransformField", List["TransformField"]] = None, partitionby: Union["TransformField", List["TransformField"]] = None, range: Union[List[Union[float, Any]], "ParamRef"] = None, rows: Union[List[Union[float, Any]], "ParamRef"] = None): + self.distinct = distinct + self.mode = mode + self.orderby = orderby + self.partitionby = partitionby + self.range = range + self.rows = rows + + +class NTile: + def __init__(self, ntile: Union[Union[str, float, bool], List[Union[str, float, bool]]], orderby: Union["TransformField", List["TransformField"]] = None, partitionby: Union["TransformField", List["TransformField"]] = None, range: Union[List[Union[float, Any]], "ParamRef"] = None, rows: Union[List[Union[float, Any]], "ParamRef"] = None): + self.ntile = ntile + self.orderby = orderby + self.partitionby = partitionby + self.range = range + self.rows = rows + + +class NthValue: + def __init__(self, nth_value: Union[Union[str, float, bool], List[Union[str, float, bool]]], orderby: Union["TransformField", List["TransformField"]] = None, partitionby: Union["TransformField", List["TransformField"]] = None, range: Union[List[Union[float, Any]], "ParamRef"] = None, rows: Union[List[Union[float, Any]], "ParamRef"] = None): + self.nth_value = nth_value + self.orderby = orderby + self.partitionby = partitionby + self.range = range + self.rows = rows + + +class ParamValue: + def __init__(self, value: Union["ParamLiteral", List[Union["ParamLiteral", "ParamRef"]]]): + self.value = value + + +class ParamDate: + def __init__(self, date: str, select: str = None): + self.date = date + self.select = select + + +class ParamDefinition: + def __init__(self, value: Union["ParamDate", "Param", "ParamValue", "Selection"]): + self.value = value + + +class ParamLiteral: + def __init__(self): + pass + + +class PercentRank: + def __init__(self, percent_rank: Union[Any, Any], orderby: Union["TransformField", List["TransformField"]] = None, partitionby: Union["TransformField", List["TransformField"]] = None, range: Union[List[Union[float, Any]], "ParamRef"] = None, rows: Union[List[Union[float, Any]], "ParamRef"] = None): + self.orderby = orderby + self.partitionby = partitionby + self.percent_rank = percent_rank + self.range = range + self.rows = rows + + +class Plot: + def __init__(self, plot: List[Union["PlotInteractor", "PlotLegend", "PlotMark"]], align: Union[float, "ParamRef"] = None, aspectRatio: Union[float, bool, Any, "ParamRef"] = None, axis: Union[str, str, str, str, str, bool, Any, "ParamRef"] = None, colorBase: Union[float, "ParamRef"] = None, colorClamp: Union[bool, "ParamRef"] = None, colorConstant: Union[float, "ParamRef"] = None, colorDomain: Union[List[Any], "Fixed", "ParamRef"] = None, colorExponent: Union[float, "ParamRef"] = None, colorInterpolate: Union["Interpolate", "ParamRef"] = None, colorLabel: Union[str, Any, "ParamRef"] = None, colorN: Union[float, "ParamRef"] = None, colorNice: Union[bool, float, "Interval", "ParamRef"] = None, colorPercent: Union[bool, "ParamRef"] = None, colorPivot: Union[Any, "ParamRef"] = None, colorRange: Union[List[Any], "Fixed", "ParamRef"] = None, colorReverse: Union[bool, "ParamRef"] = None, colorScale: Union["ColorScaleType", Any, "ParamRef"] = None, colorScheme: Union["ColorScheme", "ParamRef"] = None, colorSymmetric: Union[bool, "ParamRef"] = None, colorTickFormat: Union[str, Any, "ParamRef"] = None, colorZero: Union[bool, "ParamRef"] = None, facetGrid: Union[bool, str, "Interval", List[Any], "ParamRef"] = None, facetLabel: Union[str, Any, "ParamRef"] = None, facetMargin: Union[float, "ParamRef"] = None, facetMarginBottom: Union[float, "ParamRef"] = None, facetMarginLeft: Union[float, "ParamRef"] = None, facetMarginRight: Union[float, "ParamRef"] = None, facetMarginTop: Union[float, "ParamRef"] = None, fxAlign: Union[float, "ParamRef"] = None, fxAriaDescription: Union[str, "ParamRef"] = None, fxAriaLabel: Union[str, "ParamRef"] = None, fxAxis: Union[str, str, str, bool, Any, "ParamRef"] = None, fxDomain: Union[List[Any], "Fixed", "ParamRef"] = None, fxFontVariant: Union[str, "ParamRef"] = None, fxGrid: Union[bool, str, "Interval", List[Any], "ParamRef"] = None, fxInset: Union[float, "ParamRef"] = None, fxInsetLeft: Union[float, "ParamRef"] = None, fxInsetRight: Union[float, "ParamRef"] = None, fxLabel: Union[str, Any, "ParamRef"] = None, fxLabelAnchor: Union[str, str, str, str, str, "ParamRef"] = None, fxLabelOffset: Union[float, "ParamRef"] = None, fxLine: Union[bool, "ParamRef"] = None, fxPadding: Union[float, "ParamRef"] = None, fxPaddingInner: Union[float, "ParamRef"] = None, fxPaddingOuter: Union[float, "ParamRef"] = None, fxRange: Union[List[Any], "Fixed", "ParamRef"] = None, fxReverse: Union[bool, "ParamRef"] = None, fxRound: Union[bool, "ParamRef"] = None, fxTickFormat: Union[str, Any, "ParamRef"] = None, fxTickPadding: Union[float, "ParamRef"] = None, fxTickRotate: Union[float, "ParamRef"] = None, fxTickSize: Union[float, "ParamRef"] = None, fxTickSpacing: Union[float, "ParamRef"] = None, fxTicks: Union[float, "Interval", List[Any], "ParamRef"] = None, fyAlign: Union[float, "ParamRef"] = None, fyAriaDescription: Union[str, "ParamRef"] = None, fyAriaLabel: Union[str, "ParamRef"] = None, fyAxis: Union[str, str, str, bool, Any, "ParamRef"] = None, fyDomain: Union[List[Any], "Fixed", "ParamRef"] = None, fyFontVariant: Union[str, "ParamRef"] = None, fyGrid: Union[bool, str, "Interval", List[Any], "ParamRef"] = None, fyInset: Union[float, "ParamRef"] = None, fyInsetBottom: Union[float, "ParamRef"] = None, fyInsetTop: Union[float, "ParamRef"] = None, fyLabel: Union[str, Any, "ParamRef"] = None, fyLabelAnchor: Union[str, str, str, str, str, "ParamRef"] = None, fyLabelOffset: Union[float, "ParamRef"] = None, fyLine: Union[bool, "ParamRef"] = None, fyPadding: Union[float, "ParamRef"] = None, fyPaddingInner: Union[float, "ParamRef"] = None, fyPaddingOuter: Union[float, "ParamRef"] = None, fyRange: Union[List[Any], "Fixed", "ParamRef"] = None, fyReverse: Union[bool, "ParamRef"] = None, fyRound: Union[bool, "ParamRef"] = None, fyTickFormat: Union[str, Any, "ParamRef"] = None, fyTickPadding: Union[float, "ParamRef"] = None, fyTickRotate: Union[float, "ParamRef"] = None, fyTickSize: Union[float, "ParamRef"] = None, fyTickSpacing: Union[float, "ParamRef"] = None, fyTicks: Union[float, "Interval", List[Any], "ParamRef"] = None, grid: Union[bool, str, "ParamRef"] = None, height: Union[float, "ParamRef"] = None, inset: Union[float, "ParamRef"] = None, label: Union[str, Any, "ParamRef"] = None, lengthBase: Union[float, "ParamRef"] = None, lengthClamp: Any = None, lengthConstant: Union[float, "ParamRef"] = None, lengthDomain: Union[List[Any], "Fixed", "ParamRef"] = None, lengthExponent: Union[float, "ParamRef"] = None, lengthNice: Union[bool, float, "Interval", "ParamRef"] = None, lengthPercent: Union[bool, "ParamRef"] = None, lengthRange: Union[List[Any], "Fixed", "ParamRef"] = None, lengthScale: Union["ContinuousScaleType", Any, "ParamRef"] = None, lengthZero: Union[bool, "ParamRef"] = None, margin: Union[float, "ParamRef"] = None, marginBottom: Union[float, "ParamRef"] = None, marginLeft: Union[float, "ParamRef"] = None, marginRight: Union[float, "ParamRef"] = None, marginTop: Union[float, "ParamRef"] = None, margins: Dict[str, Any] = None, name: str = None, opacityBase: Union[float, "ParamRef"] = None, opacityClamp: Union[bool, "ParamRef"] = None, opacityConstant: Union[float, "ParamRef"] = None, opacityDomain: Union[List[Any], "Fixed", "ParamRef"] = None, opacityExponent: Union[float, "ParamRef"] = None, opacityLabel: Union[str, Any, "ParamRef"] = None, opacityNice: Union[bool, float, "Interval", "ParamRef"] = None, opacityPercent: Union[bool, "ParamRef"] = None, opacityRange: Union[List[Any], "Fixed", "ParamRef"] = None, opacityReverse: Union[bool, "ParamRef"] = None, opacityScale: Union["ContinuousScaleType", Any, "ParamRef"] = None, opacityTickFormat: Union[str, Any, "ParamRef"] = None, opacityZero: Union[bool, "ParamRef"] = None, padding: Union[float, "ParamRef"] = None, projectionClip: Union[bool, float, str, Any, "ParamRef"] = None, projectionDomain: Union[Dict[str, Any], "ParamRef"] = None, projectionInset: Union[float, "ParamRef"] = None, projectionInsetBottom: Union[float, "ParamRef"] = None, projectionInsetLeft: Union[float, "ParamRef"] = None, projectionInsetRight: Union[float, "ParamRef"] = None, projectionInsetTop: Union[float, "ParamRef"] = None, projectionParallels: Union[List[Any], "ParamRef"] = None, projectionPrecision: Union[float, "ParamRef"] = None, projectionRotate: Union[List[Any], "ParamRef"] = None, projectionType: Union["ProjectionName", Any, "ParamRef"] = None, rBase: Union[float, "ParamRef"] = None, rClamp: Any = None, rConstant: Union[float, "ParamRef"] = None, rDomain: Union[List[Any], "Fixed", "ParamRef"] = None, rExponent: Union[float, "ParamRef"] = None, rLabel: Union[str, Any, "ParamRef"] = None, rNice: Union[bool, float, "Interval", "ParamRef"] = None, rPercent: Union[bool, "ParamRef"] = None, rRange: Union[List[Any], "Fixed", "ParamRef"] = None, rScale: Union["ContinuousScaleType", Any, "ParamRef"] = None, rZero: Union[bool, "ParamRef"] = None, style: Union[str, "CSSStyles", Any, "ParamRef"] = None, symbolDomain: Union[List[Any], "Fixed", "ParamRef"] = None, symbolRange: Union[List[Any], "Fixed", "ParamRef"] = None, symbolScale: Union["DiscreteScaleType", Any, "ParamRef"] = None, width: Union[float, "ParamRef"] = None, xAlign: Union[float, "ParamRef"] = None, xAriaDescription: Union[str, "ParamRef"] = None, xAriaLabel: Union[str, "ParamRef"] = None, xAxis: Union[str, str, str, bool, Any, "ParamRef"] = None, xBase: Union[float, "ParamRef"] = None, xClamp: Union[bool, "ParamRef"] = None, xConstant: Union[float, "ParamRef"] = None, xDomain: Union[List[Any], "Fixed", "ParamRef"] = None, xExponent: Union[float, "ParamRef"] = None, xFontVariant: Union[str, "ParamRef"] = None, xGrid: Union[bool, str, "Interval", List[Any], "ParamRef"] = None, xInset: Union[float, "ParamRef"] = None, xInsetLeft: Union[float, "ParamRef"] = None, xInsetRight: Union[float, "ParamRef"] = None, xLabel: Union[str, Any, "ParamRef"] = None, xLabelAnchor: Union[str, str, str, str, str, "ParamRef"] = None, xLabelArrow: Union["LabelArrow", "ParamRef"] = None, xLabelOffset: Union[float, "ParamRef"] = None, xLine: Union[bool, "ParamRef"] = None, xNice: Union[bool, float, "Interval", "ParamRef"] = None, xPadding: Union[float, "ParamRef"] = None, xPaddingInner: Union[float, "ParamRef"] = None, xPaddingOuter: Union[float, "ParamRef"] = None, xPercent: Union[bool, "ParamRef"] = None, xRange: Union[List[Any], "Fixed", "ParamRef"] = None, xReverse: Union[bool, "ParamRef"] = None, xRound: Union[bool, "ParamRef"] = None, xScale: Union["PositionScaleType", Any, "ParamRef"] = None, xTickFormat: Union[str, Any, "ParamRef"] = None, xTickPadding: Union[float, "ParamRef"] = None, xTickRotate: Union[float, "ParamRef"] = None, xTickSize: Union[float, "ParamRef"] = None, xTickSpacing: Union[float, "ParamRef"] = None, xTicks: Union[float, "Interval", List[Any], "ParamRef"] = None, xZero: Union[bool, "ParamRef"] = None, xyDomain: Union[List[Any], "Fixed", "ParamRef"] = None, yAlign: Union[float, "ParamRef"] = None, yAriaDescription: Union[str, "ParamRef"] = None, yAriaLabel: Union[str, "ParamRef"] = None, yAxis: Union[str, str, str, bool, Any, "ParamRef"] = None, yBase: Union[float, "ParamRef"] = None, yClamp: Union[bool, "ParamRef"] = None, yConstant: Union[float, "ParamRef"] = None, yDomain: Union[List[Any], "Fixed", "ParamRef"] = None, yExponent: Union[float, "ParamRef"] = None, yFontVariant: Union[str, "ParamRef"] = None, yGrid: Union[bool, str, "Interval", List[Any], "ParamRef"] = None, yInset: Union[float, "ParamRef"] = None, yInsetBottom: Union[float, "ParamRef"] = None, yInsetTop: Union[float, "ParamRef"] = None, yLabel: Union[str, Any, "ParamRef"] = None, yLabelAnchor: Union[str, str, str, str, str, "ParamRef"] = None, yLabelArrow: Union["LabelArrow", "ParamRef"] = None, yLabelOffset: Union[float, "ParamRef"] = None, yLine: Union[bool, "ParamRef"] = None, yNice: Union[bool, float, "Interval", "ParamRef"] = None, yPadding: Union[float, "ParamRef"] = None, yPaddingInner: Union[float, "ParamRef"] = None, yPaddingOuter: Union[float, "ParamRef"] = None, yPercent: Union[bool, "ParamRef"] = None, yRange: Union[List[Any], "Fixed", "ParamRef"] = None, yReverse: Union[bool, "ParamRef"] = None, yRound: Union[bool, "ParamRef"] = None, yScale: Union["PositionScaleType", Any, "ParamRef"] = None, yTickFormat: Union[str, Any, "ParamRef"] = None, yTickPadding: Union[float, "ParamRef"] = None, yTickRotate: Union[float, "ParamRef"] = None, yTickSize: Union[float, "ParamRef"] = None, yTickSpacing: Union[float, "ParamRef"] = None, yTicks: Union[float, "Interval", List[Any], "ParamRef"] = None, yZero: Union[bool, "ParamRef"] = None): + self.align = align + self.aspectRatio = aspectRatio + self.axis = axis + self.colorBase = colorBase + self.colorClamp = colorClamp + self.colorConstant = colorConstant + self.colorDomain = colorDomain + self.colorExponent = colorExponent + self.colorInterpolate = colorInterpolate + self.colorLabel = colorLabel + self.colorN = colorN + self.colorNice = colorNice + self.colorPercent = colorPercent + self.colorPivot = colorPivot + self.colorRange = colorRange + self.colorReverse = colorReverse + self.colorScale = colorScale + self.colorScheme = colorScheme + self.colorSymmetric = colorSymmetric + self.colorTickFormat = colorTickFormat + self.colorZero = colorZero + self.facetGrid = facetGrid + self.facetLabel = facetLabel + self.facetMargin = facetMargin + self.facetMarginBottom = facetMarginBottom + self.facetMarginLeft = facetMarginLeft + self.facetMarginRight = facetMarginRight + self.facetMarginTop = facetMarginTop + self.fxAlign = fxAlign + self.fxAriaDescription = fxAriaDescription + self.fxAriaLabel = fxAriaLabel + self.fxAxis = fxAxis + self.fxDomain = fxDomain + self.fxFontVariant = fxFontVariant + self.fxGrid = fxGrid + self.fxInset = fxInset + self.fxInsetLeft = fxInsetLeft + self.fxInsetRight = fxInsetRight + self.fxLabel = fxLabel + self.fxLabelAnchor = fxLabelAnchor + self.fxLabelOffset = fxLabelOffset + self.fxLine = fxLine + self.fxPadding = fxPadding + self.fxPaddingInner = fxPaddingInner + self.fxPaddingOuter = fxPaddingOuter + self.fxRange = fxRange + self.fxReverse = fxReverse + self.fxRound = fxRound + self.fxTickFormat = fxTickFormat + self.fxTickPadding = fxTickPadding + self.fxTickRotate = fxTickRotate + self.fxTickSize = fxTickSize + self.fxTickSpacing = fxTickSpacing + self.fxTicks = fxTicks + self.fyAlign = fyAlign + self.fyAriaDescription = fyAriaDescription + self.fyAriaLabel = fyAriaLabel + self.fyAxis = fyAxis + self.fyDomain = fyDomain + self.fyFontVariant = fyFontVariant + self.fyGrid = fyGrid + self.fyInset = fyInset + self.fyInsetBottom = fyInsetBottom + self.fyInsetTop = fyInsetTop + self.fyLabel = fyLabel + self.fyLabelAnchor = fyLabelAnchor + self.fyLabelOffset = fyLabelOffset + self.fyLine = fyLine + self.fyPadding = fyPadding + self.fyPaddingInner = fyPaddingInner + self.fyPaddingOuter = fyPaddingOuter + self.fyRange = fyRange + self.fyReverse = fyReverse + self.fyRound = fyRound + self.fyTickFormat = fyTickFormat + self.fyTickPadding = fyTickPadding + self.fyTickRotate = fyTickRotate + self.fyTickSize = fyTickSize + self.fyTickSpacing = fyTickSpacing + self.fyTicks = fyTicks + self.grid = grid + self.height = height + self.inset = inset + self.label = label + self.lengthBase = lengthBase + self.lengthClamp = lengthClamp + self.lengthConstant = lengthConstant + self.lengthDomain = lengthDomain + self.lengthExponent = lengthExponent + self.lengthNice = lengthNice + self.lengthPercent = lengthPercent + self.lengthRange = lengthRange + self.lengthScale = lengthScale + self.lengthZero = lengthZero + self.margin = margin + self.marginBottom = marginBottom + self.marginLeft = marginLeft + self.marginRight = marginRight + self.marginTop = marginTop + self.margins = margins + self.name = name + self.opacityBase = opacityBase + self.opacityClamp = opacityClamp + self.opacityConstant = opacityConstant + self.opacityDomain = opacityDomain + self.opacityExponent = opacityExponent + self.opacityLabel = opacityLabel + self.opacityNice = opacityNice + self.opacityPercent = opacityPercent + self.opacityRange = opacityRange + self.opacityReverse = opacityReverse + self.opacityScale = opacityScale + self.opacityTickFormat = opacityTickFormat + self.opacityZero = opacityZero + self.padding = padding + self.plot = plot + self.projectionClip = projectionClip + self.projectionDomain = projectionDomain + self.projectionInset = projectionInset + self.projectionInsetBottom = projectionInsetBottom + self.projectionInsetLeft = projectionInsetLeft + self.projectionInsetRight = projectionInsetRight + self.projectionInsetTop = projectionInsetTop + self.projectionParallels = projectionParallels + self.projectionPrecision = projectionPrecision + self.projectionRotate = projectionRotate + self.projectionType = projectionType + self.rBase = rBase + self.rClamp = rClamp + self.rConstant = rConstant + self.rDomain = rDomain + self.rExponent = rExponent + self.rLabel = rLabel + self.rNice = rNice + self.rPercent = rPercent + self.rRange = rRange + self.rScale = rScale + self.rZero = rZero + self.style = style + self.symbolDomain = symbolDomain + self.symbolRange = symbolRange + self.symbolScale = symbolScale + self.width = width + self.xAlign = xAlign + self.xAriaDescription = xAriaDescription + self.xAriaLabel = xAriaLabel + self.xAxis = xAxis + self.xBase = xBase + self.xClamp = xClamp + self.xConstant = xConstant + self.xDomain = xDomain + self.xExponent = xExponent + self.xFontVariant = xFontVariant + self.xGrid = xGrid + self.xInset = xInset + self.xInsetLeft = xInsetLeft + self.xInsetRight = xInsetRight + self.xLabel = xLabel + self.xLabelAnchor = xLabelAnchor + self.xLabelArrow = xLabelArrow + self.xLabelOffset = xLabelOffset + self.xLine = xLine + self.xNice = xNice + self.xPadding = xPadding + self.xPaddingInner = xPaddingInner + self.xPaddingOuter = xPaddingOuter + self.xPercent = xPercent + self.xRange = xRange + self.xReverse = xReverse + self.xRound = xRound + self.xScale = xScale + self.xTickFormat = xTickFormat + self.xTickPadding = xTickPadding + self.xTickRotate = xTickRotate + self.xTickSize = xTickSize + self.xTickSpacing = xTickSpacing + self.xTicks = xTicks + self.xZero = xZero + self.xyDomain = xyDomain + self.yAlign = yAlign + self.yAriaDescription = yAriaDescription + self.yAriaLabel = yAriaLabel + self.yAxis = yAxis + self.yBase = yBase + self.yClamp = yClamp + self.yConstant = yConstant + self.yDomain = yDomain + self.yExponent = yExponent + self.yFontVariant = yFontVariant + self.yGrid = yGrid + self.yInset = yInset + self.yInsetBottom = yInsetBottom + self.yInsetTop = yInsetTop + self.yLabel = yLabel + self.yLabelAnchor = yLabelAnchor + self.yLabelArrow = yLabelArrow + self.yLabelOffset = yLabelOffset + self.yLine = yLine + self.yNice = yNice + self.yPadding = yPadding + self.yPaddingInner = yPaddingInner + self.yPaddingOuter = yPaddingOuter + self.yPercent = yPercent + self.yRange = yRange + self.yReverse = yReverse + self.yRound = yRound + self.yScale = yScale + self.yTickFormat = yTickFormat + self.yTickPadding = yTickPadding + self.yTickRotate = yTickRotate + self.yTickSize = yTickSize + self.yTickSpacing = yTickSpacing + self.yTicks = yTicks + self.yZero = yZero + + +class PlotAttributes: + def __init__(self, align: Union[float, "ParamRef"] = None, aspectRatio: Union[float, bool, Any, "ParamRef"] = None, axis: Union[str, str, str, str, str, bool, Any, "ParamRef"] = None, colorBase: Union[float, "ParamRef"] = None, colorClamp: Union[bool, "ParamRef"] = None, colorConstant: Union[float, "ParamRef"] = None, colorDomain: Union[List[Any], "Fixed", "ParamRef"] = None, colorExponent: Union[float, "ParamRef"] = None, colorInterpolate: Union["Interpolate", "ParamRef"] = None, colorLabel: Union[str, Any, "ParamRef"] = None, colorN: Union[float, "ParamRef"] = None, colorNice: Union[bool, float, "Interval", "ParamRef"] = None, colorPercent: Union[bool, "ParamRef"] = None, colorPivot: Union[Any, "ParamRef"] = None, colorRange: Union[List[Any], "Fixed", "ParamRef"] = None, colorReverse: Union[bool, "ParamRef"] = None, colorScale: Union["ColorScaleType", Any, "ParamRef"] = None, colorScheme: Union["ColorScheme", "ParamRef"] = None, colorSymmetric: Union[bool, "ParamRef"] = None, colorTickFormat: Union[str, Any, "ParamRef"] = None, colorZero: Union[bool, "ParamRef"] = None, facetGrid: Union[bool, str, "Interval", List[Any], "ParamRef"] = None, facetLabel: Union[str, Any, "ParamRef"] = None, facetMargin: Union[float, "ParamRef"] = None, facetMarginBottom: Union[float, "ParamRef"] = None, facetMarginLeft: Union[float, "ParamRef"] = None, facetMarginRight: Union[float, "ParamRef"] = None, facetMarginTop: Union[float, "ParamRef"] = None, fxAlign: Union[float, "ParamRef"] = None, fxAriaDescription: Union[str, "ParamRef"] = None, fxAriaLabel: Union[str, "ParamRef"] = None, fxAxis: Union[str, str, str, bool, Any, "ParamRef"] = None, fxDomain: Union[List[Any], "Fixed", "ParamRef"] = None, fxFontVariant: Union[str, "ParamRef"] = None, fxGrid: Union[bool, str, "Interval", List[Any], "ParamRef"] = None, fxInset: Union[float, "ParamRef"] = None, fxInsetLeft: Union[float, "ParamRef"] = None, fxInsetRight: Union[float, "ParamRef"] = None, fxLabel: Union[str, Any, "ParamRef"] = None, fxLabelAnchor: Union[str, str, str, str, str, "ParamRef"] = None, fxLabelOffset: Union[float, "ParamRef"] = None, fxLine: Union[bool, "ParamRef"] = None, fxPadding: Union[float, "ParamRef"] = None, fxPaddingInner: Union[float, "ParamRef"] = None, fxPaddingOuter: Union[float, "ParamRef"] = None, fxRange: Union[List[Any], "Fixed", "ParamRef"] = None, fxReverse: Union[bool, "ParamRef"] = None, fxRound: Union[bool, "ParamRef"] = None, fxTickFormat: Union[str, Any, "ParamRef"] = None, fxTickPadding: Union[float, "ParamRef"] = None, fxTickRotate: Union[float, "ParamRef"] = None, fxTickSize: Union[float, "ParamRef"] = None, fxTickSpacing: Union[float, "ParamRef"] = None, fxTicks: Union[float, "Interval", List[Any], "ParamRef"] = None, fyAlign: Union[float, "ParamRef"] = None, fyAriaDescription: Union[str, "ParamRef"] = None, fyAriaLabel: Union[str, "ParamRef"] = None, fyAxis: Union[str, str, str, bool, Any, "ParamRef"] = None, fyDomain: Union[List[Any], "Fixed", "ParamRef"] = None, fyFontVariant: Union[str, "ParamRef"] = None, fyGrid: Union[bool, str, "Interval", List[Any], "ParamRef"] = None, fyInset: Union[float, "ParamRef"] = None, fyInsetBottom: Union[float, "ParamRef"] = None, fyInsetTop: Union[float, "ParamRef"] = None, fyLabel: Union[str, Any, "ParamRef"] = None, fyLabelAnchor: Union[str, str, str, str, str, "ParamRef"] = None, fyLabelOffset: Union[float, "ParamRef"] = None, fyLine: Union[bool, "ParamRef"] = None, fyPadding: Union[float, "ParamRef"] = None, fyPaddingInner: Union[float, "ParamRef"] = None, fyPaddingOuter: Union[float, "ParamRef"] = None, fyRange: Union[List[Any], "Fixed", "ParamRef"] = None, fyReverse: Union[bool, "ParamRef"] = None, fyRound: Union[bool, "ParamRef"] = None, fyTickFormat: Union[str, Any, "ParamRef"] = None, fyTickPadding: Union[float, "ParamRef"] = None, fyTickRotate: Union[float, "ParamRef"] = None, fyTickSize: Union[float, "ParamRef"] = None, fyTickSpacing: Union[float, "ParamRef"] = None, fyTicks: Union[float, "Interval", List[Any], "ParamRef"] = None, grid: Union[bool, str, "ParamRef"] = None, height: Union[float, "ParamRef"] = None, inset: Union[float, "ParamRef"] = None, label: Union[str, Any, "ParamRef"] = None, lengthBase: Union[float, "ParamRef"] = None, lengthClamp: Any = None, lengthConstant: Union[float, "ParamRef"] = None, lengthDomain: Union[List[Any], "Fixed", "ParamRef"] = None, lengthExponent: Union[float, "ParamRef"] = None, lengthNice: Union[bool, float, "Interval", "ParamRef"] = None, lengthPercent: Union[bool, "ParamRef"] = None, lengthRange: Union[List[Any], "Fixed", "ParamRef"] = None, lengthScale: Union["ContinuousScaleType", Any, "ParamRef"] = None, lengthZero: Union[bool, "ParamRef"] = None, margin: Union[float, "ParamRef"] = None, marginBottom: Union[float, "ParamRef"] = None, marginLeft: Union[float, "ParamRef"] = None, marginRight: Union[float, "ParamRef"] = None, marginTop: Union[float, "ParamRef"] = None, margins: Dict[str, Any] = None, name: str = None, opacityBase: Union[float, "ParamRef"] = None, opacityClamp: Union[bool, "ParamRef"] = None, opacityConstant: Union[float, "ParamRef"] = None, opacityDomain: Union[List[Any], "Fixed", "ParamRef"] = None, opacityExponent: Union[float, "ParamRef"] = None, opacityLabel: Union[str, Any, "ParamRef"] = None, opacityNice: Union[bool, float, "Interval", "ParamRef"] = None, opacityPercent: Union[bool, "ParamRef"] = None, opacityRange: Union[List[Any], "Fixed", "ParamRef"] = None, opacityReverse: Union[bool, "ParamRef"] = None, opacityScale: Union["ContinuousScaleType", Any, "ParamRef"] = None, opacityTickFormat: Union[str, Any, "ParamRef"] = None, opacityZero: Union[bool, "ParamRef"] = None, padding: Union[float, "ParamRef"] = None, projectionClip: Union[bool, float, str, Any, "ParamRef"] = None, projectionDomain: Union[Dict[str, Any], "ParamRef"] = None, projectionInset: Union[float, "ParamRef"] = None, projectionInsetBottom: Union[float, "ParamRef"] = None, projectionInsetLeft: Union[float, "ParamRef"] = None, projectionInsetRight: Union[float, "ParamRef"] = None, projectionInsetTop: Union[float, "ParamRef"] = None, projectionParallels: Union[List[Any], "ParamRef"] = None, projectionPrecision: Union[float, "ParamRef"] = None, projectionRotate: Union[List[Any], "ParamRef"] = None, projectionType: Union["ProjectionName", Any, "ParamRef"] = None, rBase: Union[float, "ParamRef"] = None, rClamp: Any = None, rConstant: Union[float, "ParamRef"] = None, rDomain: Union[List[Any], "Fixed", "ParamRef"] = None, rExponent: Union[float, "ParamRef"] = None, rLabel: Union[str, Any, "ParamRef"] = None, rNice: Union[bool, float, "Interval", "ParamRef"] = None, rPercent: Union[bool, "ParamRef"] = None, rRange: Union[List[Any], "Fixed", "ParamRef"] = None, rScale: Union["ContinuousScaleType", Any, "ParamRef"] = None, rZero: Union[bool, "ParamRef"] = None, style: Union[str, "CSSStyles", Any, "ParamRef"] = None, symbolDomain: Union[List[Any], "Fixed", "ParamRef"] = None, symbolRange: Union[List[Any], "Fixed", "ParamRef"] = None, symbolScale: Union["DiscreteScaleType", Any, "ParamRef"] = None, width: Union[float, "ParamRef"] = None, xAlign: Union[float, "ParamRef"] = None, xAriaDescription: Union[str, "ParamRef"] = None, xAriaLabel: Union[str, "ParamRef"] = None, xAxis: Union[str, str, str, bool, Any, "ParamRef"] = None, xBase: Union[float, "ParamRef"] = None, xClamp: Union[bool, "ParamRef"] = None, xConstant: Union[float, "ParamRef"] = None, xDomain: Union[List[Any], "Fixed", "ParamRef"] = None, xExponent: Union[float, "ParamRef"] = None, xFontVariant: Union[str, "ParamRef"] = None, xGrid: Union[bool, str, "Interval", List[Any], "ParamRef"] = None, xInset: Union[float, "ParamRef"] = None, xInsetLeft: Union[float, "ParamRef"] = None, xInsetRight: Union[float, "ParamRef"] = None, xLabel: Union[str, Any, "ParamRef"] = None, xLabelAnchor: Union[str, str, str, str, str, "ParamRef"] = None, xLabelArrow: Union["LabelArrow", "ParamRef"] = None, xLabelOffset: Union[float, "ParamRef"] = None, xLine: Union[bool, "ParamRef"] = None, xNice: Union[bool, float, "Interval", "ParamRef"] = None, xPadding: Union[float, "ParamRef"] = None, xPaddingInner: Union[float, "ParamRef"] = None, xPaddingOuter: Union[float, "ParamRef"] = None, xPercent: Union[bool, "ParamRef"] = None, xRange: Union[List[Any], "Fixed", "ParamRef"] = None, xReverse: Union[bool, "ParamRef"] = None, xRound: Union[bool, "ParamRef"] = None, xScale: Union["PositionScaleType", Any, "ParamRef"] = None, xTickFormat: Union[str, Any, "ParamRef"] = None, xTickPadding: Union[float, "ParamRef"] = None, xTickRotate: Union[float, "ParamRef"] = None, xTickSize: Union[float, "ParamRef"] = None, xTickSpacing: Union[float, "ParamRef"] = None, xTicks: Union[float, "Interval", List[Any], "ParamRef"] = None, xZero: Union[bool, "ParamRef"] = None, xyDomain: Union[List[Any], "Fixed", "ParamRef"] = None, yAlign: Union[float, "ParamRef"] = None, yAriaDescription: Union[str, "ParamRef"] = None, yAriaLabel: Union[str, "ParamRef"] = None, yAxis: Union[str, str, str, bool, Any, "ParamRef"] = None, yBase: Union[float, "ParamRef"] = None, yClamp: Union[bool, "ParamRef"] = None, yConstant: Union[float, "ParamRef"] = None, yDomain: Union[List[Any], "Fixed", "ParamRef"] = None, yExponent: Union[float, "ParamRef"] = None, yFontVariant: Union[str, "ParamRef"] = None, yGrid: Union[bool, str, "Interval", List[Any], "ParamRef"] = None, yInset: Union[float, "ParamRef"] = None, yInsetBottom: Union[float, "ParamRef"] = None, yInsetTop: Union[float, "ParamRef"] = None, yLabel: Union[str, Any, "ParamRef"] = None, yLabelAnchor: Union[str, str, str, str, str, "ParamRef"] = None, yLabelArrow: Union["LabelArrow", "ParamRef"] = None, yLabelOffset: Union[float, "ParamRef"] = None, yLine: Union[bool, "ParamRef"] = None, yNice: Union[bool, float, "Interval", "ParamRef"] = None, yPadding: Union[float, "ParamRef"] = None, yPaddingInner: Union[float, "ParamRef"] = None, yPaddingOuter: Union[float, "ParamRef"] = None, yPercent: Union[bool, "ParamRef"] = None, yRange: Union[List[Any], "Fixed", "ParamRef"] = None, yReverse: Union[bool, "ParamRef"] = None, yRound: Union[bool, "ParamRef"] = None, yScale: Union["PositionScaleType", Any, "ParamRef"] = None, yTickFormat: Union[str, Any, "ParamRef"] = None, yTickPadding: Union[float, "ParamRef"] = None, yTickRotate: Union[float, "ParamRef"] = None, yTickSize: Union[float, "ParamRef"] = None, yTickSpacing: Union[float, "ParamRef"] = None, yTicks: Union[float, "Interval", List[Any], "ParamRef"] = None, yZero: Union[bool, "ParamRef"] = None): + self.align = align + self.aspectRatio = aspectRatio + self.axis = axis + self.colorBase = colorBase + self.colorClamp = colorClamp + self.colorConstant = colorConstant + self.colorDomain = colorDomain + self.colorExponent = colorExponent + self.colorInterpolate = colorInterpolate + self.colorLabel = colorLabel + self.colorN = colorN + self.colorNice = colorNice + self.colorPercent = colorPercent + self.colorPivot = colorPivot + self.colorRange = colorRange + self.colorReverse = colorReverse + self.colorScale = colorScale + self.colorScheme = colorScheme + self.colorSymmetric = colorSymmetric + self.colorTickFormat = colorTickFormat + self.colorZero = colorZero + self.facetGrid = facetGrid + self.facetLabel = facetLabel + self.facetMargin = facetMargin + self.facetMarginBottom = facetMarginBottom + self.facetMarginLeft = facetMarginLeft + self.facetMarginRight = facetMarginRight + self.facetMarginTop = facetMarginTop + self.fxAlign = fxAlign + self.fxAriaDescription = fxAriaDescription + self.fxAriaLabel = fxAriaLabel + self.fxAxis = fxAxis + self.fxDomain = fxDomain + self.fxFontVariant = fxFontVariant + self.fxGrid = fxGrid + self.fxInset = fxInset + self.fxInsetLeft = fxInsetLeft + self.fxInsetRight = fxInsetRight + self.fxLabel = fxLabel + self.fxLabelAnchor = fxLabelAnchor + self.fxLabelOffset = fxLabelOffset + self.fxLine = fxLine + self.fxPadding = fxPadding + self.fxPaddingInner = fxPaddingInner + self.fxPaddingOuter = fxPaddingOuter + self.fxRange = fxRange + self.fxReverse = fxReverse + self.fxRound = fxRound + self.fxTickFormat = fxTickFormat + self.fxTickPadding = fxTickPadding + self.fxTickRotate = fxTickRotate + self.fxTickSize = fxTickSize + self.fxTickSpacing = fxTickSpacing + self.fxTicks = fxTicks + self.fyAlign = fyAlign + self.fyAriaDescription = fyAriaDescription + self.fyAriaLabel = fyAriaLabel + self.fyAxis = fyAxis + self.fyDomain = fyDomain + self.fyFontVariant = fyFontVariant + self.fyGrid = fyGrid + self.fyInset = fyInset + self.fyInsetBottom = fyInsetBottom + self.fyInsetTop = fyInsetTop + self.fyLabel = fyLabel + self.fyLabelAnchor = fyLabelAnchor + self.fyLabelOffset = fyLabelOffset + self.fyLine = fyLine + self.fyPadding = fyPadding + self.fyPaddingInner = fyPaddingInner + self.fyPaddingOuter = fyPaddingOuter + self.fyRange = fyRange + self.fyReverse = fyReverse + self.fyRound = fyRound + self.fyTickFormat = fyTickFormat + self.fyTickPadding = fyTickPadding + self.fyTickRotate = fyTickRotate + self.fyTickSize = fyTickSize + self.fyTickSpacing = fyTickSpacing + self.fyTicks = fyTicks + self.grid = grid + self.height = height + self.inset = inset + self.label = label + self.lengthBase = lengthBase + self.lengthClamp = lengthClamp + self.lengthConstant = lengthConstant + self.lengthDomain = lengthDomain + self.lengthExponent = lengthExponent + self.lengthNice = lengthNice + self.lengthPercent = lengthPercent + self.lengthRange = lengthRange + self.lengthScale = lengthScale + self.lengthZero = lengthZero + self.margin = margin + self.marginBottom = marginBottom + self.marginLeft = marginLeft + self.marginRight = marginRight + self.marginTop = marginTop + self.margins = margins + self.name = name + self.opacityBase = opacityBase + self.opacityClamp = opacityClamp + self.opacityConstant = opacityConstant + self.opacityDomain = opacityDomain + self.opacityExponent = opacityExponent + self.opacityLabel = opacityLabel + self.opacityNice = opacityNice + self.opacityPercent = opacityPercent + self.opacityRange = opacityRange + self.opacityReverse = opacityReverse + self.opacityScale = opacityScale + self.opacityTickFormat = opacityTickFormat + self.opacityZero = opacityZero + self.padding = padding + self.projectionClip = projectionClip + self.projectionDomain = projectionDomain + self.projectionInset = projectionInset + self.projectionInsetBottom = projectionInsetBottom + self.projectionInsetLeft = projectionInsetLeft + self.projectionInsetRight = projectionInsetRight + self.projectionInsetTop = projectionInsetTop + self.projectionParallels = projectionParallels + self.projectionPrecision = projectionPrecision + self.projectionRotate = projectionRotate + self.projectionType = projectionType + self.rBase = rBase + self.rClamp = rClamp + self.rConstant = rConstant + self.rDomain = rDomain + self.rExponent = rExponent + self.rLabel = rLabel + self.rNice = rNice + self.rPercent = rPercent + self.rRange = rRange + self.rScale = rScale + self.rZero = rZero + self.style = style + self.symbolDomain = symbolDomain + self.symbolRange = symbolRange + self.symbolScale = symbolScale + self.width = width + self.xAlign = xAlign + self.xAriaDescription = xAriaDescription + self.xAriaLabel = xAriaLabel + self.xAxis = xAxis + self.xBase = xBase + self.xClamp = xClamp + self.xConstant = xConstant + self.xDomain = xDomain + self.xExponent = xExponent + self.xFontVariant = xFontVariant + self.xGrid = xGrid + self.xInset = xInset + self.xInsetLeft = xInsetLeft + self.xInsetRight = xInsetRight + self.xLabel = xLabel + self.xLabelAnchor = xLabelAnchor + self.xLabelArrow = xLabelArrow + self.xLabelOffset = xLabelOffset + self.xLine = xLine + self.xNice = xNice + self.xPadding = xPadding + self.xPaddingInner = xPaddingInner + self.xPaddingOuter = xPaddingOuter + self.xPercent = xPercent + self.xRange = xRange + self.xReverse = xReverse + self.xRound = xRound + self.xScale = xScale + self.xTickFormat = xTickFormat + self.xTickPadding = xTickPadding + self.xTickRotate = xTickRotate + self.xTickSize = xTickSize + self.xTickSpacing = xTickSpacing + self.xTicks = xTicks + self.xZero = xZero + self.xyDomain = xyDomain + self.yAlign = yAlign + self.yAriaDescription = yAriaDescription + self.yAriaLabel = yAriaLabel + self.yAxis = yAxis + self.yBase = yBase + self.yClamp = yClamp + self.yConstant = yConstant + self.yDomain = yDomain + self.yExponent = yExponent + self.yFontVariant = yFontVariant + self.yGrid = yGrid + self.yInset = yInset + self.yInsetBottom = yInsetBottom + self.yInsetTop = yInsetTop + self.yLabel = yLabel + self.yLabelAnchor = yLabelAnchor + self.yLabelArrow = yLabelArrow + self.yLabelOffset = yLabelOffset + self.yLine = yLine + self.yNice = yNice + self.yPadding = yPadding + self.yPaddingInner = yPaddingInner + self.yPaddingOuter = yPaddingOuter + self.yPercent = yPercent + self.yRange = yRange + self.yReverse = yReverse + self.yRound = yRound + self.yScale = yScale + self.yTickFormat = yTickFormat + self.yTickPadding = yTickPadding + self.yTickRotate = yTickRotate + self.yTickSize = yTickSize + self.yTickSpacing = yTickSpacing + self.yTicks = yTicks + self.yZero = yZero + + +class PlotDataInline: + def __init__(self): + pass + + +class PlotInteractor: + def __init__(self, value: Union["PanZoomX", "IntervalX", "ToggleColor", "PanY", "ToggleX", "Toggle", "NearestY", "ToggleY", "PanZoom", "IntervalY", "PanZoomY", "PanX", "NearestX", "Pan", "IntervalXY", "Highlight"]): + self.value = value + + +class PlotMark: + def __init__(self, value: Union["Circle", "DelaunayMesh", "Dot", "ErrorBarY", "GridFy", "Arrow", "Contour", "Hexbin", "Spike", "RegressionY", "Sphere", "RuleX", "Geo", "DensityY", "GridX", "AxisFy", "AxisY", "Graticule", "BarY", "DotX", "RectX", "TickX", "RuleY", "Cell", "RasterTile", "CellX", "Voronoi", "TickY", "GridY", "DensityX", "Frame", "AxisFx", "Density", "RectY", "VectorY", "AreaX", "AxisX", "TextX", "TextY", "Vector", "Image", "Rect", "Text", "Area", "LineX", "VoronoiMesh", "DelaunayLink", "Link", "VectorX", "DenseLine", "LineY", "CellY", "DotY", "BarX", "GridFx", "Line", "Hexgrid", "Raster", "AreaY", "Hull", "ErrorBarX", "Heatmap", "Hexagon"]): + self.value = value + + +class PositionScaleType: + def __init__(self): + pass + + +class Product: + def __init__(self, product: Union[Union[str, float, bool], List[Union[str, float, bool]]], distinct: bool = None, orderby: Union["TransformField", List["TransformField"]] = None, partitionby: Union["TransformField", List["TransformField"]] = None, range: Union[List[Union[float, Any]], "ParamRef"] = None, rows: Union[List[Union[float, Any]], "ParamRef"] = None): + self.distinct = distinct + self.orderby = orderby + self.partitionby = partitionby + self.product = product + self.range = range + self.rows = rows + + +class ProjectionName: + def __init__(self): + pass + + +class Quantile: + def __init__(self, quantile: List[Union[str, float, bool]], distinct: bool = None, orderby: Union["TransformField", List["TransformField"]] = None, partitionby: Union["TransformField", List["TransformField"]] = None, range: Union[List[Union[float, Any]], "ParamRef"] = None, rows: Union[List[Union[float, Any]], "ParamRef"] = None): + self.distinct = distinct + self.orderby = orderby + self.partitionby = partitionby + self.quantile = quantile + self.range = range + self.rows = rows + + +class Rank: + def __init__(self, rank: Union[Any, Any], orderby: Union["TransformField", List["TransformField"]] = None, partitionby: Union["TransformField", List["TransformField"]] = None, range: Union[List[Union[float, Any]], "ParamRef"] = None, rows: Union[List[Union[float, Any]], "ParamRef"] = None): + self.orderby = orderby + self.partitionby = partitionby + self.range = range + self.rank = rank + self.rows = rows + + +class Reducer: + def __init__(self, value: Union[str, "ReducerPercentile"]): + self.value = value + + +class ReducerPercentile: + def __init__(self): + pass + + +class RowNumber: + def __init__(self, row_number: Union[Any, Any], orderby: Union["TransformField", List["TransformField"]] = None, partitionby: Union["TransformField", List["TransformField"]] = None, range: Union[List[Union[float, Any]], "ParamRef"] = None, rows: Union[List[Union[float, Any]], "ParamRef"] = None): + self.orderby = orderby + self.partitionby = partitionby + self.range = range + self.row_number = row_number + self.rows = rows + + +class SQLExpression: + def __init__(self, sql: str, label: str = None): + self.label = label + self.sql = sql + + +class ScaleName: + def __init__(self): + pass + + +class Selection: + def __init__(self, select: str, cross: bool = None, empty: bool = None): + self.cross = cross + self.empty = empty + self.select = select + + +class SortOrder: + def __init__(self, value: Union[Dict[str, Any], "ChannelValue"]): + self.value = value + + +class Spec: + def __init__(self, value: Dict[str, Any]): + self.value = value + + +class StackOffsetName: + def __init__(self): + pass + + +class StackOrder: + def __init__(self, value: Union[str, List[Any], "StackOrderName"]): + self.value = value + + +class StackOrderName: + def __init__(self): + pass + + +class Stddev: + def __init__(self, stddev: Union[Union[str, float, bool], List[Union[str, float, bool]]], distinct: bool = None, orderby: Union["TransformField", List["TransformField"]] = None, partitionby: Union["TransformField", List["TransformField"]] = None, range: Union[List[Union[float, Any]], "ParamRef"] = None, rows: Union[List[Union[float, Any]], "ParamRef"] = None): + self.distinct = distinct + self.orderby = orderby + self.partitionby = partitionby + self.range = range + self.rows = rows + self.stddev = stddev + + +class StddevPop: + def __init__(self, stddevPop: Union[Union[str, float, bool], List[Union[str, float, bool]]], distinct: bool = None, orderby: Union["TransformField", List["TransformField"]] = None, partitionby: Union["TransformField", List["TransformField"]] = None, range: Union[List[Union[float, Any]], "ParamRef"] = None, rows: Union[List[Union[float, Any]], "ParamRef"] = None): + self.distinct = distinct + self.orderby = orderby + self.partitionby = partitionby + self.range = range + self.rows = rows + self.stddevPop = stddevPop + + +class Sum: + def __init__(self, sum: Union[Union[str, float, bool], List[Union[str, float, bool]]], distinct: bool = None, orderby: Union["TransformField", List["TransformField"]] = None, partitionby: Union["TransformField", List["TransformField"]] = None, range: Union[List[Union[float, Any]], "ParamRef"] = None, rows: Union[List[Union[float, Any]], "ParamRef"] = None): + self.distinct = distinct + self.orderby = orderby + self.partitionby = partitionby + self.range = range + self.rows = rows + self.sum = sum + + +class SymbolType: + def __init__(self): + pass + + +class TimeIntervalName: + def __init__(self): + pass + + +class TipPointer: + def __init__(self): + pass + + +class Transform: + def __init__(self, value: Union["WindowTransform", "AggregateTransform", "ColumnTransform"]): + self.value = value + + +class TransformField: + def __init__(self, value: Union[str, "ParamRef"]): + self.value = value + + +class VSpace: + def __init__(self, vspace: Union[float, str]): + self.vspace = vspace + + +class VarPop: + def __init__(self, varPop: Union[Union[str, float, bool], List[Union[str, float, bool]]], distinct: bool = None, orderby: Union["TransformField", List["TransformField"]] = None, partitionby: Union["TransformField", List["TransformField"]] = None, range: Union[List[Union[float, Any]], "ParamRef"] = None, rows: Union[List[Union[float, Any]], "ParamRef"] = None): + self.distinct = distinct + self.orderby = orderby + self.partitionby = partitionby + self.range = range + self.rows = rows + self.varPop = varPop + + +class Variance: + def __init__(self, variance: Union[Union[str, float, bool], List[Union[str, float, bool]]], distinct: bool = None, orderby: Union["TransformField", List["TransformField"]] = None, partitionby: Union["TransformField", List["TransformField"]] = None, range: Union[List[Union[float, Any]], "ParamRef"] = None, rows: Union[List[Union[float, Any]], "ParamRef"] = None): + self.distinct = distinct + self.orderby = orderby + self.partitionby = partitionby + self.range = range + self.rows = rows + self.variance = variance + + +class VectorShapeName: + def __init__(self): + pass + + +class WindowTransform: + def __init__(self, value: Union["NTile", "DenseRank", "Lead", "LastValue", "FirstValue", "Lag", "CumeDist", "Rank", "NthValue", "RowNumber", "PercentRank"]): + self.value = value + + +class Area: + def __init__(self, data: "PlotMarkData", mark: str, ariaDescription: Union[str, "ParamRef"] = None, ariaHidden: Union[str, "ParamRef"] = None, ariaLabel: "ChannelValue" = None, clip: Union[str, str, bool, Any, "ParamRef"] = None, curve: Union["Curve", "ParamRef"] = None, dx: Union[float, "ParamRef"] = None, dy: Union[float, "ParamRef"] = None, facet: Union[str, str, str, str, bool, Any, "ParamRef"] = None, facetAnchor: Union[str, str, str, str, str, str, str, str, str, str, str, str, str, Any, "ParamRef"] = None, fill: Union["ChannelValueSpec", "ParamRef"] = None, fillOpacity: Union["ChannelValueSpec", "ParamRef"] = None, filter: "ChannelValue" = None, fx: "ChannelValue" = None, fy: "ChannelValue" = None, href: "ChannelValue" = None, imageFilter: Union[str, "ParamRef"] = None, margin: Union[float, "ParamRef"] = None, marginBottom: Union[float, "ParamRef"] = None, marginLeft: Union[float, "ParamRef"] = None, marginRight: Union[float, "ParamRef"] = None, marginTop: Union[float, "ParamRef"] = None, mixBlendMode: Union[str, "ParamRef"] = None, offset: Union["StackOffset", Any, "ParamRef"] = None, opacity: "ChannelValueSpec" = None, order: Union["StackOrder", Any, "ParamRef"] = None, paintOrder: Union[str, "ParamRef"] = None, pointerEvents: Union[str, "ParamRef"] = None, reverse: Union[bool, "ParamRef"] = None, select: "SelectFilter" = None, shapeRendering: Union[str, "ParamRef"] = None, sort: Union["SortOrder", "ChannelDomainSort"] = None, stroke: Union["ChannelValueSpec", "ParamRef"] = None, strokeDasharray: Union[str, float, "ParamRef"] = None, strokeDashoffset: Union[str, float, "ParamRef"] = None, strokeLinecap: Union[str, "ParamRef"] = None, strokeLinejoin: Union[str, "ParamRef"] = None, strokeMiterlimit: Union[float, "ParamRef"] = None, strokeOpacity: "ChannelValueSpec" = None, strokeWidth: "ChannelValueSpec" = None, target: Union[str, "ParamRef"] = None, tension: Union[float, "ParamRef"] = None, tip: Union[bool, "TipPointer", Dict[str, Any], "ParamRef"] = None, title: "ChannelValue" = None, x1: "ChannelValueSpec" = None, x2: "ChannelValueSpec" = None, y1: "ChannelValueSpec" = None, y2: "ChannelValueSpec" = None, z: "ChannelValue" = None): + self.ariaDescription = ariaDescription + self.ariaHidden = ariaHidden + self.ariaLabel = ariaLabel + self.clip = clip + self.curve = curve + self.data = data + self.dx = dx + self.dy = dy + self.facet = facet + self.facetAnchor = facetAnchor + self.fill = fill + self.fillOpacity = fillOpacity + self.filter = filter + self.fx = fx + self.fy = fy + self.href = href + self.imageFilter = imageFilter + self.margin = margin + self.marginBottom = marginBottom + self.marginLeft = marginLeft + self.marginRight = marginRight + self.marginTop = marginTop + self.mark = mark + self.mixBlendMode = mixBlendMode + self.offset = offset + self.opacity = opacity + self.order = order + self.paintOrder = paintOrder + self.pointerEvents = pointerEvents + self.reverse = reverse + self.select = select + self.shapeRendering = shapeRendering + self.sort = sort + self.stroke = stroke + self.strokeDasharray = strokeDasharray + self.strokeDashoffset = strokeDashoffset + self.strokeLinecap = strokeLinecap + self.strokeLinejoin = strokeLinejoin + self.strokeMiterlimit = strokeMiterlimit + self.strokeOpacity = strokeOpacity + self.strokeWidth = strokeWidth + self.target = target + self.tension = tension + self.tip = tip + self.title = title + self.x1 = x1 + self.x2 = x2 + self.y1 = y1 + self.y2 = y2 + self.z = z + + +class AreaX: + def __init__(self, data: "PlotMarkData", mark: str, ariaDescription: Union[str, "ParamRef"] = None, ariaHidden: Union[str, "ParamRef"] = None, ariaLabel: "ChannelValue" = None, clip: Union[str, str, bool, Any, "ParamRef"] = None, curve: Union["Curve", "ParamRef"] = None, dx: Union[float, "ParamRef"] = None, dy: Union[float, "ParamRef"] = None, facet: Union[str, str, str, str, bool, Any, "ParamRef"] = None, facetAnchor: Union[str, str, str, str, str, str, str, str, str, str, str, str, str, Any, "ParamRef"] = None, fill: Union["ChannelValueSpec", "ParamRef"] = None, fillOpacity: Union["ChannelValueSpec", "ParamRef"] = None, filter: "ChannelValue" = None, fx: "ChannelValue" = None, fy: "ChannelValue" = None, href: "ChannelValue" = None, imageFilter: Union[str, "ParamRef"] = None, margin: Union[float, "ParamRef"] = None, marginBottom: Union[float, "ParamRef"] = None, marginLeft: Union[float, "ParamRef"] = None, marginRight: Union[float, "ParamRef"] = None, marginTop: Union[float, "ParamRef"] = None, mixBlendMode: Union[str, "ParamRef"] = None, offset: Union["StackOffset", Any, "ParamRef"] = None, opacity: "ChannelValueSpec" = None, order: Union["StackOrder", Any, "ParamRef"] = None, paintOrder: Union[str, "ParamRef"] = None, pointerEvents: Union[str, "ParamRef"] = None, reverse: Union[bool, "ParamRef"] = None, select: "SelectFilter" = None, shapeRendering: Union[str, "ParamRef"] = None, sort: Union["SortOrder", "ChannelDomainSort"] = None, stroke: Union["ChannelValueSpec", "ParamRef"] = None, strokeDasharray: Union[str, float, "ParamRef"] = None, strokeDashoffset: Union[str, float, "ParamRef"] = None, strokeLinecap: Union[str, "ParamRef"] = None, strokeLinejoin: Union[str, "ParamRef"] = None, strokeMiterlimit: Union[float, "ParamRef"] = None, strokeOpacity: "ChannelValueSpec" = None, strokeWidth: "ChannelValueSpec" = None, target: Union[str, "ParamRef"] = None, tension: Union[float, "ParamRef"] = None, tip: Union[bool, "TipPointer", Dict[str, Any], "ParamRef"] = None, title: "ChannelValue" = None, x: "ChannelValueSpec" = None, x1: "ChannelValueSpec" = None, x2: "ChannelValueSpec" = None, y: "ChannelValueSpec" = None, z: "ChannelValue" = None): + self.ariaDescription = ariaDescription + self.ariaHidden = ariaHidden + self.ariaLabel = ariaLabel + self.clip = clip + self.curve = curve + self.data = data + self.dx = dx + self.dy = dy + self.facet = facet + self.facetAnchor = facetAnchor + self.fill = fill + self.fillOpacity = fillOpacity + self.filter = filter + self.fx = fx + self.fy = fy + self.href = href + self.imageFilter = imageFilter + self.margin = margin + self.marginBottom = marginBottom + self.marginLeft = marginLeft + self.marginRight = marginRight + self.marginTop = marginTop + self.mark = mark + self.mixBlendMode = mixBlendMode + self.offset = offset + self.opacity = opacity + self.order = order + self.paintOrder = paintOrder + self.pointerEvents = pointerEvents + self.reverse = reverse + self.select = select + self.shapeRendering = shapeRendering + self.sort = sort + self.stroke = stroke + self.strokeDasharray = strokeDasharray + self.strokeDashoffset = strokeDashoffset + self.strokeLinecap = strokeLinecap + self.strokeLinejoin = strokeLinejoin + self.strokeMiterlimit = strokeMiterlimit + self.strokeOpacity = strokeOpacity + self.strokeWidth = strokeWidth + self.target = target + self.tension = tension + self.tip = tip + self.title = title + self.x = x + self.x1 = x1 + self.x2 = x2 + self.y = y + self.z = z + + +class AreaY: + def __init__(self, data: "PlotMarkData", mark: str, ariaDescription: Union[str, "ParamRef"] = None, ariaHidden: Union[str, "ParamRef"] = None, ariaLabel: "ChannelValue" = None, clip: Union[str, str, bool, Any, "ParamRef"] = None, curve: Union["Curve", "ParamRef"] = None, dx: Union[float, "ParamRef"] = None, dy: Union[float, "ParamRef"] = None, facet: Union[str, str, str, str, bool, Any, "ParamRef"] = None, facetAnchor: Union[str, str, str, str, str, str, str, str, str, str, str, str, str, Any, "ParamRef"] = None, fill: Union["ChannelValueSpec", "ParamRef"] = None, fillOpacity: Union["ChannelValueSpec", "ParamRef"] = None, filter: "ChannelValue" = None, fx: "ChannelValue" = None, fy: "ChannelValue" = None, href: "ChannelValue" = None, imageFilter: Union[str, "ParamRef"] = None, margin: Union[float, "ParamRef"] = None, marginBottom: Union[float, "ParamRef"] = None, marginLeft: Union[float, "ParamRef"] = None, marginRight: Union[float, "ParamRef"] = None, marginTop: Union[float, "ParamRef"] = None, mixBlendMode: Union[str, "ParamRef"] = None, offset: Union["StackOffset", Any, "ParamRef"] = None, opacity: "ChannelValueSpec" = None, order: Union["StackOrder", Any, "ParamRef"] = None, paintOrder: Union[str, "ParamRef"] = None, pointerEvents: Union[str, "ParamRef"] = None, reverse: Union[bool, "ParamRef"] = None, select: "SelectFilter" = None, shapeRendering: Union[str, "ParamRef"] = None, sort: Union["SortOrder", "ChannelDomainSort"] = None, stroke: Union["ChannelValueSpec", "ParamRef"] = None, strokeDasharray: Union[str, float, "ParamRef"] = None, strokeDashoffset: Union[str, float, "ParamRef"] = None, strokeLinecap: Union[str, "ParamRef"] = None, strokeLinejoin: Union[str, "ParamRef"] = None, strokeMiterlimit: Union[float, "ParamRef"] = None, strokeOpacity: "ChannelValueSpec" = None, strokeWidth: "ChannelValueSpec" = None, target: Union[str, "ParamRef"] = None, tension: Union[float, "ParamRef"] = None, tip: Union[bool, "TipPointer", Dict[str, Any], "ParamRef"] = None, title: "ChannelValue" = None, x: "ChannelValueSpec" = None, y: "ChannelValueSpec" = None, y1: "ChannelValueSpec" = None, y2: "ChannelValueSpec" = None, z: "ChannelValue" = None): + self.ariaDescription = ariaDescription + self.ariaHidden = ariaHidden + self.ariaLabel = ariaLabel + self.clip = clip + self.curve = curve + self.data = data + self.dx = dx + self.dy = dy + self.facet = facet + self.facetAnchor = facetAnchor + self.fill = fill + self.fillOpacity = fillOpacity + self.filter = filter + self.fx = fx + self.fy = fy + self.href = href + self.imageFilter = imageFilter + self.margin = margin + self.marginBottom = marginBottom + self.marginLeft = marginLeft + self.marginRight = marginRight + self.marginTop = marginTop + self.mark = mark + self.mixBlendMode = mixBlendMode + self.offset = offset + self.opacity = opacity + self.order = order + self.paintOrder = paintOrder + self.pointerEvents = pointerEvents + self.reverse = reverse + self.select = select + self.shapeRendering = shapeRendering + self.sort = sort + self.stroke = stroke + self.strokeDasharray = strokeDasharray + self.strokeDashoffset = strokeDashoffset + self.strokeLinecap = strokeLinecap + self.strokeLinejoin = strokeLinejoin + self.strokeMiterlimit = strokeMiterlimit + self.strokeOpacity = strokeOpacity + self.strokeWidth = strokeWidth + self.target = target + self.tension = tension + self.tip = tip + self.title = title + self.x = x + self.y = y + self.y1 = y1 + self.y2 = y2 + self.z = z + + +class Arrow: + def __init__(self, data: "PlotMarkData", mark: str, ariaDescription: Union[str, "ParamRef"] = None, ariaHidden: Union[str, "ParamRef"] = None, ariaLabel: "ChannelValue" = None, bend: Union[float, bool, "ParamRef"] = None, clip: Union[str, str, bool, Any, "ParamRef"] = None, dx: Union[float, "ParamRef"] = None, dy: Union[float, "ParamRef"] = None, facet: Union[str, str, str, str, bool, Any, "ParamRef"] = None, facetAnchor: Union[str, str, str, str, str, str, str, str, str, str, str, str, str, Any, "ParamRef"] = None, fill: Union["ChannelValueSpec", "ParamRef"] = None, fillOpacity: Union["ChannelValueSpec", "ParamRef"] = None, filter: "ChannelValue" = None, fx: "ChannelValue" = None, fy: "ChannelValue" = None, headAngle: Union[float, "ParamRef"] = None, headLength: Union[float, "ParamRef"] = None, href: "ChannelValue" = None, imageFilter: Union[str, "ParamRef"] = None, inset: Union[float, "ParamRef"] = None, insetEnd: Union[float, "ParamRef"] = None, insetStart: Union[float, "ParamRef"] = None, margin: Union[float, "ParamRef"] = None, marginBottom: Union[float, "ParamRef"] = None, marginLeft: Union[float, "ParamRef"] = None, marginRight: Union[float, "ParamRef"] = None, marginTop: Union[float, "ParamRef"] = None, mixBlendMode: Union[str, "ParamRef"] = None, opacity: "ChannelValueSpec" = None, paintOrder: Union[str, "ParamRef"] = None, pointerEvents: Union[str, "ParamRef"] = None, reverse: Union[bool, "ParamRef"] = None, select: "SelectFilter" = None, shapeRendering: Union[str, "ParamRef"] = None, sort: Union["SortOrder", "ChannelDomainSort"] = None, stroke: Union["ChannelValueSpec", "ParamRef"] = None, strokeDasharray: Union[str, float, "ParamRef"] = None, strokeDashoffset: Union[str, float, "ParamRef"] = None, strokeLinecap: Union[str, "ParamRef"] = None, strokeLinejoin: Union[str, "ParamRef"] = None, strokeMiterlimit: Union[float, "ParamRef"] = None, strokeOpacity: "ChannelValueSpec" = None, strokeWidth: "ChannelValueSpec" = None, sweep: Union[float, str, str, str, str, "ParamRef"] = None, target: Union[str, "ParamRef"] = None, tip: Union[bool, "TipPointer", Dict[str, Any], "ParamRef"] = None, title: "ChannelValue" = None, x: "ChannelValueSpec" = None, x1: "ChannelValueSpec" = None, x2: "ChannelValueSpec" = None, y: "ChannelValueSpec" = None, y1: "ChannelValueSpec" = None, y2: "ChannelValueSpec" = None): + self.ariaDescription = ariaDescription + self.ariaHidden = ariaHidden + self.ariaLabel = ariaLabel + self.bend = bend + self.clip = clip + self.data = data + self.dx = dx + self.dy = dy + self.facet = facet + self.facetAnchor = facetAnchor + self.fill = fill + self.fillOpacity = fillOpacity + self.filter = filter + self.fx = fx + self.fy = fy + self.headAngle = headAngle + self.headLength = headLength + self.href = href + self.imageFilter = imageFilter + self.inset = inset + self.insetEnd = insetEnd + self.insetStart = insetStart + self.margin = margin + self.marginBottom = marginBottom + self.marginLeft = marginLeft + self.marginRight = marginRight + self.marginTop = marginTop + self.mark = mark + self.mixBlendMode = mixBlendMode + self.opacity = opacity + self.paintOrder = paintOrder + self.pointerEvents = pointerEvents + self.reverse = reverse + self.select = select + self.shapeRendering = shapeRendering + self.sort = sort + self.stroke = stroke + self.strokeDasharray = strokeDasharray + self.strokeDashoffset = strokeDashoffset + self.strokeLinecap = strokeLinecap + self.strokeLinejoin = strokeLinejoin + self.strokeMiterlimit = strokeMiterlimit + self.strokeOpacity = strokeOpacity + self.strokeWidth = strokeWidth + self.sweep = sweep + self.target = target + self.tip = tip + self.title = title + self.x = x + self.x1 = x1 + self.x2 = x2 + self.y = y + self.y1 = y1 + self.y2 = y2 + + +class AxisFx: + def __init__(self, mark: str, anchor: Union[str, str, str, str, "ParamRef"] = None, ariaDescription: Union[str, "ParamRef"] = None, ariaHidden: Union[str, "ParamRef"] = None, ariaLabel: "ChannelValue" = None, clip: Union[str, str, bool, Any, "ParamRef"] = None, color: Union["ChannelValueSpec", "ParamRef"] = None, dx: Union[float, "ParamRef"] = None, dy: Union[float, "ParamRef"] = None, facet: Union[str, str, str, str, bool, Any, "ParamRef"] = None, facetAnchor: Union[str, str, str, str, str, str, str, str, str, str, str, str, str, Any, "ParamRef"] = None, fill: Union["ChannelValueSpec", "ParamRef"] = None, fillOpacity: Union["ChannelValueSpec", "ParamRef"] = None, filter: "ChannelValue" = None, fontFamily: Union[str, "ParamRef"] = None, fontSize: Union["ChannelValue", "ParamRef"] = None, fontStyle: Union[str, "ParamRef"] = None, fontVariant: Union[str, "ParamRef"] = None, fontWeight: Union[str, float, "ParamRef"] = None, frameAnchor: Union["FrameAnchor", "ParamRef"] = None, fx: "ChannelValue" = None, fy: "ChannelValue" = None, href: "ChannelValue" = None, imageFilter: Union[str, "ParamRef"] = None, inset: Union[float, "ParamRef"] = None, insetBottom: Union[float, "ParamRef"] = None, insetTop: Union[float, "ParamRef"] = None, interval: Union["Interval", "ParamRef"] = None, label: Union[str, Any, "ParamRef"] = None, labelAnchor: Union[str, str, str, str, str, "ParamRef"] = None, labelArrow: Union[str, str, str, str, str, str, bool, bool, Any, "ParamRef"] = None, labelOffset: Union[float, "ParamRef"] = None, lineAnchor: Union[str, str, str, "ParamRef"] = None, lineHeight: Union[float, "ParamRef"] = None, lineWidth: Union[float, "ParamRef"] = None, margin: Union[float, "ParamRef"] = None, marginBottom: Union[float, "ParamRef"] = None, marginLeft: Union[float, "ParamRef"] = None, marginRight: Union[float, "ParamRef"] = None, marginTop: Union[float, "ParamRef"] = None, marker: Union["MarkerName", str, bool, Any, "ParamRef"] = None, markerEnd: Union["MarkerName", str, bool, Any, "ParamRef"] = None, markerMid: Union["MarkerName", str, bool, Any, "ParamRef"] = None, markerStart: Union["MarkerName", str, bool, Any, "ParamRef"] = None, mixBlendMode: Union[str, "ParamRef"] = None, monospace: Union[bool, "ParamRef"] = None, opacity: "ChannelValueSpec" = None, paintOrder: Union[str, "ParamRef"] = None, pointerEvents: Union[str, "ParamRef"] = None, reverse: Union[bool, "ParamRef"] = None, rotate: Union["ChannelValue", "ParamRef"] = None, select: "SelectFilter" = None, shapeRendering: Union[str, "ParamRef"] = None, sort: Union["SortOrder", "ChannelDomainSort"] = None, stroke: Union["ChannelValueSpec", "ParamRef"] = None, strokeDasharray: Union[str, float, "ParamRef"] = None, strokeDashoffset: Union[str, float, "ParamRef"] = None, strokeLinecap: Union[str, "ParamRef"] = None, strokeLinejoin: Union[str, "ParamRef"] = None, strokeMiterlimit: Union[float, "ParamRef"] = None, strokeOpacity: "ChannelValueSpec" = None, strokeWidth: "ChannelValueSpec" = None, target: Union[str, "ParamRef"] = None, text: "ChannelValue" = None, textAnchor: Union[str, str, str, "ParamRef"] = None, textOverflow: Union[Any, str, str, str, str, str, str, str, "ParamRef"] = None, textStroke: Union["ChannelValueSpec", "ParamRef"] = None, textStrokeOpacity: "ChannelValueSpec" = None, textStrokeWidth: "ChannelValueSpec" = None, tickFormat: Union[str, Any, "ParamRef"] = None, tickPadding: Union[float, "ParamRef"] = None, tickRotate: Union[float, "ParamRef"] = None, tickSize: Union[float, "ParamRef"] = None, tickSpacing: Union[float, "ParamRef"] = None, ticks: Union[float, "Interval", List[Any], "ParamRef"] = None, tip: Union[bool, "TipPointer", Dict[str, Any], "ParamRef"] = None, title: "ChannelValue" = None, x: "ChannelValueSpec" = None, y: "ChannelValueSpec" = None, z: "ChannelValue" = None): + self.anchor = anchor + self.ariaDescription = ariaDescription + self.ariaHidden = ariaHidden + self.ariaLabel = ariaLabel + self.clip = clip + self.color = color + self.dx = dx + self.dy = dy + self.facet = facet + self.facetAnchor = facetAnchor + self.fill = fill + self.fillOpacity = fillOpacity + self.filter = filter + self.fontFamily = fontFamily + self.fontSize = fontSize + self.fontStyle = fontStyle + self.fontVariant = fontVariant + self.fontWeight = fontWeight + self.frameAnchor = frameAnchor + self.fx = fx + self.fy = fy + self.href = href + self.imageFilter = imageFilter + self.inset = inset + self.insetBottom = insetBottom + self.insetTop = insetTop + self.interval = interval + self.label = label + self.labelAnchor = labelAnchor + self.labelArrow = labelArrow + self.labelOffset = labelOffset + self.lineAnchor = lineAnchor + self.lineHeight = lineHeight + self.lineWidth = lineWidth + self.margin = margin + self.marginBottom = marginBottom + self.marginLeft = marginLeft + self.marginRight = marginRight + self.marginTop = marginTop + self.mark = mark + self.marker = marker + self.markerEnd = markerEnd + self.markerMid = markerMid + self.markerStart = markerStart + self.mixBlendMode = mixBlendMode + self.monospace = monospace + self.opacity = opacity + self.paintOrder = paintOrder + self.pointerEvents = pointerEvents + self.reverse = reverse + self.rotate = rotate + self.select = select + self.shapeRendering = shapeRendering + self.sort = sort + self.stroke = stroke + self.strokeDasharray = strokeDasharray + self.strokeDashoffset = strokeDashoffset + self.strokeLinecap = strokeLinecap + self.strokeLinejoin = strokeLinejoin + self.strokeMiterlimit = strokeMiterlimit + self.strokeOpacity = strokeOpacity + self.strokeWidth = strokeWidth + self.target = target + self.text = text + self.textAnchor = textAnchor + self.textOverflow = textOverflow + self.textStroke = textStroke + self.textStrokeOpacity = textStrokeOpacity + self.textStrokeWidth = textStrokeWidth + self.tickFormat = tickFormat + self.tickPadding = tickPadding + self.tickRotate = tickRotate + self.tickSize = tickSize + self.tickSpacing = tickSpacing + self.ticks = ticks + self.tip = tip + self.title = title + self.x = x + self.y = y + self.z = z + + +class AxisFy: + def __init__(self, mark: str, anchor: Union[str, str, str, str, "ParamRef"] = None, ariaDescription: Union[str, "ParamRef"] = None, ariaHidden: Union[str, "ParamRef"] = None, ariaLabel: "ChannelValue" = None, clip: Union[str, str, bool, Any, "ParamRef"] = None, color: Union["ChannelValueSpec", "ParamRef"] = None, dx: Union[float, "ParamRef"] = None, dy: Union[float, "ParamRef"] = None, facet: Union[str, str, str, str, bool, Any, "ParamRef"] = None, facetAnchor: Union[str, str, str, str, str, str, str, str, str, str, str, str, str, Any, "ParamRef"] = None, fill: Union["ChannelValueSpec", "ParamRef"] = None, fillOpacity: Union["ChannelValueSpec", "ParamRef"] = None, filter: "ChannelValue" = None, fontFamily: Union[str, "ParamRef"] = None, fontSize: Union["ChannelValue", "ParamRef"] = None, fontStyle: Union[str, "ParamRef"] = None, fontVariant: Union[str, "ParamRef"] = None, fontWeight: Union[str, float, "ParamRef"] = None, frameAnchor: Union["FrameAnchor", "ParamRef"] = None, fx: "ChannelValue" = None, fy: "ChannelValue" = None, href: "ChannelValue" = None, imageFilter: Union[str, "ParamRef"] = None, inset: Union[float, "ParamRef"] = None, insetLeft: Union[float, "ParamRef"] = None, insetRight: Union[float, "ParamRef"] = None, interval: Union["Interval", "ParamRef"] = None, label: Union[str, Any, "ParamRef"] = None, labelAnchor: Union[str, str, str, str, str, "ParamRef"] = None, labelArrow: Union[str, str, str, str, str, str, bool, bool, Any, "ParamRef"] = None, labelOffset: Union[float, "ParamRef"] = None, lineAnchor: Union[str, str, str, "ParamRef"] = None, lineHeight: Union[float, "ParamRef"] = None, lineWidth: Union[float, "ParamRef"] = None, margin: Union[float, "ParamRef"] = None, marginBottom: Union[float, "ParamRef"] = None, marginLeft: Union[float, "ParamRef"] = None, marginRight: Union[float, "ParamRef"] = None, marginTop: Union[float, "ParamRef"] = None, marker: Union["MarkerName", str, bool, Any, "ParamRef"] = None, markerEnd: Union["MarkerName", str, bool, Any, "ParamRef"] = None, markerMid: Union["MarkerName", str, bool, Any, "ParamRef"] = None, markerStart: Union["MarkerName", str, bool, Any, "ParamRef"] = None, mixBlendMode: Union[str, "ParamRef"] = None, monospace: Union[bool, "ParamRef"] = None, opacity: "ChannelValueSpec" = None, paintOrder: Union[str, "ParamRef"] = None, pointerEvents: Union[str, "ParamRef"] = None, reverse: Union[bool, "ParamRef"] = None, rotate: Union["ChannelValue", "ParamRef"] = None, select: "SelectFilter" = None, shapeRendering: Union[str, "ParamRef"] = None, sort: Union["SortOrder", "ChannelDomainSort"] = None, stroke: Union["ChannelValueSpec", "ParamRef"] = None, strokeDasharray: Union[str, float, "ParamRef"] = None, strokeDashoffset: Union[str, float, "ParamRef"] = None, strokeLinecap: Union[str, "ParamRef"] = None, strokeLinejoin: Union[str, "ParamRef"] = None, strokeMiterlimit: Union[float, "ParamRef"] = None, strokeOpacity: "ChannelValueSpec" = None, strokeWidth: "ChannelValueSpec" = None, target: Union[str, "ParamRef"] = None, text: "ChannelValue" = None, textAnchor: Union[str, str, str, "ParamRef"] = None, textOverflow: Union[Any, str, str, str, str, str, str, str, "ParamRef"] = None, textStroke: Union["ChannelValueSpec", "ParamRef"] = None, textStrokeOpacity: "ChannelValueSpec" = None, textStrokeWidth: "ChannelValueSpec" = None, tickFormat: Union[str, Any, "ParamRef"] = None, tickPadding: Union[float, "ParamRef"] = None, tickRotate: Union[float, "ParamRef"] = None, tickSize: Union[float, "ParamRef"] = None, tickSpacing: Union[float, "ParamRef"] = None, ticks: Union[float, "Interval", List[Any], "ParamRef"] = None, tip: Union[bool, "TipPointer", Dict[str, Any], "ParamRef"] = None, title: "ChannelValue" = None, x: "ChannelValueSpec" = None, y: "ChannelValueSpec" = None, z: "ChannelValue" = None): + self.anchor = anchor + self.ariaDescription = ariaDescription + self.ariaHidden = ariaHidden + self.ariaLabel = ariaLabel + self.clip = clip + self.color = color + self.dx = dx + self.dy = dy + self.facet = facet + self.facetAnchor = facetAnchor + self.fill = fill + self.fillOpacity = fillOpacity + self.filter = filter + self.fontFamily = fontFamily + self.fontSize = fontSize + self.fontStyle = fontStyle + self.fontVariant = fontVariant + self.fontWeight = fontWeight + self.frameAnchor = frameAnchor + self.fx = fx + self.fy = fy + self.href = href + self.imageFilter = imageFilter + self.inset = inset + self.insetLeft = insetLeft + self.insetRight = insetRight + self.interval = interval + self.label = label + self.labelAnchor = labelAnchor + self.labelArrow = labelArrow + self.labelOffset = labelOffset + self.lineAnchor = lineAnchor + self.lineHeight = lineHeight + self.lineWidth = lineWidth + self.margin = margin + self.marginBottom = marginBottom + self.marginLeft = marginLeft + self.marginRight = marginRight + self.marginTop = marginTop + self.mark = mark + self.marker = marker + self.markerEnd = markerEnd + self.markerMid = markerMid + self.markerStart = markerStart + self.mixBlendMode = mixBlendMode + self.monospace = monospace + self.opacity = opacity + self.paintOrder = paintOrder + self.pointerEvents = pointerEvents + self.reverse = reverse + self.rotate = rotate + self.select = select + self.shapeRendering = shapeRendering + self.sort = sort + self.stroke = stroke + self.strokeDasharray = strokeDasharray + self.strokeDashoffset = strokeDashoffset + self.strokeLinecap = strokeLinecap + self.strokeLinejoin = strokeLinejoin + self.strokeMiterlimit = strokeMiterlimit + self.strokeOpacity = strokeOpacity + self.strokeWidth = strokeWidth + self.target = target + self.text = text + self.textAnchor = textAnchor + self.textOverflow = textOverflow + self.textStroke = textStroke + self.textStrokeOpacity = textStrokeOpacity + self.textStrokeWidth = textStrokeWidth + self.tickFormat = tickFormat + self.tickPadding = tickPadding + self.tickRotate = tickRotate + self.tickSize = tickSize + self.tickSpacing = tickSpacing + self.ticks = ticks + self.tip = tip + self.title = title + self.x = x + self.y = y + self.z = z + + +class AxisX: + def __init__(self, mark: str, anchor: Union[str, str, str, str, "ParamRef"] = None, ariaDescription: Union[str, "ParamRef"] = None, ariaHidden: Union[str, "ParamRef"] = None, ariaLabel: "ChannelValue" = None, clip: Union[str, str, bool, Any, "ParamRef"] = None, color: Union["ChannelValueSpec", "ParamRef"] = None, dx: Union[float, "ParamRef"] = None, dy: Union[float, "ParamRef"] = None, facet: Union[str, str, str, str, bool, Any, "ParamRef"] = None, facetAnchor: Union[str, str, str, str, str, str, str, str, str, str, str, str, str, Any, "ParamRef"] = None, fill: Union["ChannelValueSpec", "ParamRef"] = None, fillOpacity: Union["ChannelValueSpec", "ParamRef"] = None, filter: "ChannelValue" = None, fontFamily: Union[str, "ParamRef"] = None, fontSize: Union["ChannelValue", "ParamRef"] = None, fontStyle: Union[str, "ParamRef"] = None, fontVariant: Union[str, "ParamRef"] = None, fontWeight: Union[str, float, "ParamRef"] = None, frameAnchor: Union["FrameAnchor", "ParamRef"] = None, fx: "ChannelValue" = None, fy: "ChannelValue" = None, href: "ChannelValue" = None, imageFilter: Union[str, "ParamRef"] = None, inset: Union[float, "ParamRef"] = None, insetBottom: Union[float, "ParamRef"] = None, insetTop: Union[float, "ParamRef"] = None, interval: Union["Interval", "ParamRef"] = None, label: Union[str, Any, "ParamRef"] = None, labelAnchor: Union[str, str, str, str, str, "ParamRef"] = None, labelArrow: Union[str, str, str, str, str, str, bool, bool, Any, "ParamRef"] = None, labelOffset: Union[float, "ParamRef"] = None, lineAnchor: Union[str, str, str, "ParamRef"] = None, lineHeight: Union[float, "ParamRef"] = None, lineWidth: Union[float, "ParamRef"] = None, margin: Union[float, "ParamRef"] = None, marginBottom: Union[float, "ParamRef"] = None, marginLeft: Union[float, "ParamRef"] = None, marginRight: Union[float, "ParamRef"] = None, marginTop: Union[float, "ParamRef"] = None, marker: Union["MarkerName", str, bool, Any, "ParamRef"] = None, markerEnd: Union["MarkerName", str, bool, Any, "ParamRef"] = None, markerMid: Union["MarkerName", str, bool, Any, "ParamRef"] = None, markerStart: Union["MarkerName", str, bool, Any, "ParamRef"] = None, mixBlendMode: Union[str, "ParamRef"] = None, monospace: Union[bool, "ParamRef"] = None, opacity: "ChannelValueSpec" = None, paintOrder: Union[str, "ParamRef"] = None, pointerEvents: Union[str, "ParamRef"] = None, reverse: Union[bool, "ParamRef"] = None, rotate: Union["ChannelValue", "ParamRef"] = None, select: "SelectFilter" = None, shapeRendering: Union[str, "ParamRef"] = None, sort: Union["SortOrder", "ChannelDomainSort"] = None, stroke: Union["ChannelValueSpec", "ParamRef"] = None, strokeDasharray: Union[str, float, "ParamRef"] = None, strokeDashoffset: Union[str, float, "ParamRef"] = None, strokeLinecap: Union[str, "ParamRef"] = None, strokeLinejoin: Union[str, "ParamRef"] = None, strokeMiterlimit: Union[float, "ParamRef"] = None, strokeOpacity: "ChannelValueSpec" = None, strokeWidth: "ChannelValueSpec" = None, target: Union[str, "ParamRef"] = None, text: "ChannelValue" = None, textAnchor: Union[str, str, str, "ParamRef"] = None, textOverflow: Union[Any, str, str, str, str, str, str, str, "ParamRef"] = None, textStroke: Union["ChannelValueSpec", "ParamRef"] = None, textStrokeOpacity: "ChannelValueSpec" = None, textStrokeWidth: "ChannelValueSpec" = None, tickFormat: Union[str, Any, "ParamRef"] = None, tickPadding: Union[float, "ParamRef"] = None, tickRotate: Union[float, "ParamRef"] = None, tickSize: Union[float, "ParamRef"] = None, tickSpacing: Union[float, "ParamRef"] = None, ticks: Union[float, "Interval", List[Any], "ParamRef"] = None, tip: Union[bool, "TipPointer", Dict[str, Any], "ParamRef"] = None, title: "ChannelValue" = None, x: "ChannelValueSpec" = None, y: "ChannelValueSpec" = None, z: "ChannelValue" = None): + self.anchor = anchor + self.ariaDescription = ariaDescription + self.ariaHidden = ariaHidden + self.ariaLabel = ariaLabel + self.clip = clip + self.color = color + self.dx = dx + self.dy = dy + self.facet = facet + self.facetAnchor = facetAnchor + self.fill = fill + self.fillOpacity = fillOpacity + self.filter = filter + self.fontFamily = fontFamily + self.fontSize = fontSize + self.fontStyle = fontStyle + self.fontVariant = fontVariant + self.fontWeight = fontWeight + self.frameAnchor = frameAnchor + self.fx = fx + self.fy = fy + self.href = href + self.imageFilter = imageFilter + self.inset = inset + self.insetBottom = insetBottom + self.insetTop = insetTop + self.interval = interval + self.label = label + self.labelAnchor = labelAnchor + self.labelArrow = labelArrow + self.labelOffset = labelOffset + self.lineAnchor = lineAnchor + self.lineHeight = lineHeight + self.lineWidth = lineWidth + self.margin = margin + self.marginBottom = marginBottom + self.marginLeft = marginLeft + self.marginRight = marginRight + self.marginTop = marginTop + self.mark = mark + self.marker = marker + self.markerEnd = markerEnd + self.markerMid = markerMid + self.markerStart = markerStart + self.mixBlendMode = mixBlendMode + self.monospace = monospace + self.opacity = opacity + self.paintOrder = paintOrder + self.pointerEvents = pointerEvents + self.reverse = reverse + self.rotate = rotate + self.select = select + self.shapeRendering = shapeRendering + self.sort = sort + self.stroke = stroke + self.strokeDasharray = strokeDasharray + self.strokeDashoffset = strokeDashoffset + self.strokeLinecap = strokeLinecap + self.strokeLinejoin = strokeLinejoin + self.strokeMiterlimit = strokeMiterlimit + self.strokeOpacity = strokeOpacity + self.strokeWidth = strokeWidth + self.target = target + self.text = text + self.textAnchor = textAnchor + self.textOverflow = textOverflow + self.textStroke = textStroke + self.textStrokeOpacity = textStrokeOpacity + self.textStrokeWidth = textStrokeWidth + self.tickFormat = tickFormat + self.tickPadding = tickPadding + self.tickRotate = tickRotate + self.tickSize = tickSize + self.tickSpacing = tickSpacing + self.ticks = ticks + self.tip = tip + self.title = title + self.x = x + self.y = y + self.z = z + + +class AxisY: + def __init__(self, mark: str, anchor: Union[str, str, str, str, "ParamRef"] = None, ariaDescription: Union[str, "ParamRef"] = None, ariaHidden: Union[str, "ParamRef"] = None, ariaLabel: "ChannelValue" = None, clip: Union[str, str, bool, Any, "ParamRef"] = None, color: Union["ChannelValueSpec", "ParamRef"] = None, dx: Union[float, "ParamRef"] = None, dy: Union[float, "ParamRef"] = None, facet: Union[str, str, str, str, bool, Any, "ParamRef"] = None, facetAnchor: Union[str, str, str, str, str, str, str, str, str, str, str, str, str, Any, "ParamRef"] = None, fill: Union["ChannelValueSpec", "ParamRef"] = None, fillOpacity: Union["ChannelValueSpec", "ParamRef"] = None, filter: "ChannelValue" = None, fontFamily: Union[str, "ParamRef"] = None, fontSize: Union["ChannelValue", "ParamRef"] = None, fontStyle: Union[str, "ParamRef"] = None, fontVariant: Union[str, "ParamRef"] = None, fontWeight: Union[str, float, "ParamRef"] = None, frameAnchor: Union["FrameAnchor", "ParamRef"] = None, fx: "ChannelValue" = None, fy: "ChannelValue" = None, href: "ChannelValue" = None, imageFilter: Union[str, "ParamRef"] = None, inset: Union[float, "ParamRef"] = None, insetLeft: Union[float, "ParamRef"] = None, insetRight: Union[float, "ParamRef"] = None, interval: Union["Interval", "ParamRef"] = None, label: Union[str, Any, "ParamRef"] = None, labelAnchor: Union[str, str, str, str, str, "ParamRef"] = None, labelArrow: Union[str, str, str, str, str, str, bool, bool, Any, "ParamRef"] = None, labelOffset: Union[float, "ParamRef"] = None, lineAnchor: Union[str, str, str, "ParamRef"] = None, lineHeight: Union[float, "ParamRef"] = None, lineWidth: Union[float, "ParamRef"] = None, margin: Union[float, "ParamRef"] = None, marginBottom: Union[float, "ParamRef"] = None, marginLeft: Union[float, "ParamRef"] = None, marginRight: Union[float, "ParamRef"] = None, marginTop: Union[float, "ParamRef"] = None, marker: Union["MarkerName", str, bool, Any, "ParamRef"] = None, markerEnd: Union["MarkerName", str, bool, Any, "ParamRef"] = None, markerMid: Union["MarkerName", str, bool, Any, "ParamRef"] = None, markerStart: Union["MarkerName", str, bool, Any, "ParamRef"] = None, mixBlendMode: Union[str, "ParamRef"] = None, monospace: Union[bool, "ParamRef"] = None, opacity: "ChannelValueSpec" = None, paintOrder: Union[str, "ParamRef"] = None, pointerEvents: Union[str, "ParamRef"] = None, reverse: Union[bool, "ParamRef"] = None, rotate: Union["ChannelValue", "ParamRef"] = None, select: "SelectFilter" = None, shapeRendering: Union[str, "ParamRef"] = None, sort: Union["SortOrder", "ChannelDomainSort"] = None, stroke: Union["ChannelValueSpec", "ParamRef"] = None, strokeDasharray: Union[str, float, "ParamRef"] = None, strokeDashoffset: Union[str, float, "ParamRef"] = None, strokeLinecap: Union[str, "ParamRef"] = None, strokeLinejoin: Union[str, "ParamRef"] = None, strokeMiterlimit: Union[float, "ParamRef"] = None, strokeOpacity: "ChannelValueSpec" = None, strokeWidth: "ChannelValueSpec" = None, target: Union[str, "ParamRef"] = None, text: "ChannelValue" = None, textAnchor: Union[str, str, str, "ParamRef"] = None, textOverflow: Union[Any, str, str, str, str, str, str, str, "ParamRef"] = None, textStroke: Union["ChannelValueSpec", "ParamRef"] = None, textStrokeOpacity: "ChannelValueSpec" = None, textStrokeWidth: "ChannelValueSpec" = None, tickFormat: Union[str, Any, "ParamRef"] = None, tickPadding: Union[float, "ParamRef"] = None, tickRotate: Union[float, "ParamRef"] = None, tickSize: Union[float, "ParamRef"] = None, tickSpacing: Union[float, "ParamRef"] = None, ticks: Union[float, "Interval", List[Any], "ParamRef"] = None, tip: Union[bool, "TipPointer", Dict[str, Any], "ParamRef"] = None, title: "ChannelValue" = None, x: "ChannelValueSpec" = None, y: "ChannelValueSpec" = None, z: "ChannelValue" = None): + self.anchor = anchor + self.ariaDescription = ariaDescription + self.ariaHidden = ariaHidden + self.ariaLabel = ariaLabel + self.clip = clip + self.color = color + self.dx = dx + self.dy = dy + self.facet = facet + self.facetAnchor = facetAnchor + self.fill = fill + self.fillOpacity = fillOpacity + self.filter = filter + self.fontFamily = fontFamily + self.fontSize = fontSize + self.fontStyle = fontStyle + self.fontVariant = fontVariant + self.fontWeight = fontWeight + self.frameAnchor = frameAnchor + self.fx = fx + self.fy = fy + self.href = href + self.imageFilter = imageFilter + self.inset = inset + self.insetLeft = insetLeft + self.insetRight = insetRight + self.interval = interval + self.label = label + self.labelAnchor = labelAnchor + self.labelArrow = labelArrow + self.labelOffset = labelOffset + self.lineAnchor = lineAnchor + self.lineHeight = lineHeight + self.lineWidth = lineWidth + self.margin = margin + self.marginBottom = marginBottom + self.marginLeft = marginLeft + self.marginRight = marginRight + self.marginTop = marginTop + self.mark = mark + self.marker = marker + self.markerEnd = markerEnd + self.markerMid = markerMid + self.markerStart = markerStart + self.mixBlendMode = mixBlendMode + self.monospace = monospace + self.opacity = opacity + self.paintOrder = paintOrder + self.pointerEvents = pointerEvents + self.reverse = reverse + self.rotate = rotate + self.select = select + self.shapeRendering = shapeRendering + self.sort = sort + self.stroke = stroke + self.strokeDasharray = strokeDasharray + self.strokeDashoffset = strokeDashoffset + self.strokeLinecap = strokeLinecap + self.strokeLinejoin = strokeLinejoin + self.strokeMiterlimit = strokeMiterlimit + self.strokeOpacity = strokeOpacity + self.strokeWidth = strokeWidth + self.target = target + self.text = text + self.textAnchor = textAnchor + self.textOverflow = textOverflow + self.textStroke = textStroke + self.textStrokeOpacity = textStrokeOpacity + self.textStrokeWidth = textStrokeWidth + self.tickFormat = tickFormat + self.tickPadding = tickPadding + self.tickRotate = tickRotate + self.tickSize = tickSize + self.tickSpacing = tickSpacing + self.ticks = ticks + self.tip = tip + self.title = title + self.x = x + self.y = y + self.z = z + + +class Cell: + def __init__(self, data: "PlotMarkData", mark: str, ariaDescription: Union[str, "ParamRef"] = None, ariaHidden: Union[str, "ParamRef"] = None, ariaLabel: "ChannelValue" = None, clip: Union[str, str, bool, Any, "ParamRef"] = None, dx: Union[float, "ParamRef"] = None, dy: Union[float, "ParamRef"] = None, facet: Union[str, str, str, str, bool, Any, "ParamRef"] = None, facetAnchor: Union[str, str, str, str, str, str, str, str, str, str, str, str, str, Any, "ParamRef"] = None, fill: Union["ChannelValueSpec", "ParamRef"] = None, fillOpacity: Union["ChannelValueSpec", "ParamRef"] = None, filter: "ChannelValue" = None, fx: "ChannelValue" = None, fy: "ChannelValue" = None, href: "ChannelValue" = None, imageFilter: Union[str, "ParamRef"] = None, inset: Union[float, "ParamRef"] = None, insetBottom: Union[float, "ParamRef"] = None, insetLeft: Union[float, "ParamRef"] = None, insetRight: Union[float, "ParamRef"] = None, insetTop: Union[float, "ParamRef"] = None, margin: Union[float, "ParamRef"] = None, marginBottom: Union[float, "ParamRef"] = None, marginLeft: Union[float, "ParamRef"] = None, marginRight: Union[float, "ParamRef"] = None, marginTop: Union[float, "ParamRef"] = None, mixBlendMode: Union[str, "ParamRef"] = None, opacity: "ChannelValueSpec" = None, paintOrder: Union[str, "ParamRef"] = None, pointerEvents: Union[str, "ParamRef"] = None, reverse: Union[bool, "ParamRef"] = None, rx: Union[float, str, "ParamRef"] = None, ry: Union[float, str, "ParamRef"] = None, select: "SelectFilter" = None, shapeRendering: Union[str, "ParamRef"] = None, sort: Union["SortOrder", "ChannelDomainSort"] = None, stroke: Union["ChannelValueSpec", "ParamRef"] = None, strokeDasharray: Union[str, float, "ParamRef"] = None, strokeDashoffset: Union[str, float, "ParamRef"] = None, strokeLinecap: Union[str, "ParamRef"] = None, strokeLinejoin: Union[str, "ParamRef"] = None, strokeMiterlimit: Union[float, "ParamRef"] = None, strokeOpacity: "ChannelValueSpec" = None, strokeWidth: "ChannelValueSpec" = None, target: Union[str, "ParamRef"] = None, tip: Union[bool, "TipPointer", Dict[str, Any], "ParamRef"] = None, title: "ChannelValue" = None, x: "ChannelValueSpec" = None, y: "ChannelValueSpec" = None): + self.ariaDescription = ariaDescription + self.ariaHidden = ariaHidden + self.ariaLabel = ariaLabel + self.clip = clip + self.data = data + self.dx = dx + self.dy = dy + self.facet = facet + self.facetAnchor = facetAnchor + self.fill = fill + self.fillOpacity = fillOpacity + self.filter = filter + self.fx = fx + self.fy = fy + self.href = href + self.imageFilter = imageFilter + self.inset = inset + self.insetBottom = insetBottom + self.insetLeft = insetLeft + self.insetRight = insetRight + self.insetTop = insetTop + self.margin = margin + self.marginBottom = marginBottom + self.marginLeft = marginLeft + self.marginRight = marginRight + self.marginTop = marginTop + self.mark = mark + self.mixBlendMode = mixBlendMode + self.opacity = opacity + self.paintOrder = paintOrder + self.pointerEvents = pointerEvents + self.reverse = reverse + self.rx = rx + self.ry = ry + self.select = select + self.shapeRendering = shapeRendering + self.sort = sort + self.stroke = stroke + self.strokeDasharray = strokeDasharray + self.strokeDashoffset = strokeDashoffset + self.strokeLinecap = strokeLinecap + self.strokeLinejoin = strokeLinejoin + self.strokeMiterlimit = strokeMiterlimit + self.strokeOpacity = strokeOpacity + self.strokeWidth = strokeWidth + self.target = target + self.tip = tip + self.title = title + self.x = x + self.y = y + + +class CellX: + def __init__(self, data: "PlotMarkData", mark: str, ariaDescription: Union[str, "ParamRef"] = None, ariaHidden: Union[str, "ParamRef"] = None, ariaLabel: "ChannelValue" = None, clip: Union[str, str, bool, Any, "ParamRef"] = None, dx: Union[float, "ParamRef"] = None, dy: Union[float, "ParamRef"] = None, facet: Union[str, str, str, str, bool, Any, "ParamRef"] = None, facetAnchor: Union[str, str, str, str, str, str, str, str, str, str, str, str, str, Any, "ParamRef"] = None, fill: Union["ChannelValueSpec", "ParamRef"] = None, fillOpacity: Union["ChannelValueSpec", "ParamRef"] = None, filter: "ChannelValue" = None, fx: "ChannelValue" = None, fy: "ChannelValue" = None, href: "ChannelValue" = None, imageFilter: Union[str, "ParamRef"] = None, inset: Union[float, "ParamRef"] = None, insetBottom: Union[float, "ParamRef"] = None, insetLeft: Union[float, "ParamRef"] = None, insetRight: Union[float, "ParamRef"] = None, insetTop: Union[float, "ParamRef"] = None, margin: Union[float, "ParamRef"] = None, marginBottom: Union[float, "ParamRef"] = None, marginLeft: Union[float, "ParamRef"] = None, marginRight: Union[float, "ParamRef"] = None, marginTop: Union[float, "ParamRef"] = None, mixBlendMode: Union[str, "ParamRef"] = None, opacity: "ChannelValueSpec" = None, paintOrder: Union[str, "ParamRef"] = None, pointerEvents: Union[str, "ParamRef"] = None, reverse: Union[bool, "ParamRef"] = None, rx: Union[float, str, "ParamRef"] = None, ry: Union[float, str, "ParamRef"] = None, select: "SelectFilter" = None, shapeRendering: Union[str, "ParamRef"] = None, sort: Union["SortOrder", "ChannelDomainSort"] = None, stroke: Union["ChannelValueSpec", "ParamRef"] = None, strokeDasharray: Union[str, float, "ParamRef"] = None, strokeDashoffset: Union[str, float, "ParamRef"] = None, strokeLinecap: Union[str, "ParamRef"] = None, strokeLinejoin: Union[str, "ParamRef"] = None, strokeMiterlimit: Union[float, "ParamRef"] = None, strokeOpacity: "ChannelValueSpec" = None, strokeWidth: "ChannelValueSpec" = None, target: Union[str, "ParamRef"] = None, tip: Union[bool, "TipPointer", Dict[str, Any], "ParamRef"] = None, title: "ChannelValue" = None, x: "ChannelValueSpec" = None, y: "ChannelValueSpec" = None): + self.ariaDescription = ariaDescription + self.ariaHidden = ariaHidden + self.ariaLabel = ariaLabel + self.clip = clip + self.data = data + self.dx = dx + self.dy = dy + self.facet = facet + self.facetAnchor = facetAnchor + self.fill = fill + self.fillOpacity = fillOpacity + self.filter = filter + self.fx = fx + self.fy = fy + self.href = href + self.imageFilter = imageFilter + self.inset = inset + self.insetBottom = insetBottom + self.insetLeft = insetLeft + self.insetRight = insetRight + self.insetTop = insetTop + self.margin = margin + self.marginBottom = marginBottom + self.marginLeft = marginLeft + self.marginRight = marginRight + self.marginTop = marginTop + self.mark = mark + self.mixBlendMode = mixBlendMode + self.opacity = opacity + self.paintOrder = paintOrder + self.pointerEvents = pointerEvents + self.reverse = reverse + self.rx = rx + self.ry = ry + self.select = select + self.shapeRendering = shapeRendering + self.sort = sort + self.stroke = stroke + self.strokeDasharray = strokeDasharray + self.strokeDashoffset = strokeDashoffset + self.strokeLinecap = strokeLinecap + self.strokeLinejoin = strokeLinejoin + self.strokeMiterlimit = strokeMiterlimit + self.strokeOpacity = strokeOpacity + self.strokeWidth = strokeWidth + self.target = target + self.tip = tip + self.title = title + self.x = x + self.y = y + + +class CellY: + def __init__(self, data: "PlotMarkData", mark: str, ariaDescription: Union[str, "ParamRef"] = None, ariaHidden: Union[str, "ParamRef"] = None, ariaLabel: "ChannelValue" = None, clip: Union[str, str, bool, Any, "ParamRef"] = None, dx: Union[float, "ParamRef"] = None, dy: Union[float, "ParamRef"] = None, facet: Union[str, str, str, str, bool, Any, "ParamRef"] = None, facetAnchor: Union[str, str, str, str, str, str, str, str, str, str, str, str, str, Any, "ParamRef"] = None, fill: Union["ChannelValueSpec", "ParamRef"] = None, fillOpacity: Union["ChannelValueSpec", "ParamRef"] = None, filter: "ChannelValue" = None, fx: "ChannelValue" = None, fy: "ChannelValue" = None, href: "ChannelValue" = None, imageFilter: Union[str, "ParamRef"] = None, inset: Union[float, "ParamRef"] = None, insetBottom: Union[float, "ParamRef"] = None, insetLeft: Union[float, "ParamRef"] = None, insetRight: Union[float, "ParamRef"] = None, insetTop: Union[float, "ParamRef"] = None, margin: Union[float, "ParamRef"] = None, marginBottom: Union[float, "ParamRef"] = None, marginLeft: Union[float, "ParamRef"] = None, marginRight: Union[float, "ParamRef"] = None, marginTop: Union[float, "ParamRef"] = None, mixBlendMode: Union[str, "ParamRef"] = None, opacity: "ChannelValueSpec" = None, paintOrder: Union[str, "ParamRef"] = None, pointerEvents: Union[str, "ParamRef"] = None, reverse: Union[bool, "ParamRef"] = None, rx: Union[float, str, "ParamRef"] = None, ry: Union[float, str, "ParamRef"] = None, select: "SelectFilter" = None, shapeRendering: Union[str, "ParamRef"] = None, sort: Union["SortOrder", "ChannelDomainSort"] = None, stroke: Union["ChannelValueSpec", "ParamRef"] = None, strokeDasharray: Union[str, float, "ParamRef"] = None, strokeDashoffset: Union[str, float, "ParamRef"] = None, strokeLinecap: Union[str, "ParamRef"] = None, strokeLinejoin: Union[str, "ParamRef"] = None, strokeMiterlimit: Union[float, "ParamRef"] = None, strokeOpacity: "ChannelValueSpec" = None, strokeWidth: "ChannelValueSpec" = None, target: Union[str, "ParamRef"] = None, tip: Union[bool, "TipPointer", Dict[str, Any], "ParamRef"] = None, title: "ChannelValue" = None, x: "ChannelValueSpec" = None, y: "ChannelValueSpec" = None): + self.ariaDescription = ariaDescription + self.ariaHidden = ariaHidden + self.ariaLabel = ariaLabel + self.clip = clip + self.data = data + self.dx = dx + self.dy = dy + self.facet = facet + self.facetAnchor = facetAnchor + self.fill = fill + self.fillOpacity = fillOpacity + self.filter = filter + self.fx = fx + self.fy = fy + self.href = href + self.imageFilter = imageFilter + self.inset = inset + self.insetBottom = insetBottom + self.insetLeft = insetLeft + self.insetRight = insetRight + self.insetTop = insetTop + self.margin = margin + self.marginBottom = marginBottom + self.marginLeft = marginLeft + self.marginRight = marginRight + self.marginTop = marginTop + self.mark = mark + self.mixBlendMode = mixBlendMode + self.opacity = opacity + self.paintOrder = paintOrder + self.pointerEvents = pointerEvents + self.reverse = reverse + self.rx = rx + self.ry = ry + self.select = select + self.shapeRendering = shapeRendering + self.sort = sort + self.stroke = stroke + self.strokeDasharray = strokeDasharray + self.strokeDashoffset = strokeDashoffset + self.strokeLinecap = strokeLinecap + self.strokeLinejoin = strokeLinejoin + self.strokeMiterlimit = strokeMiterlimit + self.strokeOpacity = strokeOpacity + self.strokeWidth = strokeWidth + self.target = target + self.tip = tip + self.title = title + self.x = x + self.y = y + + +class Circle: + def __init__(self, data: "PlotMarkData", mark: str, ariaDescription: Union[str, "ParamRef"] = None, ariaHidden: Union[str, "ParamRef"] = None, ariaLabel: "ChannelValue" = None, clip: Union[str, str, bool, Any, "ParamRef"] = None, dx: Union[float, "ParamRef"] = None, dy: Union[float, "ParamRef"] = None, facet: Union[str, str, str, str, bool, Any, "ParamRef"] = None, facetAnchor: Union[str, str, str, str, str, str, str, str, str, str, str, str, str, Any, "ParamRef"] = None, fill: Union["ChannelValueSpec", "ParamRef"] = None, fillOpacity: Union["ChannelValueSpec", "ParamRef"] = None, filter: "ChannelValue" = None, frameAnchor: Union["FrameAnchor", "ParamRef"] = None, fx: "ChannelValue" = None, fy: "ChannelValue" = None, href: "ChannelValue" = None, imageFilter: Union[str, "ParamRef"] = None, margin: Union[float, "ParamRef"] = None, marginBottom: Union[float, "ParamRef"] = None, marginLeft: Union[float, "ParamRef"] = None, marginRight: Union[float, "ParamRef"] = None, marginTop: Union[float, "ParamRef"] = None, mixBlendMode: Union[str, "ParamRef"] = None, opacity: "ChannelValueSpec" = None, paintOrder: Union[str, "ParamRef"] = None, pointerEvents: Union[str, "ParamRef"] = None, r: Union["ChannelValueSpec", float, "ParamRef"] = None, reverse: Union[bool, "ParamRef"] = None, rotate: Union["ChannelValue", float, "ParamRef"] = None, select: "SelectFilter" = None, shapeRendering: Union[str, "ParamRef"] = None, sort: Union["SortOrder", "ChannelDomainSort"] = None, stroke: Union["ChannelValueSpec", "ParamRef"] = None, strokeDasharray: Union[str, float, "ParamRef"] = None, strokeDashoffset: Union[str, float, "ParamRef"] = None, strokeLinecap: Union[str, "ParamRef"] = None, strokeLinejoin: Union[str, "ParamRef"] = None, strokeMiterlimit: Union[float, "ParamRef"] = None, strokeOpacity: "ChannelValueSpec" = None, strokeWidth: "ChannelValueSpec" = None, symbol: Union["ChannelValueSpec", "SymbolType", "ParamRef"] = None, target: Union[str, "ParamRef"] = None, tip: Union[bool, "TipPointer", Dict[str, Any], "ParamRef"] = None, title: "ChannelValue" = None, x: "ChannelValueSpec" = None, y: "ChannelValueSpec" = None, z: "ChannelValue" = None): + self.ariaDescription = ariaDescription + self.ariaHidden = ariaHidden + self.ariaLabel = ariaLabel + self.clip = clip + self.data = data + self.dx = dx + self.dy = dy + self.facet = facet + self.facetAnchor = facetAnchor + self.fill = fill + self.fillOpacity = fillOpacity + self.filter = filter + self.frameAnchor = frameAnchor + self.fx = fx + self.fy = fy + self.href = href + self.imageFilter = imageFilter + self.margin = margin + self.marginBottom = marginBottom + self.marginLeft = marginLeft + self.marginRight = marginRight + self.marginTop = marginTop + self.mark = mark + self.mixBlendMode = mixBlendMode + self.opacity = opacity + self.paintOrder = paintOrder + self.pointerEvents = pointerEvents + self.r = r + self.reverse = reverse + self.rotate = rotate + self.select = select + self.shapeRendering = shapeRendering + self.sort = sort + self.stroke = stroke + self.strokeDasharray = strokeDasharray + self.strokeDashoffset = strokeDashoffset + self.strokeLinecap = strokeLinecap + self.strokeLinejoin = strokeLinejoin + self.strokeMiterlimit = strokeMiterlimit + self.strokeOpacity = strokeOpacity + self.strokeWidth = strokeWidth + self.symbol = symbol + self.target = target + self.tip = tip + self.title = title + self.x = x + self.y = y + self.z = z + + +class Contour: + def __init__(self, data: "PlotMarkData", mark: str, ariaDescription: Union[str, "ParamRef"] = None, ariaHidden: Union[str, "ParamRef"] = None, ariaLabel: "ChannelValue" = None, bandwidth: Union[float, "ParamRef"] = None, clip: Union[str, str, bool, Any, "ParamRef"] = None, dx: Union[float, "ParamRef"] = None, dy: Union[float, "ParamRef"] = None, facet: Union[str, str, str, str, bool, Any, "ParamRef"] = None, facetAnchor: Union[str, str, str, str, str, str, str, str, str, str, str, str, str, Any, "ParamRef"] = None, fill: Union["ChannelValueSpec", "ParamRef"] = None, fillOpacity: Union["ChannelValueSpec", "ParamRef"] = None, filter: "ChannelValue" = None, fx: "ChannelValue" = None, fy: "ChannelValue" = None, height: Union[float, "ParamRef"] = None, href: "ChannelValue" = None, imageFilter: Union[str, "ParamRef"] = None, interpolate: Union["GridInterpolate", Any, "ParamRef"] = None, margin: Union[float, "ParamRef"] = None, marginBottom: Union[float, "ParamRef"] = None, marginLeft: Union[float, "ParamRef"] = None, marginRight: Union[float, "ParamRef"] = None, marginTop: Union[float, "ParamRef"] = None, mixBlendMode: Union[str, "ParamRef"] = None, opacity: "ChannelValueSpec" = None, pad: Union[float, "ParamRef"] = None, paintOrder: Union[str, "ParamRef"] = None, pixelSize: Union[float, "ParamRef"] = None, pointerEvents: Union[str, "ParamRef"] = None, reverse: Union[bool, "ParamRef"] = None, select: "SelectFilter" = None, shapeRendering: Union[str, "ParamRef"] = None, sort: Union["SortOrder", "ChannelDomainSort"] = None, stroke: Union["ChannelValueSpec", "ParamRef"] = None, strokeDasharray: Union[str, float, "ParamRef"] = None, strokeDashoffset: Union[str, float, "ParamRef"] = None, strokeLinecap: Union[str, "ParamRef"] = None, strokeLinejoin: Union[str, "ParamRef"] = None, strokeMiterlimit: Union[float, "ParamRef"] = None, strokeOpacity: "ChannelValueSpec" = None, strokeWidth: "ChannelValueSpec" = None, target: Union[str, "ParamRef"] = None, thresholds: Union[float, List[float], "ParamRef"] = None, tip: Union[bool, "TipPointer", Dict[str, Any], "ParamRef"] = None, title: "ChannelValue" = None, width: Union[float, "ParamRef"] = None, x: "ChannelValueSpec" = None, y: "ChannelValueSpec" = None): + self.ariaDescription = ariaDescription + self.ariaHidden = ariaHidden + self.ariaLabel = ariaLabel + self.bandwidth = bandwidth + self.clip = clip + self.data = data + self.dx = dx + self.dy = dy + self.facet = facet + self.facetAnchor = facetAnchor + self.fill = fill + self.fillOpacity = fillOpacity + self.filter = filter + self.fx = fx + self.fy = fy + self.height = height + self.href = href + self.imageFilter = imageFilter + self.interpolate = interpolate + self.margin = margin + self.marginBottom = marginBottom + self.marginLeft = marginLeft + self.marginRight = marginRight + self.marginTop = marginTop + self.mark = mark + self.mixBlendMode = mixBlendMode + self.opacity = opacity + self.pad = pad + self.paintOrder = paintOrder + self.pixelSize = pixelSize + self.pointerEvents = pointerEvents + self.reverse = reverse + self.select = select + self.shapeRendering = shapeRendering + self.sort = sort + self.stroke = stroke + self.strokeDasharray = strokeDasharray + self.strokeDashoffset = strokeDashoffset + self.strokeLinecap = strokeLinecap + self.strokeLinejoin = strokeLinejoin + self.strokeMiterlimit = strokeMiterlimit + self.strokeOpacity = strokeOpacity + self.strokeWidth = strokeWidth + self.target = target + self.thresholds = thresholds + self.tip = tip + self.title = title + self.width = width + self.x = x + self.y = y + + +class DelaunayLink: + def __init__(self, data: "PlotMarkData", mark: str, ariaDescription: Union[str, "ParamRef"] = None, ariaHidden: Union[str, "ParamRef"] = None, ariaLabel: "ChannelValue" = None, clip: Union[str, str, bool, Any, "ParamRef"] = None, curve: Union["Curve", "ParamRef"] = None, dx: Union[float, "ParamRef"] = None, dy: Union[float, "ParamRef"] = None, facet: Union[str, str, str, str, bool, Any, "ParamRef"] = None, facetAnchor: Union[str, str, str, str, str, str, str, str, str, str, str, str, str, Any, "ParamRef"] = None, fill: Union["ChannelValueSpec", "ParamRef"] = None, fillOpacity: Union["ChannelValueSpec", "ParamRef"] = None, filter: "ChannelValue" = None, fx: "ChannelValue" = None, fy: "ChannelValue" = None, href: "ChannelValue" = None, imageFilter: Union[str, "ParamRef"] = None, margin: Union[float, "ParamRef"] = None, marginBottom: Union[float, "ParamRef"] = None, marginLeft: Union[float, "ParamRef"] = None, marginRight: Union[float, "ParamRef"] = None, marginTop: Union[float, "ParamRef"] = None, marker: Union["MarkerName", str, bool, Any, "ParamRef"] = None, markerEnd: Union["MarkerName", str, bool, Any, "ParamRef"] = None, markerMid: Union["MarkerName", str, bool, Any, "ParamRef"] = None, markerStart: Union["MarkerName", str, bool, Any, "ParamRef"] = None, mixBlendMode: Union[str, "ParamRef"] = None, opacity: "ChannelValueSpec" = None, paintOrder: Union[str, "ParamRef"] = None, pointerEvents: Union[str, "ParamRef"] = None, reverse: Union[bool, "ParamRef"] = None, select: "SelectFilter" = None, shapeRendering: Union[str, "ParamRef"] = None, sort: Union["SortOrder", "ChannelDomainSort"] = None, stroke: Union["ChannelValueSpec", "ParamRef"] = None, strokeDasharray: Union[str, float, "ParamRef"] = None, strokeDashoffset: Union[str, float, "ParamRef"] = None, strokeLinecap: Union[str, "ParamRef"] = None, strokeLinejoin: Union[str, "ParamRef"] = None, strokeMiterlimit: Union[float, "ParamRef"] = None, strokeOpacity: "ChannelValueSpec" = None, strokeWidth: "ChannelValueSpec" = None, target: Union[str, "ParamRef"] = None, tension: Union[float, "ParamRef"] = None, tip: Union[bool, "TipPointer", Dict[str, Any], "ParamRef"] = None, title: "ChannelValue" = None, x: "ChannelValueSpec" = None, y: "ChannelValueSpec" = None, z: "ChannelValue" = None): + self.ariaDescription = ariaDescription + self.ariaHidden = ariaHidden + self.ariaLabel = ariaLabel + self.clip = clip + self.curve = curve + self.data = data + self.dx = dx + self.dy = dy + self.facet = facet + self.facetAnchor = facetAnchor + self.fill = fill + self.fillOpacity = fillOpacity + self.filter = filter + self.fx = fx + self.fy = fy + self.href = href + self.imageFilter = imageFilter + self.margin = margin + self.marginBottom = marginBottom + self.marginLeft = marginLeft + self.marginRight = marginRight + self.marginTop = marginTop + self.mark = mark + self.marker = marker + self.markerEnd = markerEnd + self.markerMid = markerMid + self.markerStart = markerStart + self.mixBlendMode = mixBlendMode + self.opacity = opacity + self.paintOrder = paintOrder + self.pointerEvents = pointerEvents + self.reverse = reverse + self.select = select + self.shapeRendering = shapeRendering + self.sort = sort + self.stroke = stroke + self.strokeDasharray = strokeDasharray + self.strokeDashoffset = strokeDashoffset + self.strokeLinecap = strokeLinecap + self.strokeLinejoin = strokeLinejoin + self.strokeMiterlimit = strokeMiterlimit + self.strokeOpacity = strokeOpacity + self.strokeWidth = strokeWidth + self.target = target + self.tension = tension + self.tip = tip + self.title = title + self.x = x + self.y = y + self.z = z + + +class DelaunayMesh: + def __init__(self, data: "PlotMarkData", mark: str, ariaDescription: Union[str, "ParamRef"] = None, ariaHidden: Union[str, "ParamRef"] = None, ariaLabel: "ChannelValue" = None, clip: Union[str, str, bool, Any, "ParamRef"] = None, curve: Union["Curve", "ParamRef"] = None, dx: Union[float, "ParamRef"] = None, dy: Union[float, "ParamRef"] = None, facet: Union[str, str, str, str, bool, Any, "ParamRef"] = None, facetAnchor: Union[str, str, str, str, str, str, str, str, str, str, str, str, str, Any, "ParamRef"] = None, fill: Union["ChannelValueSpec", "ParamRef"] = None, fillOpacity: Union["ChannelValueSpec", "ParamRef"] = None, filter: "ChannelValue" = None, fx: "ChannelValue" = None, fy: "ChannelValue" = None, href: "ChannelValue" = None, imageFilter: Union[str, "ParamRef"] = None, margin: Union[float, "ParamRef"] = None, marginBottom: Union[float, "ParamRef"] = None, marginLeft: Union[float, "ParamRef"] = None, marginRight: Union[float, "ParamRef"] = None, marginTop: Union[float, "ParamRef"] = None, marker: Union["MarkerName", str, bool, Any, "ParamRef"] = None, markerEnd: Union["MarkerName", str, bool, Any, "ParamRef"] = None, markerMid: Union["MarkerName", str, bool, Any, "ParamRef"] = None, markerStart: Union["MarkerName", str, bool, Any, "ParamRef"] = None, mixBlendMode: Union[str, "ParamRef"] = None, opacity: "ChannelValueSpec" = None, paintOrder: Union[str, "ParamRef"] = None, pointerEvents: Union[str, "ParamRef"] = None, reverse: Union[bool, "ParamRef"] = None, select: "SelectFilter" = None, shapeRendering: Union[str, "ParamRef"] = None, sort: Union["SortOrder", "ChannelDomainSort"] = None, stroke: Union["ChannelValueSpec", "ParamRef"] = None, strokeDasharray: Union[str, float, "ParamRef"] = None, strokeDashoffset: Union[str, float, "ParamRef"] = None, strokeLinecap: Union[str, "ParamRef"] = None, strokeLinejoin: Union[str, "ParamRef"] = None, strokeMiterlimit: Union[float, "ParamRef"] = None, strokeOpacity: "ChannelValueSpec" = None, strokeWidth: "ChannelValueSpec" = None, target: Union[str, "ParamRef"] = None, tension: Union[float, "ParamRef"] = None, tip: Union[bool, "TipPointer", Dict[str, Any], "ParamRef"] = None, title: "ChannelValue" = None, x: "ChannelValueSpec" = None, y: "ChannelValueSpec" = None, z: "ChannelValue" = None): + self.ariaDescription = ariaDescription + self.ariaHidden = ariaHidden + self.ariaLabel = ariaLabel + self.clip = clip + self.curve = curve + self.data = data + self.dx = dx + self.dy = dy + self.facet = facet + self.facetAnchor = facetAnchor + self.fill = fill + self.fillOpacity = fillOpacity + self.filter = filter + self.fx = fx + self.fy = fy + self.href = href + self.imageFilter = imageFilter + self.margin = margin + self.marginBottom = marginBottom + self.marginLeft = marginLeft + self.marginRight = marginRight + self.marginTop = marginTop + self.mark = mark + self.marker = marker + self.markerEnd = markerEnd + self.markerMid = markerMid + self.markerStart = markerStart + self.mixBlendMode = mixBlendMode + self.opacity = opacity + self.paintOrder = paintOrder + self.pointerEvents = pointerEvents + self.reverse = reverse + self.select = select + self.shapeRendering = shapeRendering + self.sort = sort + self.stroke = stroke + self.strokeDasharray = strokeDasharray + self.strokeDashoffset = strokeDashoffset + self.strokeLinecap = strokeLinecap + self.strokeLinejoin = strokeLinejoin + self.strokeMiterlimit = strokeMiterlimit + self.strokeOpacity = strokeOpacity + self.strokeWidth = strokeWidth + self.target = target + self.tension = tension + self.tip = tip + self.title = title + self.x = x + self.y = y + self.z = z + + +class DenseLine: + def __init__(self, data: "PlotMarkData", mark: str, ariaDescription: Union[str, "ParamRef"] = None, ariaHidden: Union[str, "ParamRef"] = None, ariaLabel: "ChannelValue" = None, bandwidth: Union[float, "ParamRef"] = None, clip: Union[str, str, bool, Any, "ParamRef"] = None, dx: Union[float, "ParamRef"] = None, dy: Union[float, "ParamRef"] = None, facet: Union[str, str, str, str, bool, Any, "ParamRef"] = None, facetAnchor: Union[str, str, str, str, str, str, str, str, str, str, str, str, str, Any, "ParamRef"] = None, fill: Union["ChannelValueSpec", "ParamRef"] = None, fillOpacity: Union["ChannelValueSpec", "ParamRef"] = None, filter: "ChannelValue" = None, fx: "ChannelValue" = None, fy: "ChannelValue" = None, height: Union[float, "ParamRef"] = None, href: "ChannelValue" = None, imageFilter: Union[str, "ParamRef"] = None, imageRendering: Union[str, "ParamRef"] = None, interpolate: Union["GridInterpolate", Any, "ParamRef"] = None, margin: Union[float, "ParamRef"] = None, marginBottom: Union[float, "ParamRef"] = None, marginLeft: Union[float, "ParamRef"] = None, marginRight: Union[float, "ParamRef"] = None, marginTop: Union[float, "ParamRef"] = None, mixBlendMode: Union[str, "ParamRef"] = None, normalize: Union[bool, "ParamRef"] = None, opacity: "ChannelValueSpec" = None, pad: Union[float, "ParamRef"] = None, paintOrder: Union[str, "ParamRef"] = None, pixelSize: Union[float, "ParamRef"] = None, pointerEvents: Union[str, "ParamRef"] = None, reverse: Union[bool, "ParamRef"] = None, select: "SelectFilter" = None, shapeRendering: Union[str, "ParamRef"] = None, sort: Union["SortOrder", "ChannelDomainSort"] = None, stroke: Union["ChannelValueSpec", "ParamRef"] = None, strokeDasharray: Union[str, float, "ParamRef"] = None, strokeDashoffset: Union[str, float, "ParamRef"] = None, strokeLinecap: Union[str, "ParamRef"] = None, strokeLinejoin: Union[str, "ParamRef"] = None, strokeMiterlimit: Union[float, "ParamRef"] = None, strokeOpacity: "ChannelValueSpec" = None, strokeWidth: "ChannelValueSpec" = None, target: Union[str, "ParamRef"] = None, tip: Union[bool, "TipPointer", Dict[str, Any], "ParamRef"] = None, title: "ChannelValue" = None, width: Union[float, "ParamRef"] = None, x: "ChannelValueSpec" = None, y: "ChannelValueSpec" = None, z: "ChannelValue" = None): + self.ariaDescription = ariaDescription + self.ariaHidden = ariaHidden + self.ariaLabel = ariaLabel + self.bandwidth = bandwidth + self.clip = clip + self.data = data + self.dx = dx + self.dy = dy + self.facet = facet + self.facetAnchor = facetAnchor + self.fill = fill + self.fillOpacity = fillOpacity + self.filter = filter + self.fx = fx + self.fy = fy + self.height = height + self.href = href + self.imageFilter = imageFilter + self.imageRendering = imageRendering + self.interpolate = interpolate + self.margin = margin + self.marginBottom = marginBottom + self.marginLeft = marginLeft + self.marginRight = marginRight + self.marginTop = marginTop + self.mark = mark + self.mixBlendMode = mixBlendMode + self.normalize = normalize + self.opacity = opacity + self.pad = pad + self.paintOrder = paintOrder + self.pixelSize = pixelSize + self.pointerEvents = pointerEvents + self.reverse = reverse + self.select = select + self.shapeRendering = shapeRendering + self.sort = sort + self.stroke = stroke + self.strokeDasharray = strokeDasharray + self.strokeDashoffset = strokeDashoffset + self.strokeLinecap = strokeLinecap + self.strokeLinejoin = strokeLinejoin + self.strokeMiterlimit = strokeMiterlimit + self.strokeOpacity = strokeOpacity + self.strokeWidth = strokeWidth + self.target = target + self.tip = tip + self.title = title + self.width = width + self.x = x + self.y = y + self.z = z + + +class Density: + def __init__(self, data: "PlotMarkData", mark: str, ariaDescription: Union[str, "ParamRef"] = None, ariaHidden: Union[str, "ParamRef"] = None, ariaLabel: "ChannelValue" = None, bandwidth: Union[float, "ParamRef"] = None, clip: Union[str, str, bool, Any, "ParamRef"] = None, dx: Union[float, "ParamRef"] = None, dy: Union[float, "ParamRef"] = None, facet: Union[str, str, str, str, bool, Any, "ParamRef"] = None, facetAnchor: Union[str, str, str, str, str, str, str, str, str, str, str, str, str, Any, "ParamRef"] = None, fill: Union["ChannelValueSpec", "ParamRef"] = None, fillOpacity: Union["ChannelValueSpec", "ParamRef"] = None, filter: "ChannelValue" = None, fontFamily: Union[str, "ParamRef"] = None, fontSize: Union["ChannelValue", "ParamRef"] = None, fontStyle: Union[str, "ParamRef"] = None, fontVariant: Union[str, "ParamRef"] = None, fontWeight: Union[str, float, "ParamRef"] = None, frameAnchor: Union["FrameAnchor", "ParamRef"] = None, fx: "ChannelValue" = None, fy: "ChannelValue" = None, height: Union[float, "ParamRef"] = None, href: "ChannelValue" = None, imageFilter: Union[str, "ParamRef"] = None, interpolate: Union["GridInterpolate", Any, "ParamRef"] = None, lineHeight: Union[float, "ParamRef"] = None, lineWidth: Union[float, "ParamRef"] = None, margin: Union[float, "ParamRef"] = None, marginBottom: Union[float, "ParamRef"] = None, marginLeft: Union[float, "ParamRef"] = None, marginRight: Union[float, "ParamRef"] = None, marginTop: Union[float, "ParamRef"] = None, mixBlendMode: Union[str, "ParamRef"] = None, monospace: Union[bool, "ParamRef"] = None, opacity: "ChannelValueSpec" = None, pad: Union[float, "ParamRef"] = None, paintOrder: Union[str, "ParamRef"] = None, pixelSize: Union[float, "ParamRef"] = None, pointerEvents: Union[str, "ParamRef"] = None, r: Union["ChannelValueSpec", float, "ParamRef"] = None, reverse: Union[bool, "ParamRef"] = None, rotate: Union["ChannelValue", float, "ParamRef"] = None, select: "SelectFilter" = None, shapeRendering: Union[str, "ParamRef"] = None, sort: Union["SortOrder", "ChannelDomainSort"] = None, stroke: Union["ChannelValueSpec", "ParamRef"] = None, strokeDasharray: Union[str, float, "ParamRef"] = None, strokeDashoffset: Union[str, float, "ParamRef"] = None, strokeLinecap: Union[str, "ParamRef"] = None, strokeLinejoin: Union[str, "ParamRef"] = None, strokeMiterlimit: Union[float, "ParamRef"] = None, strokeOpacity: "ChannelValueSpec" = None, strokeWidth: "ChannelValueSpec" = None, symbol: Union["ChannelValueSpec", "SymbolType", "ParamRef"] = None, target: Union[str, "ParamRef"] = None, textAnchor: Union[str, str, str, "ParamRef"] = None, textOverflow: Union[Any, str, str, str, str, str, str, str, "ParamRef"] = None, tip: Union[bool, "TipPointer", Dict[str, Any], "ParamRef"] = None, title: "ChannelValue" = None, type: Union[str, str, str, str, str, "ParamRef"] = None, width: Union[float, "ParamRef"] = None, x: "ChannelValueSpec" = None, y: "ChannelValueSpec" = None, z: "ChannelValue" = None): + self.ariaDescription = ariaDescription + self.ariaHidden = ariaHidden + self.ariaLabel = ariaLabel + self.bandwidth = bandwidth + self.clip = clip + self.data = data + self.dx = dx + self.dy = dy + self.facet = facet + self.facetAnchor = facetAnchor + self.fill = fill + self.fillOpacity = fillOpacity + self.filter = filter + self.fontFamily = fontFamily + self.fontSize = fontSize + self.fontStyle = fontStyle + self.fontVariant = fontVariant + self.fontWeight = fontWeight + self.frameAnchor = frameAnchor + self.fx = fx + self.fy = fy + self.height = height + self.href = href + self.imageFilter = imageFilter + self.interpolate = interpolate + self.lineHeight = lineHeight + self.lineWidth = lineWidth + self.margin = margin + self.marginBottom = marginBottom + self.marginLeft = marginLeft + self.marginRight = marginRight + self.marginTop = marginTop + self.mark = mark + self.mixBlendMode = mixBlendMode + self.monospace = monospace + self.opacity = opacity + self.pad = pad + self.paintOrder = paintOrder + self.pixelSize = pixelSize + self.pointerEvents = pointerEvents + self.r = r + self.reverse = reverse + self.rotate = rotate + self.select = select + self.shapeRendering = shapeRendering + self.sort = sort + self.stroke = stroke + self.strokeDasharray = strokeDasharray + self.strokeDashoffset = strokeDashoffset + self.strokeLinecap = strokeLinecap + self.strokeLinejoin = strokeLinejoin + self.strokeMiterlimit = strokeMiterlimit + self.strokeOpacity = strokeOpacity + self.strokeWidth = strokeWidth + self.symbol = symbol + self.target = target + self.textAnchor = textAnchor + self.textOverflow = textOverflow + self.tip = tip + self.title = title + self.type = type + self.width = width + self.x = x + self.y = y + self.z = z + + +class Dot: + def __init__(self, data: "PlotMarkData", mark: str, ariaDescription: Union[str, "ParamRef"] = None, ariaHidden: Union[str, "ParamRef"] = None, ariaLabel: "ChannelValue" = None, clip: Union[str, str, bool, Any, "ParamRef"] = None, dx: Union[float, "ParamRef"] = None, dy: Union[float, "ParamRef"] = None, facet: Union[str, str, str, str, bool, Any, "ParamRef"] = None, facetAnchor: Union[str, str, str, str, str, str, str, str, str, str, str, str, str, Any, "ParamRef"] = None, fill: Union["ChannelValueSpec", "ParamRef"] = None, fillOpacity: Union["ChannelValueSpec", "ParamRef"] = None, filter: "ChannelValue" = None, frameAnchor: Union["FrameAnchor", "ParamRef"] = None, fx: "ChannelValue" = None, fy: "ChannelValue" = None, href: "ChannelValue" = None, imageFilter: Union[str, "ParamRef"] = None, margin: Union[float, "ParamRef"] = None, marginBottom: Union[float, "ParamRef"] = None, marginLeft: Union[float, "ParamRef"] = None, marginRight: Union[float, "ParamRef"] = None, marginTop: Union[float, "ParamRef"] = None, mixBlendMode: Union[str, "ParamRef"] = None, opacity: "ChannelValueSpec" = None, paintOrder: Union[str, "ParamRef"] = None, pointerEvents: Union[str, "ParamRef"] = None, r: Union["ChannelValueSpec", float, "ParamRef"] = None, reverse: Union[bool, "ParamRef"] = None, rotate: Union["ChannelValue", float, "ParamRef"] = None, select: "SelectFilter" = None, shapeRendering: Union[str, "ParamRef"] = None, sort: Union["SortOrder", "ChannelDomainSort"] = None, stroke: Union["ChannelValueSpec", "ParamRef"] = None, strokeDasharray: Union[str, float, "ParamRef"] = None, strokeDashoffset: Union[str, float, "ParamRef"] = None, strokeLinecap: Union[str, "ParamRef"] = None, strokeLinejoin: Union[str, "ParamRef"] = None, strokeMiterlimit: Union[float, "ParamRef"] = None, strokeOpacity: "ChannelValueSpec" = None, strokeWidth: "ChannelValueSpec" = None, symbol: Union["ChannelValueSpec", "SymbolType", "ParamRef"] = None, target: Union[str, "ParamRef"] = None, tip: Union[bool, "TipPointer", Dict[str, Any], "ParamRef"] = None, title: "ChannelValue" = None, x: "ChannelValueSpec" = None, y: "ChannelValueSpec" = None, z: "ChannelValue" = None): + self.ariaDescription = ariaDescription + self.ariaHidden = ariaHidden + self.ariaLabel = ariaLabel + self.clip = clip + self.data = data + self.dx = dx + self.dy = dy + self.facet = facet + self.facetAnchor = facetAnchor + self.fill = fill + self.fillOpacity = fillOpacity + self.filter = filter + self.frameAnchor = frameAnchor + self.fx = fx + self.fy = fy + self.href = href + self.imageFilter = imageFilter + self.margin = margin + self.marginBottom = marginBottom + self.marginLeft = marginLeft + self.marginRight = marginRight + self.marginTop = marginTop + self.mark = mark + self.mixBlendMode = mixBlendMode + self.opacity = opacity + self.paintOrder = paintOrder + self.pointerEvents = pointerEvents + self.r = r + self.reverse = reverse + self.rotate = rotate + self.select = select + self.shapeRendering = shapeRendering + self.sort = sort + self.stroke = stroke + self.strokeDasharray = strokeDasharray + self.strokeDashoffset = strokeDashoffset + self.strokeLinecap = strokeLinecap + self.strokeLinejoin = strokeLinejoin + self.strokeMiterlimit = strokeMiterlimit + self.strokeOpacity = strokeOpacity + self.strokeWidth = strokeWidth + self.symbol = symbol + self.target = target + self.tip = tip + self.title = title + self.x = x + self.y = y + self.z = z + + +class ErrorBarX: + def __init__(self, data: "PlotMarkData", mark: str, x: "ChannelValueSpec", ariaDescription: Union[str, "ParamRef"] = None, ariaHidden: Union[str, "ParamRef"] = None, ariaLabel: "ChannelValue" = None, ci: Union[float, "ParamRef"] = None, clip: Union[str, str, bool, Any, "ParamRef"] = None, dx: Union[float, "ParamRef"] = None, dy: Union[float, "ParamRef"] = None, facet: Union[str, str, str, str, bool, Any, "ParamRef"] = None, facetAnchor: Union[str, str, str, str, str, str, str, str, str, str, str, str, str, Any, "ParamRef"] = None, fill: Union["ChannelValueSpec", "ParamRef"] = None, fillOpacity: Union["ChannelValueSpec", "ParamRef"] = None, filter: "ChannelValue" = None, fx: "ChannelValue" = None, fy: "ChannelValue" = None, href: "ChannelValue" = None, imageFilter: Union[str, "ParamRef"] = None, margin: Union[float, "ParamRef"] = None, marginBottom: Union[float, "ParamRef"] = None, marginLeft: Union[float, "ParamRef"] = None, marginRight: Union[float, "ParamRef"] = None, marginTop: Union[float, "ParamRef"] = None, marker: Union["MarkerName", str, bool, Any, "ParamRef"] = None, markerEnd: Union["MarkerName", str, bool, Any, "ParamRef"] = None, markerMid: Union["MarkerName", str, bool, Any, "ParamRef"] = None, markerStart: Union["MarkerName", str, bool, Any, "ParamRef"] = None, mixBlendMode: Union[str, "ParamRef"] = None, opacity: "ChannelValueSpec" = None, paintOrder: Union[str, "ParamRef"] = None, pointerEvents: Union[str, "ParamRef"] = None, reverse: Union[bool, "ParamRef"] = None, select: "SelectFilter" = None, shapeRendering: Union[str, "ParamRef"] = None, sort: Union["SortOrder", "ChannelDomainSort"] = None, stroke: Union["ChannelValueSpec", "ParamRef"] = None, strokeDasharray: Union[str, float, "ParamRef"] = None, strokeDashoffset: Union[str, float, "ParamRef"] = None, strokeLinecap: Union[str, "ParamRef"] = None, strokeLinejoin: Union[str, "ParamRef"] = None, strokeMiterlimit: Union[float, "ParamRef"] = None, strokeOpacity: "ChannelValueSpec" = None, strokeWidth: "ChannelValueSpec" = None, target: Union[str, "ParamRef"] = None, tip: Union[bool, "TipPointer", Dict[str, Any], "ParamRef"] = None, title: "ChannelValue" = None, y: "ChannelValueSpec" = None, z: "ChannelValue" = None): + self.ariaDescription = ariaDescription + self.ariaHidden = ariaHidden + self.ariaLabel = ariaLabel + self.ci = ci + self.clip = clip + self.data = data + self.dx = dx + self.dy = dy + self.facet = facet + self.facetAnchor = facetAnchor + self.fill = fill + self.fillOpacity = fillOpacity + self.filter = filter + self.fx = fx + self.fy = fy + self.href = href + self.imageFilter = imageFilter + self.margin = margin + self.marginBottom = marginBottom + self.marginLeft = marginLeft + self.marginRight = marginRight + self.marginTop = marginTop + self.mark = mark + self.marker = marker + self.markerEnd = markerEnd + self.markerMid = markerMid + self.markerStart = markerStart + self.mixBlendMode = mixBlendMode + self.opacity = opacity + self.paintOrder = paintOrder + self.pointerEvents = pointerEvents + self.reverse = reverse + self.select = select + self.shapeRendering = shapeRendering + self.sort = sort + self.stroke = stroke + self.strokeDasharray = strokeDasharray + self.strokeDashoffset = strokeDashoffset + self.strokeLinecap = strokeLinecap + self.strokeLinejoin = strokeLinejoin + self.strokeMiterlimit = strokeMiterlimit + self.strokeOpacity = strokeOpacity + self.strokeWidth = strokeWidth + self.target = target + self.tip = tip + self.title = title + self.x = x + self.y = y + self.z = z + + +class ErrorBarY: + def __init__(self, data: "PlotMarkData", mark: str, y: "ChannelValueSpec", ariaDescription: Union[str, "ParamRef"] = None, ariaHidden: Union[str, "ParamRef"] = None, ariaLabel: "ChannelValue" = None, ci: Union[float, "ParamRef"] = None, clip: Union[str, str, bool, Any, "ParamRef"] = None, dx: Union[float, "ParamRef"] = None, dy: Union[float, "ParamRef"] = None, facet: Union[str, str, str, str, bool, Any, "ParamRef"] = None, facetAnchor: Union[str, str, str, str, str, str, str, str, str, str, str, str, str, Any, "ParamRef"] = None, fill: Union["ChannelValueSpec", "ParamRef"] = None, fillOpacity: Union["ChannelValueSpec", "ParamRef"] = None, filter: "ChannelValue" = None, fx: "ChannelValue" = None, fy: "ChannelValue" = None, href: "ChannelValue" = None, imageFilter: Union[str, "ParamRef"] = None, margin: Union[float, "ParamRef"] = None, marginBottom: Union[float, "ParamRef"] = None, marginLeft: Union[float, "ParamRef"] = None, marginRight: Union[float, "ParamRef"] = None, marginTop: Union[float, "ParamRef"] = None, marker: Union["MarkerName", str, bool, Any, "ParamRef"] = None, markerEnd: Union["MarkerName", str, bool, Any, "ParamRef"] = None, markerMid: Union["MarkerName", str, bool, Any, "ParamRef"] = None, markerStart: Union["MarkerName", str, bool, Any, "ParamRef"] = None, mixBlendMode: Union[str, "ParamRef"] = None, opacity: "ChannelValueSpec" = None, paintOrder: Union[str, "ParamRef"] = None, pointerEvents: Union[str, "ParamRef"] = None, reverse: Union[bool, "ParamRef"] = None, select: "SelectFilter" = None, shapeRendering: Union[str, "ParamRef"] = None, sort: Union["SortOrder", "ChannelDomainSort"] = None, stroke: Union["ChannelValueSpec", "ParamRef"] = None, strokeDasharray: Union[str, float, "ParamRef"] = None, strokeDashoffset: Union[str, float, "ParamRef"] = None, strokeLinecap: Union[str, "ParamRef"] = None, strokeLinejoin: Union[str, "ParamRef"] = None, strokeMiterlimit: Union[float, "ParamRef"] = None, strokeOpacity: "ChannelValueSpec" = None, strokeWidth: "ChannelValueSpec" = None, target: Union[str, "ParamRef"] = None, tip: Union[bool, "TipPointer", Dict[str, Any], "ParamRef"] = None, title: "ChannelValue" = None, x: "ChannelValueSpec" = None, z: "ChannelValue" = None): + self.ariaDescription = ariaDescription + self.ariaHidden = ariaHidden + self.ariaLabel = ariaLabel + self.ci = ci + self.clip = clip + self.data = data + self.dx = dx + self.dy = dy + self.facet = facet + self.facetAnchor = facetAnchor + self.fill = fill + self.fillOpacity = fillOpacity + self.filter = filter + self.fx = fx + self.fy = fy + self.href = href + self.imageFilter = imageFilter + self.margin = margin + self.marginBottom = marginBottom + self.marginLeft = marginLeft + self.marginRight = marginRight + self.marginTop = marginTop + self.mark = mark + self.marker = marker + self.markerEnd = markerEnd + self.markerMid = markerMid + self.markerStart = markerStart + self.mixBlendMode = mixBlendMode + self.opacity = opacity + self.paintOrder = paintOrder + self.pointerEvents = pointerEvents + self.reverse = reverse + self.select = select + self.shapeRendering = shapeRendering + self.sort = sort + self.stroke = stroke + self.strokeDasharray = strokeDasharray + self.strokeDashoffset = strokeDashoffset + self.strokeLinecap = strokeLinecap + self.strokeLinejoin = strokeLinejoin + self.strokeMiterlimit = strokeMiterlimit + self.strokeOpacity = strokeOpacity + self.strokeWidth = strokeWidth + self.target = target + self.tip = tip + self.title = title + self.x = x + self.y = y + self.z = z + + +class Frame: + def __init__(self, mark: str, anchor: Union[str, str, str, str, Any, "ParamRef"] = None, ariaDescription: Union[str, "ParamRef"] = None, ariaHidden: Union[str, "ParamRef"] = None, ariaLabel: "ChannelValue" = None, clip: Union[str, str, bool, Any, "ParamRef"] = None, dx: Union[float, "ParamRef"] = None, dy: Union[float, "ParamRef"] = None, facet: Union[str, str, str, str, bool, Any, "ParamRef"] = None, facetAnchor: Union[str, str, str, str, str, str, str, str, str, str, str, str, str, Any, "ParamRef"] = None, fill: Union["ChannelValueSpec", "ParamRef"] = None, fillOpacity: Union["ChannelValueSpec", "ParamRef"] = None, filter: "ChannelValue" = None, fx: "ChannelValue" = None, fy: "ChannelValue" = None, href: "ChannelValue" = None, imageFilter: Union[str, "ParamRef"] = None, inset: Union[float, "ParamRef"] = None, insetBottom: Union[float, "ParamRef"] = None, insetLeft: Union[float, "ParamRef"] = None, insetRight: Union[float, "ParamRef"] = None, insetTop: Union[float, "ParamRef"] = None, margin: Union[float, "ParamRef"] = None, marginBottom: Union[float, "ParamRef"] = None, marginLeft: Union[float, "ParamRef"] = None, marginRight: Union[float, "ParamRef"] = None, marginTop: Union[float, "ParamRef"] = None, mixBlendMode: Union[str, "ParamRef"] = None, opacity: "ChannelValueSpec" = None, paintOrder: Union[str, "ParamRef"] = None, pointerEvents: Union[str, "ParamRef"] = None, reverse: Union[bool, "ParamRef"] = None, rx: Union[float, str, "ParamRef"] = None, ry: Union[float, str, "ParamRef"] = None, select: "SelectFilter" = None, shapeRendering: Union[str, "ParamRef"] = None, sort: Union["SortOrder", "ChannelDomainSort"] = None, stroke: Union["ChannelValueSpec", "ParamRef"] = None, strokeDasharray: Union[str, float, "ParamRef"] = None, strokeDashoffset: Union[str, float, "ParamRef"] = None, strokeLinecap: Union[str, "ParamRef"] = None, strokeLinejoin: Union[str, "ParamRef"] = None, strokeMiterlimit: Union[float, "ParamRef"] = None, strokeOpacity: "ChannelValueSpec" = None, strokeWidth: "ChannelValueSpec" = None, target: Union[str, "ParamRef"] = None, tip: Union[bool, "TipPointer", Dict[str, Any], "ParamRef"] = None, title: "ChannelValue" = None): + self.anchor = anchor + self.ariaDescription = ariaDescription + self.ariaHidden = ariaHidden + self.ariaLabel = ariaLabel + self.clip = clip + self.dx = dx + self.dy = dy + self.facet = facet + self.facetAnchor = facetAnchor + self.fill = fill + self.fillOpacity = fillOpacity + self.filter = filter + self.fx = fx + self.fy = fy + self.href = href + self.imageFilter = imageFilter + self.inset = inset + self.insetBottom = insetBottom + self.insetLeft = insetLeft + self.insetRight = insetRight + self.insetTop = insetTop + self.margin = margin + self.marginBottom = marginBottom + self.marginLeft = marginLeft + self.marginRight = marginRight + self.marginTop = marginTop + self.mark = mark + self.mixBlendMode = mixBlendMode + self.opacity = opacity + self.paintOrder = paintOrder + self.pointerEvents = pointerEvents + self.reverse = reverse + self.rx = rx + self.ry = ry + self.select = select + self.shapeRendering = shapeRendering + self.sort = sort + self.stroke = stroke + self.strokeDasharray = strokeDasharray + self.strokeDashoffset = strokeDashoffset + self.strokeLinecap = strokeLinecap + self.strokeLinejoin = strokeLinejoin + self.strokeMiterlimit = strokeMiterlimit + self.strokeOpacity = strokeOpacity + self.strokeWidth = strokeWidth + self.target = target + self.tip = tip + self.title = title + + +class Geo: + def __init__(self, data: "PlotMarkData", mark: str, ariaDescription: Union[str, "ParamRef"] = None, ariaHidden: Union[str, "ParamRef"] = None, ariaLabel: "ChannelValue" = None, clip: Union[str, str, bool, Any, "ParamRef"] = None, dx: Union[float, "ParamRef"] = None, dy: Union[float, "ParamRef"] = None, facet: Union[str, str, str, str, bool, Any, "ParamRef"] = None, facetAnchor: Union[str, str, str, str, str, str, str, str, str, str, str, str, str, Any, "ParamRef"] = None, fill: Union["ChannelValueSpec", "ParamRef"] = None, fillOpacity: Union["ChannelValueSpec", "ParamRef"] = None, filter: "ChannelValue" = None, fx: "ChannelValue" = None, fy: "ChannelValue" = None, geometry: "ChannelValue" = None, href: "ChannelValue" = None, imageFilter: Union[str, "ParamRef"] = None, margin: Union[float, "ParamRef"] = None, marginBottom: Union[float, "ParamRef"] = None, marginLeft: Union[float, "ParamRef"] = None, marginRight: Union[float, "ParamRef"] = None, marginTop: Union[float, "ParamRef"] = None, mixBlendMode: Union[str, "ParamRef"] = None, opacity: "ChannelValueSpec" = None, paintOrder: Union[str, "ParamRef"] = None, pointerEvents: Union[str, "ParamRef"] = None, r: Union["ChannelValueSpec", "ParamRef"] = None, reverse: Union[bool, "ParamRef"] = None, select: "SelectFilter" = None, shapeRendering: Union[str, "ParamRef"] = None, sort: Union["SortOrder", "ChannelDomainSort"] = None, stroke: Union["ChannelValueSpec", "ParamRef"] = None, strokeDasharray: Union[str, float, "ParamRef"] = None, strokeDashoffset: Union[str, float, "ParamRef"] = None, strokeLinecap: Union[str, "ParamRef"] = None, strokeLinejoin: Union[str, "ParamRef"] = None, strokeMiterlimit: Union[float, "ParamRef"] = None, strokeOpacity: "ChannelValueSpec" = None, strokeWidth: "ChannelValueSpec" = None, target: Union[str, "ParamRef"] = None, tip: Union[bool, "TipPointer", Dict[str, Any], "ParamRef"] = None, title: "ChannelValue" = None): + self.ariaDescription = ariaDescription + self.ariaHidden = ariaHidden + self.ariaLabel = ariaLabel + self.clip = clip + self.data = data + self.dx = dx + self.dy = dy + self.facet = facet + self.facetAnchor = facetAnchor + self.fill = fill + self.fillOpacity = fillOpacity + self.filter = filter + self.fx = fx + self.fy = fy + self.geometry = geometry + self.href = href + self.imageFilter = imageFilter + self.margin = margin + self.marginBottom = marginBottom + self.marginLeft = marginLeft + self.marginRight = marginRight + self.marginTop = marginTop + self.mark = mark + self.mixBlendMode = mixBlendMode + self.opacity = opacity + self.paintOrder = paintOrder + self.pointerEvents = pointerEvents + self.r = r + self.reverse = reverse + self.select = select + self.shapeRendering = shapeRendering + self.sort = sort + self.stroke = stroke + self.strokeDasharray = strokeDasharray + self.strokeDashoffset = strokeDashoffset + self.strokeLinecap = strokeLinecap + self.strokeLinejoin = strokeLinejoin + self.strokeMiterlimit = strokeMiterlimit + self.strokeOpacity = strokeOpacity + self.strokeWidth = strokeWidth + self.target = target + self.tip = tip + self.title = title + + +class Graticule: + def __init__(self, mark: str, ariaDescription: Union[str, "ParamRef"] = None, ariaHidden: Union[str, "ParamRef"] = None, ariaLabel: "ChannelValue" = None, clip: Union[str, str, bool, Any, "ParamRef"] = None, dx: Union[float, "ParamRef"] = None, dy: Union[float, "ParamRef"] = None, facet: Union[str, str, str, str, bool, Any, "ParamRef"] = None, facetAnchor: Union[str, str, str, str, str, str, str, str, str, str, str, str, str, Any, "ParamRef"] = None, fill: Union["ChannelValueSpec", "ParamRef"] = None, fillOpacity: Union["ChannelValueSpec", "ParamRef"] = None, filter: "ChannelValue" = None, fx: "ChannelValue" = None, fy: "ChannelValue" = None, href: "ChannelValue" = None, imageFilter: Union[str, "ParamRef"] = None, margin: Union[float, "ParamRef"] = None, marginBottom: Union[float, "ParamRef"] = None, marginLeft: Union[float, "ParamRef"] = None, marginRight: Union[float, "ParamRef"] = None, marginTop: Union[float, "ParamRef"] = None, mixBlendMode: Union[str, "ParamRef"] = None, opacity: "ChannelValueSpec" = None, paintOrder: Union[str, "ParamRef"] = None, pointerEvents: Union[str, "ParamRef"] = None, reverse: Union[bool, "ParamRef"] = None, select: "SelectFilter" = None, shapeRendering: Union[str, "ParamRef"] = None, sort: Union["SortOrder", "ChannelDomainSort"] = None, stroke: Union["ChannelValueSpec", "ParamRef"] = None, strokeDasharray: Union[str, float, "ParamRef"] = None, strokeDashoffset: Union[str, float, "ParamRef"] = None, strokeLinecap: Union[str, "ParamRef"] = None, strokeLinejoin: Union[str, "ParamRef"] = None, strokeMiterlimit: Union[float, "ParamRef"] = None, strokeOpacity: "ChannelValueSpec" = None, strokeWidth: "ChannelValueSpec" = None, target: Union[str, "ParamRef"] = None, tip: Union[bool, "TipPointer", Dict[str, Any], "ParamRef"] = None, title: "ChannelValue" = None): + self.ariaDescription = ariaDescription + self.ariaHidden = ariaHidden + self.ariaLabel = ariaLabel + self.clip = clip + self.dx = dx + self.dy = dy + self.facet = facet + self.facetAnchor = facetAnchor + self.fill = fill + self.fillOpacity = fillOpacity + self.filter = filter + self.fx = fx + self.fy = fy + self.href = href + self.imageFilter = imageFilter + self.margin = margin + self.marginBottom = marginBottom + self.marginLeft = marginLeft + self.marginRight = marginRight + self.marginTop = marginTop + self.mark = mark + self.mixBlendMode = mixBlendMode + self.opacity = opacity + self.paintOrder = paintOrder + self.pointerEvents = pointerEvents + self.reverse = reverse + self.select = select + self.shapeRendering = shapeRendering + self.sort = sort + self.stroke = stroke + self.strokeDasharray = strokeDasharray + self.strokeDashoffset = strokeDashoffset + self.strokeLinecap = strokeLinecap + self.strokeLinejoin = strokeLinejoin + self.strokeMiterlimit = strokeMiterlimit + self.strokeOpacity = strokeOpacity + self.strokeWidth = strokeWidth + self.target = target + self.tip = tip + self.title = title + + +class Heatmap: + def __init__(self, data: "PlotMarkData", mark: str, ariaDescription: Union[str, "ParamRef"] = None, ariaHidden: Union[str, "ParamRef"] = None, ariaLabel: "ChannelValue" = None, bandwidth: Union[float, "ParamRef"] = None, clip: Union[str, str, bool, Any, "ParamRef"] = None, dx: Union[float, "ParamRef"] = None, dy: Union[float, "ParamRef"] = None, facet: Union[str, str, str, str, bool, Any, "ParamRef"] = None, facetAnchor: Union[str, str, str, str, str, str, str, str, str, str, str, str, str, Any, "ParamRef"] = None, fill: Union["ChannelValueSpec", "ParamRef"] = None, fillOpacity: Union["ChannelValueSpec", "ParamRef"] = None, filter: "ChannelValue" = None, fx: "ChannelValue" = None, fy: "ChannelValue" = None, height: Union[float, "ParamRef"] = None, href: "ChannelValue" = None, imageFilter: Union[str, "ParamRef"] = None, imageRendering: Union[str, "ParamRef"] = None, interpolate: Union["GridInterpolate", Any, "ParamRef"] = None, margin: Union[float, "ParamRef"] = None, marginBottom: Union[float, "ParamRef"] = None, marginLeft: Union[float, "ParamRef"] = None, marginRight: Union[float, "ParamRef"] = None, marginTop: Union[float, "ParamRef"] = None, mixBlendMode: Union[str, "ParamRef"] = None, opacity: "ChannelValueSpec" = None, pad: Union[float, "ParamRef"] = None, paintOrder: Union[str, "ParamRef"] = None, pixelSize: Union[float, "ParamRef"] = None, pointerEvents: Union[str, "ParamRef"] = None, reverse: Union[bool, "ParamRef"] = None, select: "SelectFilter" = None, shapeRendering: Union[str, "ParamRef"] = None, sort: Union["SortOrder", "ChannelDomainSort"] = None, stroke: Union["ChannelValueSpec", "ParamRef"] = None, strokeDasharray: Union[str, float, "ParamRef"] = None, strokeDashoffset: Union[str, float, "ParamRef"] = None, strokeLinecap: Union[str, "ParamRef"] = None, strokeLinejoin: Union[str, "ParamRef"] = None, strokeMiterlimit: Union[float, "ParamRef"] = None, strokeOpacity: "ChannelValueSpec" = None, strokeWidth: "ChannelValueSpec" = None, target: Union[str, "ParamRef"] = None, tip: Union[bool, "TipPointer", Dict[str, Any], "ParamRef"] = None, title: "ChannelValue" = None, width: Union[float, "ParamRef"] = None, x: "ChannelValueSpec" = None, y: "ChannelValueSpec" = None): + self.ariaDescription = ariaDescription + self.ariaHidden = ariaHidden + self.ariaLabel = ariaLabel + self.bandwidth = bandwidth + self.clip = clip + self.data = data + self.dx = dx + self.dy = dy + self.facet = facet + self.facetAnchor = facetAnchor + self.fill = fill + self.fillOpacity = fillOpacity + self.filter = filter + self.fx = fx + self.fy = fy + self.height = height + self.href = href + self.imageFilter = imageFilter + self.imageRendering = imageRendering + self.interpolate = interpolate + self.margin = margin + self.marginBottom = marginBottom + self.marginLeft = marginLeft + self.marginRight = marginRight + self.marginTop = marginTop + self.mark = mark + self.mixBlendMode = mixBlendMode + self.opacity = opacity + self.pad = pad + self.paintOrder = paintOrder + self.pixelSize = pixelSize + self.pointerEvents = pointerEvents + self.reverse = reverse + self.select = select + self.shapeRendering = shapeRendering + self.sort = sort + self.stroke = stroke + self.strokeDasharray = strokeDasharray + self.strokeDashoffset = strokeDashoffset + self.strokeLinecap = strokeLinecap + self.strokeLinejoin = strokeLinejoin + self.strokeMiterlimit = strokeMiterlimit + self.strokeOpacity = strokeOpacity + self.strokeWidth = strokeWidth + self.target = target + self.tip = tip + self.title = title + self.width = width + self.x = x + self.y = y + + +class Hexagon: + def __init__(self, data: "PlotMarkData", mark: str, ariaDescription: Union[str, "ParamRef"] = None, ariaHidden: Union[str, "ParamRef"] = None, ariaLabel: "ChannelValue" = None, clip: Union[str, str, bool, Any, "ParamRef"] = None, dx: Union[float, "ParamRef"] = None, dy: Union[float, "ParamRef"] = None, facet: Union[str, str, str, str, bool, Any, "ParamRef"] = None, facetAnchor: Union[str, str, str, str, str, str, str, str, str, str, str, str, str, Any, "ParamRef"] = None, fill: Union["ChannelValueSpec", "ParamRef"] = None, fillOpacity: Union["ChannelValueSpec", "ParamRef"] = None, filter: "ChannelValue" = None, frameAnchor: Union["FrameAnchor", "ParamRef"] = None, fx: "ChannelValue" = None, fy: "ChannelValue" = None, href: "ChannelValue" = None, imageFilter: Union[str, "ParamRef"] = None, margin: Union[float, "ParamRef"] = None, marginBottom: Union[float, "ParamRef"] = None, marginLeft: Union[float, "ParamRef"] = None, marginRight: Union[float, "ParamRef"] = None, marginTop: Union[float, "ParamRef"] = None, mixBlendMode: Union[str, "ParamRef"] = None, opacity: "ChannelValueSpec" = None, paintOrder: Union[str, "ParamRef"] = None, pointerEvents: Union[str, "ParamRef"] = None, r: Union["ChannelValueSpec", float, "ParamRef"] = None, reverse: Union[bool, "ParamRef"] = None, rotate: Union["ChannelValue", float, "ParamRef"] = None, select: "SelectFilter" = None, shapeRendering: Union[str, "ParamRef"] = None, sort: Union["SortOrder", "ChannelDomainSort"] = None, stroke: Union["ChannelValueSpec", "ParamRef"] = None, strokeDasharray: Union[str, float, "ParamRef"] = None, strokeDashoffset: Union[str, float, "ParamRef"] = None, strokeLinecap: Union[str, "ParamRef"] = None, strokeLinejoin: Union[str, "ParamRef"] = None, strokeMiterlimit: Union[float, "ParamRef"] = None, strokeOpacity: "ChannelValueSpec" = None, strokeWidth: "ChannelValueSpec" = None, symbol: Union["ChannelValueSpec", "SymbolType", "ParamRef"] = None, target: Union[str, "ParamRef"] = None, tip: Union[bool, "TipPointer", Dict[str, Any], "ParamRef"] = None, title: "ChannelValue" = None, x: "ChannelValueSpec" = None, y: "ChannelValueSpec" = None, z: "ChannelValue" = None): + self.ariaDescription = ariaDescription + self.ariaHidden = ariaHidden + self.ariaLabel = ariaLabel + self.clip = clip + self.data = data + self.dx = dx + self.dy = dy + self.facet = facet + self.facetAnchor = facetAnchor + self.fill = fill + self.fillOpacity = fillOpacity + self.filter = filter + self.frameAnchor = frameAnchor + self.fx = fx + self.fy = fy + self.href = href + self.imageFilter = imageFilter + self.margin = margin + self.marginBottom = marginBottom + self.marginLeft = marginLeft + self.marginRight = marginRight + self.marginTop = marginTop + self.mark = mark + self.mixBlendMode = mixBlendMode + self.opacity = opacity + self.paintOrder = paintOrder + self.pointerEvents = pointerEvents + self.r = r + self.reverse = reverse + self.rotate = rotate + self.select = select + self.shapeRendering = shapeRendering + self.sort = sort + self.stroke = stroke + self.strokeDasharray = strokeDasharray + self.strokeDashoffset = strokeDashoffset + self.strokeLinecap = strokeLinecap + self.strokeLinejoin = strokeLinejoin + self.strokeMiterlimit = strokeMiterlimit + self.strokeOpacity = strokeOpacity + self.strokeWidth = strokeWidth + self.symbol = symbol + self.target = target + self.tip = tip + self.title = title + self.x = x + self.y = y + self.z = z + + +class Hexbin: + def __init__(self, data: "PlotMarkData", mark: str, ariaDescription: Union[str, "ParamRef"] = None, ariaHidden: Union[str, "ParamRef"] = None, ariaLabel: "ChannelValue" = None, binWidth: Union[float, "ParamRef"] = None, clip: Union[str, str, bool, Any, "ParamRef"] = None, dx: Union[float, "ParamRef"] = None, dy: Union[float, "ParamRef"] = None, facet: Union[str, str, str, str, bool, Any, "ParamRef"] = None, facetAnchor: Union[str, str, str, str, str, str, str, str, str, str, str, str, str, Any, "ParamRef"] = None, fill: Union["ChannelValueSpec", "ParamRef"] = None, fillOpacity: Union["ChannelValueSpec", "ParamRef"] = None, filter: "ChannelValue" = None, fontFamily: Union[str, "ParamRef"] = None, fontSize: Union["ChannelValue", "ParamRef"] = None, fontStyle: Union[str, "ParamRef"] = None, fontVariant: Union[str, "ParamRef"] = None, fontWeight: Union[str, float, "ParamRef"] = None, frameAnchor: Union["FrameAnchor", "ParamRef"] = None, fx: "ChannelValue" = None, fy: "ChannelValue" = None, href: "ChannelValue" = None, imageFilter: Union[str, "ParamRef"] = None, lineHeight: Union[float, "ParamRef"] = None, lineWidth: Union[float, "ParamRef"] = None, margin: Union[float, "ParamRef"] = None, marginBottom: Union[float, "ParamRef"] = None, marginLeft: Union[float, "ParamRef"] = None, marginRight: Union[float, "ParamRef"] = None, marginTop: Union[float, "ParamRef"] = None, mixBlendMode: Union[str, "ParamRef"] = None, monospace: Union[bool, "ParamRef"] = None, opacity: "ChannelValueSpec" = None, paintOrder: Union[str, "ParamRef"] = None, pointerEvents: Union[str, "ParamRef"] = None, r: Union["ChannelValueSpec", float, "ParamRef"] = None, reverse: Union[bool, "ParamRef"] = None, rotate: Union["ChannelValue", float, "ParamRef"] = None, select: "SelectFilter" = None, shapeRendering: Union[str, "ParamRef"] = None, sort: Union["SortOrder", "ChannelDomainSort"] = None, stroke: Union["ChannelValueSpec", "ParamRef"] = None, strokeDasharray: Union[str, float, "ParamRef"] = None, strokeDashoffset: Union[str, float, "ParamRef"] = None, strokeLinecap: Union[str, "ParamRef"] = None, strokeLinejoin: Union[str, "ParamRef"] = None, strokeMiterlimit: Union[float, "ParamRef"] = None, strokeOpacity: "ChannelValueSpec" = None, strokeWidth: "ChannelValueSpec" = None, symbol: Union["ChannelValueSpec", "SymbolType", "ParamRef"] = None, target: Union[str, "ParamRef"] = None, textAnchor: Union[str, str, str, "ParamRef"] = None, textOverflow: Union[Any, str, str, str, str, str, str, str, "ParamRef"] = None, tip: Union[bool, "TipPointer", Dict[str, Any], "ParamRef"] = None, title: "ChannelValue" = None, type: Union[str, str, str, str, "ParamRef"] = None, x: "ChannelValueSpec" = None, y: "ChannelValueSpec" = None, z: "ChannelValue" = None): + self.ariaDescription = ariaDescription + self.ariaHidden = ariaHidden + self.ariaLabel = ariaLabel + self.binWidth = binWidth + self.clip = clip + self.data = data + self.dx = dx + self.dy = dy + self.facet = facet + self.facetAnchor = facetAnchor + self.fill = fill + self.fillOpacity = fillOpacity + self.filter = filter + self.fontFamily = fontFamily + self.fontSize = fontSize + self.fontStyle = fontStyle + self.fontVariant = fontVariant + self.fontWeight = fontWeight + self.frameAnchor = frameAnchor + self.fx = fx + self.fy = fy + self.href = href + self.imageFilter = imageFilter + self.lineHeight = lineHeight + self.lineWidth = lineWidth + self.margin = margin + self.marginBottom = marginBottom + self.marginLeft = marginLeft + self.marginRight = marginRight + self.marginTop = marginTop + self.mark = mark + self.mixBlendMode = mixBlendMode + self.monospace = monospace + self.opacity = opacity + self.paintOrder = paintOrder + self.pointerEvents = pointerEvents + self.r = r + self.reverse = reverse + self.rotate = rotate + self.select = select + self.shapeRendering = shapeRendering + self.sort = sort + self.stroke = stroke + self.strokeDasharray = strokeDasharray + self.strokeDashoffset = strokeDashoffset + self.strokeLinecap = strokeLinecap + self.strokeLinejoin = strokeLinejoin + self.strokeMiterlimit = strokeMiterlimit + self.strokeOpacity = strokeOpacity + self.strokeWidth = strokeWidth + self.symbol = symbol + self.target = target + self.textAnchor = textAnchor + self.textOverflow = textOverflow + self.tip = tip + self.title = title + self.type = type + self.x = x + self.y = y + self.z = z + + +class Hexgrid: + def __init__(self, mark: str, ariaDescription: Union[str, "ParamRef"] = None, ariaHidden: Union[str, "ParamRef"] = None, ariaLabel: "ChannelValue" = None, binWidth: Union[float, "ParamRef"] = None, clip: Union[str, str, bool, Any, "ParamRef"] = None, dx: Union[float, "ParamRef"] = None, dy: Union[float, "ParamRef"] = None, facet: Union[str, str, str, str, bool, Any, "ParamRef"] = None, facetAnchor: Union[str, str, str, str, str, str, str, str, str, str, str, str, str, Any, "ParamRef"] = None, fill: Union["ChannelValueSpec", "ParamRef"] = None, fillOpacity: Union["ChannelValueSpec", "ParamRef"] = None, filter: "ChannelValue" = None, fx: "ChannelValue" = None, fy: "ChannelValue" = None, href: "ChannelValue" = None, imageFilter: Union[str, "ParamRef"] = None, margin: Union[float, "ParamRef"] = None, marginBottom: Union[float, "ParamRef"] = None, marginLeft: Union[float, "ParamRef"] = None, marginRight: Union[float, "ParamRef"] = None, marginTop: Union[float, "ParamRef"] = None, mixBlendMode: Union[str, "ParamRef"] = None, opacity: "ChannelValueSpec" = None, paintOrder: Union[str, "ParamRef"] = None, pointerEvents: Union[str, "ParamRef"] = None, reverse: Union[bool, "ParamRef"] = None, select: "SelectFilter" = None, shapeRendering: Union[str, "ParamRef"] = None, sort: Union["SortOrder", "ChannelDomainSort"] = None, stroke: Union["ChannelValueSpec", "ParamRef"] = None, strokeDasharray: Union[str, float, "ParamRef"] = None, strokeDashoffset: Union[str, float, "ParamRef"] = None, strokeLinecap: Union[str, "ParamRef"] = None, strokeLinejoin: Union[str, "ParamRef"] = None, strokeMiterlimit: Union[float, "ParamRef"] = None, strokeOpacity: "ChannelValueSpec" = None, strokeWidth: "ChannelValueSpec" = None, target: Union[str, "ParamRef"] = None, tip: Union[bool, "TipPointer", Dict[str, Any], "ParamRef"] = None, title: "ChannelValue" = None): + self.ariaDescription = ariaDescription + self.ariaHidden = ariaHidden + self.ariaLabel = ariaLabel + self.binWidth = binWidth + self.clip = clip + self.dx = dx + self.dy = dy + self.facet = facet + self.facetAnchor = facetAnchor + self.fill = fill + self.fillOpacity = fillOpacity + self.filter = filter + self.fx = fx + self.fy = fy + self.href = href + self.imageFilter = imageFilter + self.margin = margin + self.marginBottom = marginBottom + self.marginLeft = marginLeft + self.marginRight = marginRight + self.marginTop = marginTop + self.mark = mark + self.mixBlendMode = mixBlendMode + self.opacity = opacity + self.paintOrder = paintOrder + self.pointerEvents = pointerEvents + self.reverse = reverse + self.select = select + self.shapeRendering = shapeRendering + self.sort = sort + self.stroke = stroke + self.strokeDasharray = strokeDasharray + self.strokeDashoffset = strokeDashoffset + self.strokeLinecap = strokeLinecap + self.strokeLinejoin = strokeLinejoin + self.strokeMiterlimit = strokeMiterlimit + self.strokeOpacity = strokeOpacity + self.strokeWidth = strokeWidth + self.target = target + self.tip = tip + self.title = title + + +class Hull: + def __init__(self, data: "PlotMarkData", mark: str, ariaDescription: Union[str, "ParamRef"] = None, ariaHidden: Union[str, "ParamRef"] = None, ariaLabel: "ChannelValue" = None, clip: Union[str, str, bool, Any, "ParamRef"] = None, curve: Union["Curve", "ParamRef"] = None, dx: Union[float, "ParamRef"] = None, dy: Union[float, "ParamRef"] = None, facet: Union[str, str, str, str, bool, Any, "ParamRef"] = None, facetAnchor: Union[str, str, str, str, str, str, str, str, str, str, str, str, str, Any, "ParamRef"] = None, fill: Union["ChannelValueSpec", "ParamRef"] = None, fillOpacity: Union["ChannelValueSpec", "ParamRef"] = None, filter: "ChannelValue" = None, fx: "ChannelValue" = None, fy: "ChannelValue" = None, href: "ChannelValue" = None, imageFilter: Union[str, "ParamRef"] = None, margin: Union[float, "ParamRef"] = None, marginBottom: Union[float, "ParamRef"] = None, marginLeft: Union[float, "ParamRef"] = None, marginRight: Union[float, "ParamRef"] = None, marginTop: Union[float, "ParamRef"] = None, marker: Union["MarkerName", str, bool, Any, "ParamRef"] = None, markerEnd: Union["MarkerName", str, bool, Any, "ParamRef"] = None, markerMid: Union["MarkerName", str, bool, Any, "ParamRef"] = None, markerStart: Union["MarkerName", str, bool, Any, "ParamRef"] = None, mixBlendMode: Union[str, "ParamRef"] = None, opacity: "ChannelValueSpec" = None, paintOrder: Union[str, "ParamRef"] = None, pointerEvents: Union[str, "ParamRef"] = None, reverse: Union[bool, "ParamRef"] = None, select: "SelectFilter" = None, shapeRendering: Union[str, "ParamRef"] = None, sort: Union["SortOrder", "ChannelDomainSort"] = None, stroke: Union["ChannelValueSpec", "ParamRef"] = None, strokeDasharray: Union[str, float, "ParamRef"] = None, strokeDashoffset: Union[str, float, "ParamRef"] = None, strokeLinecap: Union[str, "ParamRef"] = None, strokeLinejoin: Union[str, "ParamRef"] = None, strokeMiterlimit: Union[float, "ParamRef"] = None, strokeOpacity: "ChannelValueSpec" = None, strokeWidth: "ChannelValueSpec" = None, target: Union[str, "ParamRef"] = None, tension: Union[float, "ParamRef"] = None, tip: Union[bool, "TipPointer", Dict[str, Any], "ParamRef"] = None, title: "ChannelValue" = None, x: "ChannelValueSpec" = None, y: "ChannelValueSpec" = None, z: "ChannelValue" = None): + self.ariaDescription = ariaDescription + self.ariaHidden = ariaHidden + self.ariaLabel = ariaLabel + self.clip = clip + self.curve = curve + self.data = data + self.dx = dx + self.dy = dy + self.facet = facet + self.facetAnchor = facetAnchor + self.fill = fill + self.fillOpacity = fillOpacity + self.filter = filter + self.fx = fx + self.fy = fy + self.href = href + self.imageFilter = imageFilter + self.margin = margin + self.marginBottom = marginBottom + self.marginLeft = marginLeft + self.marginRight = marginRight + self.marginTop = marginTop + self.mark = mark + self.marker = marker + self.markerEnd = markerEnd + self.markerMid = markerMid + self.markerStart = markerStart + self.mixBlendMode = mixBlendMode + self.opacity = opacity + self.paintOrder = paintOrder + self.pointerEvents = pointerEvents + self.reverse = reverse + self.select = select + self.shapeRendering = shapeRendering + self.sort = sort + self.stroke = stroke + self.strokeDasharray = strokeDasharray + self.strokeDashoffset = strokeDashoffset + self.strokeLinecap = strokeLinecap + self.strokeLinejoin = strokeLinejoin + self.strokeMiterlimit = strokeMiterlimit + self.strokeOpacity = strokeOpacity + self.strokeWidth = strokeWidth + self.target = target + self.tension = tension + self.tip = tip + self.title = title + self.x = x + self.y = y + self.z = z + + +class Image: + def __init__(self, data: "PlotMarkData", mark: str, ariaDescription: Union[str, "ParamRef"] = None, ariaHidden: Union[str, "ParamRef"] = None, ariaLabel: "ChannelValue" = None, clip: Union[str, str, bool, Any, "ParamRef"] = None, crossOrigin: Union[str, "ParamRef"] = None, dx: Union[float, "ParamRef"] = None, dy: Union[float, "ParamRef"] = None, facet: Union[str, str, str, str, bool, Any, "ParamRef"] = None, facetAnchor: Union[str, str, str, str, str, str, str, str, str, str, str, str, str, Any, "ParamRef"] = None, fill: Union["ChannelValueSpec", "ParamRef"] = None, fillOpacity: Union["ChannelValueSpec", "ParamRef"] = None, filter: "ChannelValue" = None, frameAnchor: Union["FrameAnchor", "ParamRef"] = None, fx: "ChannelValue" = None, fy: "ChannelValue" = None, height: Union["ChannelValue", "ParamRef"] = None, href: "ChannelValue" = None, imageFilter: Union[str, "ParamRef"] = None, imageRendering: Union[str, "ParamRef"] = None, margin: Union[float, "ParamRef"] = None, marginBottom: Union[float, "ParamRef"] = None, marginLeft: Union[float, "ParamRef"] = None, marginRight: Union[float, "ParamRef"] = None, marginTop: Union[float, "ParamRef"] = None, mixBlendMode: Union[str, "ParamRef"] = None, opacity: "ChannelValueSpec" = None, paintOrder: Union[str, "ParamRef"] = None, pointerEvents: Union[str, "ParamRef"] = None, preserveAspectRatio: Union[str, "ParamRef"] = None, r: Union["ChannelValue", "ParamRef"] = None, reverse: Union[bool, "ParamRef"] = None, rotate: Union["ChannelValue", "ParamRef"] = None, select: "SelectFilter" = None, shapeRendering: Union[str, "ParamRef"] = None, sort: Union["SortOrder", "ChannelDomainSort"] = None, src: Union["ChannelValue", "ParamRef"] = None, stroke: Union["ChannelValueSpec", "ParamRef"] = None, strokeDasharray: Union[str, float, "ParamRef"] = None, strokeDashoffset: Union[str, float, "ParamRef"] = None, strokeLinecap: Union[str, "ParamRef"] = None, strokeLinejoin: Union[str, "ParamRef"] = None, strokeMiterlimit: Union[float, "ParamRef"] = None, strokeOpacity: "ChannelValueSpec" = None, strokeWidth: "ChannelValueSpec" = None, target: Union[str, "ParamRef"] = None, tip: Union[bool, "TipPointer", Dict[str, Any], "ParamRef"] = None, title: "ChannelValue" = None, width: Union["ChannelValue", "ParamRef"] = None, x: "ChannelValueSpec" = None, y: "ChannelValueSpec" = None): + self.ariaDescription = ariaDescription + self.ariaHidden = ariaHidden + self.ariaLabel = ariaLabel + self.clip = clip + self.crossOrigin = crossOrigin + self.data = data + self.dx = dx + self.dy = dy + self.facet = facet + self.facetAnchor = facetAnchor + self.fill = fill + self.fillOpacity = fillOpacity + self.filter = filter + self.frameAnchor = frameAnchor + self.fx = fx + self.fy = fy + self.height = height + self.href = href + self.imageFilter = imageFilter + self.imageRendering = imageRendering + self.margin = margin + self.marginBottom = marginBottom + self.marginLeft = marginLeft + self.marginRight = marginRight + self.marginTop = marginTop + self.mark = mark + self.mixBlendMode = mixBlendMode + self.opacity = opacity + self.paintOrder = paintOrder + self.pointerEvents = pointerEvents + self.preserveAspectRatio = preserveAspectRatio + self.r = r + self.reverse = reverse + self.rotate = rotate + self.select = select + self.shapeRendering = shapeRendering + self.sort = sort + self.src = src + self.stroke = stroke + self.strokeDasharray = strokeDasharray + self.strokeDashoffset = strokeDashoffset + self.strokeLinecap = strokeLinecap + self.strokeLinejoin = strokeLinejoin + self.strokeMiterlimit = strokeMiterlimit + self.strokeOpacity = strokeOpacity + self.strokeWidth = strokeWidth + self.target = target + self.tip = tip + self.title = title + self.width = width + self.x = x + self.y = y + + +class Line: + def __init__(self, data: "PlotMarkData", mark: str, ariaDescription: Union[str, "ParamRef"] = None, ariaHidden: Union[str, "ParamRef"] = None, ariaLabel: "ChannelValue" = None, clip: Union[str, str, bool, Any, "ParamRef"] = None, curve: Union["Curve", str, "ParamRef"] = None, dx: Union[float, "ParamRef"] = None, dy: Union[float, "ParamRef"] = None, facet: Union[str, str, str, str, bool, Any, "ParamRef"] = None, facetAnchor: Union[str, str, str, str, str, str, str, str, str, str, str, str, str, Any, "ParamRef"] = None, fill: Union["ChannelValueSpec", "ParamRef"] = None, fillOpacity: Union["ChannelValueSpec", "ParamRef"] = None, filter: "ChannelValue" = None, fx: "ChannelValue" = None, fy: "ChannelValue" = None, href: "ChannelValue" = None, imageFilter: Union[str, "ParamRef"] = None, margin: Union[float, "ParamRef"] = None, marginBottom: Union[float, "ParamRef"] = None, marginLeft: Union[float, "ParamRef"] = None, marginRight: Union[float, "ParamRef"] = None, marginTop: Union[float, "ParamRef"] = None, marker: Union["MarkerName", str, bool, Any, "ParamRef"] = None, markerEnd: Union["MarkerName", str, bool, Any, "ParamRef"] = None, markerMid: Union["MarkerName", str, bool, Any, "ParamRef"] = None, markerStart: Union["MarkerName", str, bool, Any, "ParamRef"] = None, mixBlendMode: Union[str, "ParamRef"] = None, opacity: "ChannelValueSpec" = None, paintOrder: Union[str, "ParamRef"] = None, pointerEvents: Union[str, "ParamRef"] = None, reverse: Union[bool, "ParamRef"] = None, select: "SelectFilter" = None, shapeRendering: Union[str, "ParamRef"] = None, sort: Union["SortOrder", "ChannelDomainSort"] = None, stroke: Union["ChannelValueSpec", "ParamRef"] = None, strokeDasharray: Union[str, float, "ParamRef"] = None, strokeDashoffset: Union[str, float, "ParamRef"] = None, strokeLinecap: Union[str, "ParamRef"] = None, strokeLinejoin: Union[str, "ParamRef"] = None, strokeMiterlimit: Union[float, "ParamRef"] = None, strokeOpacity: "ChannelValueSpec" = None, strokeWidth: "ChannelValueSpec" = None, target: Union[str, "ParamRef"] = None, tension: Union[float, "ParamRef"] = None, tip: Union[bool, "TipPointer", Dict[str, Any], "ParamRef"] = None, title: "ChannelValue" = None, x: "ChannelValueSpec" = None, y: "ChannelValueSpec" = None, z: "ChannelValue" = None): + self.ariaDescription = ariaDescription + self.ariaHidden = ariaHidden + self.ariaLabel = ariaLabel + self.clip = clip + self.curve = curve + self.data = data + self.dx = dx + self.dy = dy + self.facet = facet + self.facetAnchor = facetAnchor + self.fill = fill + self.fillOpacity = fillOpacity + self.filter = filter + self.fx = fx + self.fy = fy + self.href = href + self.imageFilter = imageFilter + self.margin = margin + self.marginBottom = marginBottom + self.marginLeft = marginLeft + self.marginRight = marginRight + self.marginTop = marginTop + self.mark = mark + self.marker = marker + self.markerEnd = markerEnd + self.markerMid = markerMid + self.markerStart = markerStart + self.mixBlendMode = mixBlendMode + self.opacity = opacity + self.paintOrder = paintOrder + self.pointerEvents = pointerEvents + self.reverse = reverse + self.select = select + self.shapeRendering = shapeRendering + self.sort = sort + self.stroke = stroke + self.strokeDasharray = strokeDasharray + self.strokeDashoffset = strokeDashoffset + self.strokeLinecap = strokeLinecap + self.strokeLinejoin = strokeLinejoin + self.strokeMiterlimit = strokeMiterlimit + self.strokeOpacity = strokeOpacity + self.strokeWidth = strokeWidth + self.target = target + self.tension = tension + self.tip = tip + self.title = title + self.x = x + self.y = y + self.z = z + + +class LineX: + def __init__(self, data: "PlotMarkData", mark: str, ariaDescription: Union[str, "ParamRef"] = None, ariaHidden: Union[str, "ParamRef"] = None, ariaLabel: "ChannelValue" = None, clip: Union[str, str, bool, Any, "ParamRef"] = None, curve: Union["Curve", str, "ParamRef"] = None, dx: Union[float, "ParamRef"] = None, dy: Union[float, "ParamRef"] = None, facet: Union[str, str, str, str, bool, Any, "ParamRef"] = None, facetAnchor: Union[str, str, str, str, str, str, str, str, str, str, str, str, str, Any, "ParamRef"] = None, fill: Union["ChannelValueSpec", "ParamRef"] = None, fillOpacity: Union["ChannelValueSpec", "ParamRef"] = None, filter: "ChannelValue" = None, fx: "ChannelValue" = None, fy: "ChannelValue" = None, href: "ChannelValue" = None, imageFilter: Union[str, "ParamRef"] = None, margin: Union[float, "ParamRef"] = None, marginBottom: Union[float, "ParamRef"] = None, marginLeft: Union[float, "ParamRef"] = None, marginRight: Union[float, "ParamRef"] = None, marginTop: Union[float, "ParamRef"] = None, marker: Union["MarkerName", str, bool, Any, "ParamRef"] = None, markerEnd: Union["MarkerName", str, bool, Any, "ParamRef"] = None, markerMid: Union["MarkerName", str, bool, Any, "ParamRef"] = None, markerStart: Union["MarkerName", str, bool, Any, "ParamRef"] = None, mixBlendMode: Union[str, "ParamRef"] = None, opacity: "ChannelValueSpec" = None, paintOrder: Union[str, "ParamRef"] = None, pointerEvents: Union[str, "ParamRef"] = None, reverse: Union[bool, "ParamRef"] = None, select: "SelectFilter" = None, shapeRendering: Union[str, "ParamRef"] = None, sort: Union["SortOrder", "ChannelDomainSort"] = None, stroke: Union["ChannelValueSpec", "ParamRef"] = None, strokeDasharray: Union[str, float, "ParamRef"] = None, strokeDashoffset: Union[str, float, "ParamRef"] = None, strokeLinecap: Union[str, "ParamRef"] = None, strokeLinejoin: Union[str, "ParamRef"] = None, strokeMiterlimit: Union[float, "ParamRef"] = None, strokeOpacity: "ChannelValueSpec" = None, strokeWidth: "ChannelValueSpec" = None, target: Union[str, "ParamRef"] = None, tension: Union[float, "ParamRef"] = None, tip: Union[bool, "TipPointer", Dict[str, Any], "ParamRef"] = None, title: "ChannelValue" = None, x: "ChannelValueSpec" = None, y: "ChannelValueSpec" = None, z: "ChannelValue" = None): + self.ariaDescription = ariaDescription + self.ariaHidden = ariaHidden + self.ariaLabel = ariaLabel + self.clip = clip + self.curve = curve + self.data = data + self.dx = dx + self.dy = dy + self.facet = facet + self.facetAnchor = facetAnchor + self.fill = fill + self.fillOpacity = fillOpacity + self.filter = filter + self.fx = fx + self.fy = fy + self.href = href + self.imageFilter = imageFilter + self.margin = margin + self.marginBottom = marginBottom + self.marginLeft = marginLeft + self.marginRight = marginRight + self.marginTop = marginTop + self.mark = mark + self.marker = marker + self.markerEnd = markerEnd + self.markerMid = markerMid + self.markerStart = markerStart + self.mixBlendMode = mixBlendMode + self.opacity = opacity + self.paintOrder = paintOrder + self.pointerEvents = pointerEvents + self.reverse = reverse + self.select = select + self.shapeRendering = shapeRendering + self.sort = sort + self.stroke = stroke + self.strokeDasharray = strokeDasharray + self.strokeDashoffset = strokeDashoffset + self.strokeLinecap = strokeLinecap + self.strokeLinejoin = strokeLinejoin + self.strokeMiterlimit = strokeMiterlimit + self.strokeOpacity = strokeOpacity + self.strokeWidth = strokeWidth + self.target = target + self.tension = tension + self.tip = tip + self.title = title + self.x = x + self.y = y + self.z = z + + +class LineY: + def __init__(self, data: "PlotMarkData", mark: str, ariaDescription: Union[str, "ParamRef"] = None, ariaHidden: Union[str, "ParamRef"] = None, ariaLabel: "ChannelValue" = None, clip: Union[str, str, bool, Any, "ParamRef"] = None, curve: Union["Curve", str, "ParamRef"] = None, dx: Union[float, "ParamRef"] = None, dy: Union[float, "ParamRef"] = None, facet: Union[str, str, str, str, bool, Any, "ParamRef"] = None, facetAnchor: Union[str, str, str, str, str, str, str, str, str, str, str, str, str, Any, "ParamRef"] = None, fill: Union["ChannelValueSpec", "ParamRef"] = None, fillOpacity: Union["ChannelValueSpec", "ParamRef"] = None, filter: "ChannelValue" = None, fx: "ChannelValue" = None, fy: "ChannelValue" = None, href: "ChannelValue" = None, imageFilter: Union[str, "ParamRef"] = None, margin: Union[float, "ParamRef"] = None, marginBottom: Union[float, "ParamRef"] = None, marginLeft: Union[float, "ParamRef"] = None, marginRight: Union[float, "ParamRef"] = None, marginTop: Union[float, "ParamRef"] = None, marker: Union["MarkerName", str, bool, Any, "ParamRef"] = None, markerEnd: Union["MarkerName", str, bool, Any, "ParamRef"] = None, markerMid: Union["MarkerName", str, bool, Any, "ParamRef"] = None, markerStart: Union["MarkerName", str, bool, Any, "ParamRef"] = None, mixBlendMode: Union[str, "ParamRef"] = None, opacity: "ChannelValueSpec" = None, paintOrder: Union[str, "ParamRef"] = None, pointerEvents: Union[str, "ParamRef"] = None, reverse: Union[bool, "ParamRef"] = None, select: "SelectFilter" = None, shapeRendering: Union[str, "ParamRef"] = None, sort: Union["SortOrder", "ChannelDomainSort"] = None, stroke: Union["ChannelValueSpec", "ParamRef"] = None, strokeDasharray: Union[str, float, "ParamRef"] = None, strokeDashoffset: Union[str, float, "ParamRef"] = None, strokeLinecap: Union[str, "ParamRef"] = None, strokeLinejoin: Union[str, "ParamRef"] = None, strokeMiterlimit: Union[float, "ParamRef"] = None, strokeOpacity: "ChannelValueSpec" = None, strokeWidth: "ChannelValueSpec" = None, target: Union[str, "ParamRef"] = None, tension: Union[float, "ParamRef"] = None, tip: Union[bool, "TipPointer", Dict[str, Any], "ParamRef"] = None, title: "ChannelValue" = None, x: "ChannelValueSpec" = None, y: "ChannelValueSpec" = None, z: "ChannelValue" = None): + self.ariaDescription = ariaDescription + self.ariaHidden = ariaHidden + self.ariaLabel = ariaLabel + self.clip = clip + self.curve = curve + self.data = data + self.dx = dx + self.dy = dy + self.facet = facet + self.facetAnchor = facetAnchor + self.fill = fill + self.fillOpacity = fillOpacity + self.filter = filter + self.fx = fx + self.fy = fy + self.href = href + self.imageFilter = imageFilter + self.margin = margin + self.marginBottom = marginBottom + self.marginLeft = marginLeft + self.marginRight = marginRight + self.marginTop = marginTop + self.mark = mark + self.marker = marker + self.markerEnd = markerEnd + self.markerMid = markerMid + self.markerStart = markerStart + self.mixBlendMode = mixBlendMode + self.opacity = opacity + self.paintOrder = paintOrder + self.pointerEvents = pointerEvents + self.reverse = reverse + self.select = select + self.shapeRendering = shapeRendering + self.sort = sort + self.stroke = stroke + self.strokeDasharray = strokeDasharray + self.strokeDashoffset = strokeDashoffset + self.strokeLinecap = strokeLinecap + self.strokeLinejoin = strokeLinejoin + self.strokeMiterlimit = strokeMiterlimit + self.strokeOpacity = strokeOpacity + self.strokeWidth = strokeWidth + self.target = target + self.tension = tension + self.tip = tip + self.title = title + self.x = x + self.y = y + self.z = z + + +class Link: + def __init__(self, data: "PlotMarkData", mark: str, ariaDescription: Union[str, "ParamRef"] = None, ariaHidden: Union[str, "ParamRef"] = None, ariaLabel: "ChannelValue" = None, clip: Union[str, str, bool, Any, "ParamRef"] = None, curve: Union[Union["Curve", "ParamRef", str], "ParamRef"] = None, dx: Union[float, "ParamRef"] = None, dy: Union[float, "ParamRef"] = None, facet: Union[str, str, str, str, bool, Any, "ParamRef"] = None, facetAnchor: Union[str, str, str, str, str, str, str, str, str, str, str, str, str, Any, "ParamRef"] = None, fill: Union["ChannelValueSpec", "ParamRef"] = None, fillOpacity: Union["ChannelValueSpec", "ParamRef"] = None, filter: "ChannelValue" = None, fx: "ChannelValue" = None, fy: "ChannelValue" = None, href: "ChannelValue" = None, imageFilter: Union[str, "ParamRef"] = None, margin: Union[float, "ParamRef"] = None, marginBottom: Union[float, "ParamRef"] = None, marginLeft: Union[float, "ParamRef"] = None, marginRight: Union[float, "ParamRef"] = None, marginTop: Union[float, "ParamRef"] = None, marker: Union["MarkerName", str, bool, Any, "ParamRef"] = None, markerEnd: Union["MarkerName", str, bool, Any, "ParamRef"] = None, markerMid: Union["MarkerName", str, bool, Any, "ParamRef"] = None, markerStart: Union["MarkerName", str, bool, Any, "ParamRef"] = None, mixBlendMode: Union[str, "ParamRef"] = None, opacity: "ChannelValueSpec" = None, paintOrder: Union[str, "ParamRef"] = None, pointerEvents: Union[str, "ParamRef"] = None, reverse: Union[bool, "ParamRef"] = None, select: "SelectFilter" = None, shapeRendering: Union[str, "ParamRef"] = None, sort: Union["SortOrder", "ChannelDomainSort"] = None, stroke: Union["ChannelValueSpec", "ParamRef"] = None, strokeDasharray: Union[str, float, "ParamRef"] = None, strokeDashoffset: Union[str, float, "ParamRef"] = None, strokeLinecap: Union[str, "ParamRef"] = None, strokeLinejoin: Union[str, "ParamRef"] = None, strokeMiterlimit: Union[float, "ParamRef"] = None, strokeOpacity: "ChannelValueSpec" = None, strokeWidth: "ChannelValueSpec" = None, target: Union[str, "ParamRef"] = None, tension: Union[float, "ParamRef"] = None, tip: Union[bool, "TipPointer", Dict[str, Any], "ParamRef"] = None, title: "ChannelValue" = None, x: "ChannelValueSpec" = None, x1: "ChannelValueSpec" = None, x2: "ChannelValueSpec" = None, y: "ChannelValueSpec" = None, y1: "ChannelValueSpec" = None, y2: "ChannelValueSpec" = None): + self.ariaDescription = ariaDescription + self.ariaHidden = ariaHidden + self.ariaLabel = ariaLabel + self.clip = clip + self.curve = curve + self.data = data + self.dx = dx + self.dy = dy + self.facet = facet + self.facetAnchor = facetAnchor + self.fill = fill + self.fillOpacity = fillOpacity + self.filter = filter + self.fx = fx + self.fy = fy + self.href = href + self.imageFilter = imageFilter + self.margin = margin + self.marginBottom = marginBottom + self.marginLeft = marginLeft + self.marginRight = marginRight + self.marginTop = marginTop + self.mark = mark + self.marker = marker + self.markerEnd = markerEnd + self.markerMid = markerMid + self.markerStart = markerStart + self.mixBlendMode = mixBlendMode + self.opacity = opacity + self.paintOrder = paintOrder + self.pointerEvents = pointerEvents + self.reverse = reverse + self.select = select + self.shapeRendering = shapeRendering + self.sort = sort + self.stroke = stroke + self.strokeDasharray = strokeDasharray + self.strokeDashoffset = strokeDashoffset + self.strokeLinecap = strokeLinecap + self.strokeLinejoin = strokeLinejoin + self.strokeMiterlimit = strokeMiterlimit + self.strokeOpacity = strokeOpacity + self.strokeWidth = strokeWidth + self.target = target + self.tension = tension + self.tip = tip + self.title = title + self.x = x + self.x1 = x1 + self.x2 = x2 + self.y = y + self.y1 = y1 + self.y2 = y2 + + +class Raster: + def __init__(self, data: "PlotMarkData", mark: str, ariaDescription: Union[str, "ParamRef"] = None, ariaHidden: Union[str, "ParamRef"] = None, ariaLabel: "ChannelValue" = None, bandwidth: Union[float, "ParamRef"] = None, clip: Union[str, str, bool, Any, "ParamRef"] = None, dx: Union[float, "ParamRef"] = None, dy: Union[float, "ParamRef"] = None, facet: Union[str, str, str, str, bool, Any, "ParamRef"] = None, facetAnchor: Union[str, str, str, str, str, str, str, str, str, str, str, str, str, Any, "ParamRef"] = None, fill: Union["ChannelValueSpec", "ParamRef"] = None, fillOpacity: Union["ChannelValueSpec", "ParamRef"] = None, filter: "ChannelValue" = None, fx: "ChannelValue" = None, fy: "ChannelValue" = None, height: Union[float, "ParamRef"] = None, href: "ChannelValue" = None, imageFilter: Union[str, "ParamRef"] = None, imageRendering: Union[str, "ParamRef"] = None, interpolate: Union["GridInterpolate", Any, "ParamRef"] = None, margin: Union[float, "ParamRef"] = None, marginBottom: Union[float, "ParamRef"] = None, marginLeft: Union[float, "ParamRef"] = None, marginRight: Union[float, "ParamRef"] = None, marginTop: Union[float, "ParamRef"] = None, mixBlendMode: Union[str, "ParamRef"] = None, opacity: "ChannelValueSpec" = None, pad: Union[float, "ParamRef"] = None, paintOrder: Union[str, "ParamRef"] = None, pixelSize: Union[float, "ParamRef"] = None, pointerEvents: Union[str, "ParamRef"] = None, reverse: Union[bool, "ParamRef"] = None, select: "SelectFilter" = None, shapeRendering: Union[str, "ParamRef"] = None, sort: Union["SortOrder", "ChannelDomainSort"] = None, stroke: Union["ChannelValueSpec", "ParamRef"] = None, strokeDasharray: Union[str, float, "ParamRef"] = None, strokeDashoffset: Union[str, float, "ParamRef"] = None, strokeLinecap: Union[str, "ParamRef"] = None, strokeLinejoin: Union[str, "ParamRef"] = None, strokeMiterlimit: Union[float, "ParamRef"] = None, strokeOpacity: "ChannelValueSpec" = None, strokeWidth: "ChannelValueSpec" = None, target: Union[str, "ParamRef"] = None, tip: Union[bool, "TipPointer", Dict[str, Any], "ParamRef"] = None, title: "ChannelValue" = None, width: Union[float, "ParamRef"] = None, x: "ChannelValueSpec" = None, y: "ChannelValueSpec" = None): + self.ariaDescription = ariaDescription + self.ariaHidden = ariaHidden + self.ariaLabel = ariaLabel + self.bandwidth = bandwidth + self.clip = clip + self.data = data + self.dx = dx + self.dy = dy + self.facet = facet + self.facetAnchor = facetAnchor + self.fill = fill + self.fillOpacity = fillOpacity + self.filter = filter + self.fx = fx + self.fy = fy + self.height = height + self.href = href + self.imageFilter = imageFilter + self.imageRendering = imageRendering + self.interpolate = interpolate + self.margin = margin + self.marginBottom = marginBottom + self.marginLeft = marginLeft + self.marginRight = marginRight + self.marginTop = marginTop + self.mark = mark + self.mixBlendMode = mixBlendMode + self.opacity = opacity + self.pad = pad + self.paintOrder = paintOrder + self.pixelSize = pixelSize + self.pointerEvents = pointerEvents + self.reverse = reverse + self.select = select + self.shapeRendering = shapeRendering + self.sort = sort + self.stroke = stroke + self.strokeDasharray = strokeDasharray + self.strokeDashoffset = strokeDashoffset + self.strokeLinecap = strokeLinecap + self.strokeLinejoin = strokeLinejoin + self.strokeMiterlimit = strokeMiterlimit + self.strokeOpacity = strokeOpacity + self.strokeWidth = strokeWidth + self.target = target + self.tip = tip + self.title = title + self.width = width + self.x = x + self.y = y + + +class RasterTile: + def __init__(self, data: "PlotMarkData", mark: str, ariaDescription: Union[str, "ParamRef"] = None, ariaHidden: Union[str, "ParamRef"] = None, ariaLabel: "ChannelValue" = None, bandwidth: Union[float, "ParamRef"] = None, clip: Union[str, str, bool, Any, "ParamRef"] = None, dx: Union[float, "ParamRef"] = None, dy: Union[float, "ParamRef"] = None, facet: Union[str, str, str, str, bool, Any, "ParamRef"] = None, facetAnchor: Union[str, str, str, str, str, str, str, str, str, str, str, str, str, Any, "ParamRef"] = None, fill: Union["ChannelValueSpec", "ParamRef"] = None, fillOpacity: Union["ChannelValueSpec", "ParamRef"] = None, filter: "ChannelValue" = None, fx: "ChannelValue" = None, fy: "ChannelValue" = None, height: Union[float, "ParamRef"] = None, href: "ChannelValue" = None, imageFilter: Union[str, "ParamRef"] = None, imageRendering: Union[str, "ParamRef"] = None, interpolate: Union["GridInterpolate", Any, "ParamRef"] = None, margin: Union[float, "ParamRef"] = None, marginBottom: Union[float, "ParamRef"] = None, marginLeft: Union[float, "ParamRef"] = None, marginRight: Union[float, "ParamRef"] = None, marginTop: Union[float, "ParamRef"] = None, mixBlendMode: Union[str, "ParamRef"] = None, opacity: "ChannelValueSpec" = None, origin: Union[List[float], "ParamRef"] = None, pad: Union[float, "ParamRef"] = None, paintOrder: Union[str, "ParamRef"] = None, pixelSize: Union[float, "ParamRef"] = None, pointerEvents: Union[str, "ParamRef"] = None, reverse: Union[bool, "ParamRef"] = None, select: "SelectFilter" = None, shapeRendering: Union[str, "ParamRef"] = None, sort: Union["SortOrder", "ChannelDomainSort"] = None, stroke: Union["ChannelValueSpec", "ParamRef"] = None, strokeDasharray: Union[str, float, "ParamRef"] = None, strokeDashoffset: Union[str, float, "ParamRef"] = None, strokeLinecap: Union[str, "ParamRef"] = None, strokeLinejoin: Union[str, "ParamRef"] = None, strokeMiterlimit: Union[float, "ParamRef"] = None, strokeOpacity: "ChannelValueSpec" = None, strokeWidth: "ChannelValueSpec" = None, target: Union[str, "ParamRef"] = None, tip: Union[bool, "TipPointer", Dict[str, Any], "ParamRef"] = None, title: "ChannelValue" = None, width: Union[float, "ParamRef"] = None, x: "ChannelValueSpec" = None, y: "ChannelValueSpec" = None): + self.ariaDescription = ariaDescription + self.ariaHidden = ariaHidden + self.ariaLabel = ariaLabel + self.bandwidth = bandwidth + self.clip = clip + self.data = data + self.dx = dx + self.dy = dy + self.facet = facet + self.facetAnchor = facetAnchor + self.fill = fill + self.fillOpacity = fillOpacity + self.filter = filter + self.fx = fx + self.fy = fy + self.height = height + self.href = href + self.imageFilter = imageFilter + self.imageRendering = imageRendering + self.interpolate = interpolate + self.margin = margin + self.marginBottom = marginBottom + self.marginLeft = marginLeft + self.marginRight = marginRight + self.marginTop = marginTop + self.mark = mark + self.mixBlendMode = mixBlendMode + self.opacity = opacity + self.origin = origin + self.pad = pad + self.paintOrder = paintOrder + self.pixelSize = pixelSize + self.pointerEvents = pointerEvents + self.reverse = reverse + self.select = select + self.shapeRendering = shapeRendering + self.sort = sort + self.stroke = stroke + self.strokeDasharray = strokeDasharray + self.strokeDashoffset = strokeDashoffset + self.strokeLinecap = strokeLinecap + self.strokeLinejoin = strokeLinejoin + self.strokeMiterlimit = strokeMiterlimit + self.strokeOpacity = strokeOpacity + self.strokeWidth = strokeWidth + self.target = target + self.tip = tip + self.title = title + self.width = width + self.x = x + self.y = y + + +class RegressionY: + def __init__(self, data: "PlotMarkData", mark: str, ariaDescription: Union[str, "ParamRef"] = None, ariaHidden: Union[str, "ParamRef"] = None, ariaLabel: "ChannelValue" = None, ci: Union[float, "ParamRef"] = None, clip: Union[str, str, bool, Any, "ParamRef"] = None, dx: Union[float, "ParamRef"] = None, dy: Union[float, "ParamRef"] = None, facet: Union[str, str, str, str, bool, Any, "ParamRef"] = None, facetAnchor: Union[str, str, str, str, str, str, str, str, str, str, str, str, str, Any, "ParamRef"] = None, fill: Union["ChannelValueSpec", "ParamRef"] = None, fillOpacity: Union["ChannelValueSpec", "ParamRef"] = None, filter: "ChannelValue" = None, fx: "ChannelValue" = None, fy: "ChannelValue" = None, href: "ChannelValue" = None, imageFilter: Union[str, "ParamRef"] = None, margin: Union[float, "ParamRef"] = None, marginBottom: Union[float, "ParamRef"] = None, marginLeft: Union[float, "ParamRef"] = None, marginRight: Union[float, "ParamRef"] = None, marginTop: Union[float, "ParamRef"] = None, mixBlendMode: Union[str, "ParamRef"] = None, opacity: "ChannelValueSpec" = None, paintOrder: Union[str, "ParamRef"] = None, pointerEvents: Union[str, "ParamRef"] = None, precision: Union[float, "ParamRef"] = None, reverse: Union[bool, "ParamRef"] = None, select: "SelectFilter" = None, shapeRendering: Union[str, "ParamRef"] = None, sort: Union["SortOrder", "ChannelDomainSort"] = None, stroke: Union["ChannelValueSpec", "ParamRef"] = None, strokeDasharray: Union[str, float, "ParamRef"] = None, strokeDashoffset: Union[str, float, "ParamRef"] = None, strokeLinecap: Union[str, "ParamRef"] = None, strokeLinejoin: Union[str, "ParamRef"] = None, strokeMiterlimit: Union[float, "ParamRef"] = None, strokeOpacity: "ChannelValueSpec" = None, strokeWidth: "ChannelValueSpec" = None, target: Union[str, "ParamRef"] = None, tip: Union[bool, "TipPointer", Dict[str, Any], "ParamRef"] = None, title: "ChannelValue" = None, x: "ChannelValueSpec" = None, y: "ChannelValueSpec" = None, z: "ChannelValue" = None): + self.ariaDescription = ariaDescription + self.ariaHidden = ariaHidden + self.ariaLabel = ariaLabel + self.ci = ci + self.clip = clip + self.data = data + self.dx = dx + self.dy = dy + self.facet = facet + self.facetAnchor = facetAnchor + self.fill = fill + self.fillOpacity = fillOpacity + self.filter = filter + self.fx = fx + self.fy = fy + self.href = href + self.imageFilter = imageFilter + self.margin = margin + self.marginBottom = marginBottom + self.marginLeft = marginLeft + self.marginRight = marginRight + self.marginTop = marginTop + self.mark = mark + self.mixBlendMode = mixBlendMode + self.opacity = opacity + self.paintOrder = paintOrder + self.pointerEvents = pointerEvents + self.precision = precision + self.reverse = reverse + self.select = select + self.shapeRendering = shapeRendering + self.sort = sort + self.stroke = stroke + self.strokeDasharray = strokeDasharray + self.strokeDashoffset = strokeDashoffset + self.strokeLinecap = strokeLinecap + self.strokeLinejoin = strokeLinejoin + self.strokeMiterlimit = strokeMiterlimit + self.strokeOpacity = strokeOpacity + self.strokeWidth = strokeWidth + self.target = target + self.tip = tip + self.title = title + self.x = x + self.y = y + self.z = z + + +class Sphere: + def __init__(self, mark: str, ariaDescription: Union[str, "ParamRef"] = None, ariaHidden: Union[str, "ParamRef"] = None, ariaLabel: "ChannelValue" = None, clip: Union[str, str, bool, Any, "ParamRef"] = None, dx: Union[float, "ParamRef"] = None, dy: Union[float, "ParamRef"] = None, facet: Union[str, str, str, str, bool, Any, "ParamRef"] = None, facetAnchor: Union[str, str, str, str, str, str, str, str, str, str, str, str, str, Any, "ParamRef"] = None, fill: Union["ChannelValueSpec", "ParamRef"] = None, fillOpacity: Union["ChannelValueSpec", "ParamRef"] = None, filter: "ChannelValue" = None, fx: "ChannelValue" = None, fy: "ChannelValue" = None, href: "ChannelValue" = None, imageFilter: Union[str, "ParamRef"] = None, margin: Union[float, "ParamRef"] = None, marginBottom: Union[float, "ParamRef"] = None, marginLeft: Union[float, "ParamRef"] = None, marginRight: Union[float, "ParamRef"] = None, marginTop: Union[float, "ParamRef"] = None, mixBlendMode: Union[str, "ParamRef"] = None, opacity: "ChannelValueSpec" = None, paintOrder: Union[str, "ParamRef"] = None, pointerEvents: Union[str, "ParamRef"] = None, reverse: Union[bool, "ParamRef"] = None, select: "SelectFilter" = None, shapeRendering: Union[str, "ParamRef"] = None, sort: Union["SortOrder", "ChannelDomainSort"] = None, stroke: Union["ChannelValueSpec", "ParamRef"] = None, strokeDasharray: Union[str, float, "ParamRef"] = None, strokeDashoffset: Union[str, float, "ParamRef"] = None, strokeLinecap: Union[str, "ParamRef"] = None, strokeLinejoin: Union[str, "ParamRef"] = None, strokeMiterlimit: Union[float, "ParamRef"] = None, strokeOpacity: "ChannelValueSpec" = None, strokeWidth: "ChannelValueSpec" = None, target: Union[str, "ParamRef"] = None, tip: Union[bool, "TipPointer", Dict[str, Any], "ParamRef"] = None, title: "ChannelValue" = None): + self.ariaDescription = ariaDescription + self.ariaHidden = ariaHidden + self.ariaLabel = ariaLabel + self.clip = clip + self.dx = dx + self.dy = dy + self.facet = facet + self.facetAnchor = facetAnchor + self.fill = fill + self.fillOpacity = fillOpacity + self.filter = filter + self.fx = fx + self.fy = fy + self.href = href + self.imageFilter = imageFilter + self.margin = margin + self.marginBottom = marginBottom + self.marginLeft = marginLeft + self.marginRight = marginRight + self.marginTop = marginTop + self.mark = mark + self.mixBlendMode = mixBlendMode + self.opacity = opacity + self.paintOrder = paintOrder + self.pointerEvents = pointerEvents + self.reverse = reverse + self.select = select + self.shapeRendering = shapeRendering + self.sort = sort + self.stroke = stroke + self.strokeDasharray = strokeDasharray + self.strokeDashoffset = strokeDashoffset + self.strokeLinecap = strokeLinecap + self.strokeLinejoin = strokeLinejoin + self.strokeMiterlimit = strokeMiterlimit + self.strokeOpacity = strokeOpacity + self.strokeWidth = strokeWidth + self.target = target + self.tip = tip + self.title = title + + +class Spike: + def __init__(self, data: "PlotMarkData", mark: str, anchor: Union[str, str, str, "ParamRef"] = None, ariaDescription: Union[str, "ParamRef"] = None, ariaHidden: Union[str, "ParamRef"] = None, ariaLabel: "ChannelValue" = None, clip: Union[str, str, bool, Any, "ParamRef"] = None, dx: Union[float, "ParamRef"] = None, dy: Union[float, "ParamRef"] = None, facet: Union[str, str, str, str, bool, Any, "ParamRef"] = None, facetAnchor: Union[str, str, str, str, str, str, str, str, str, str, str, str, str, Any, "ParamRef"] = None, fill: Union["ChannelValueSpec", "ParamRef"] = None, fillOpacity: Union["ChannelValueSpec", "ParamRef"] = None, filter: "ChannelValue" = None, frameAnchor: Union["FrameAnchor", "ParamRef"] = None, fx: "ChannelValue" = None, fy: "ChannelValue" = None, href: "ChannelValue" = None, imageFilter: Union[str, "ParamRef"] = None, length: "ChannelValueSpec" = None, margin: Union[float, "ParamRef"] = None, marginBottom: Union[float, "ParamRef"] = None, marginLeft: Union[float, "ParamRef"] = None, marginRight: Union[float, "ParamRef"] = None, marginTop: Union[float, "ParamRef"] = None, mixBlendMode: Union[str, "ParamRef"] = None, opacity: "ChannelValueSpec" = None, paintOrder: Union[str, "ParamRef"] = None, pointerEvents: Union[str, "ParamRef"] = None, r: Union[float, "ParamRef"] = None, reverse: Union[bool, "ParamRef"] = None, rotate: "ChannelValue" = None, select: "SelectFilter" = None, shape: Union["VectorShape", "ParamRef"] = None, shapeRendering: Union[str, "ParamRef"] = None, sort: Union["SortOrder", "ChannelDomainSort"] = None, stroke: Union["ChannelValueSpec", "ParamRef"] = None, strokeDasharray: Union[str, float, "ParamRef"] = None, strokeDashoffset: Union[str, float, "ParamRef"] = None, strokeLinecap: Union[str, "ParamRef"] = None, strokeLinejoin: Union[str, "ParamRef"] = None, strokeMiterlimit: Union[float, "ParamRef"] = None, strokeOpacity: "ChannelValueSpec" = None, strokeWidth: "ChannelValueSpec" = None, target: Union[str, "ParamRef"] = None, tip: Union[bool, "TipPointer", Dict[str, Any], "ParamRef"] = None, title: "ChannelValue" = None, x: "ChannelValueSpec" = None, y: "ChannelValueSpec" = None): + self.anchor = anchor + self.ariaDescription = ariaDescription + self.ariaHidden = ariaHidden + self.ariaLabel = ariaLabel + self.clip = clip + self.data = data + self.dx = dx + self.dy = dy + self.facet = facet + self.facetAnchor = facetAnchor + self.fill = fill + self.fillOpacity = fillOpacity + self.filter = filter + self.frameAnchor = frameAnchor + self.fx = fx + self.fy = fy + self.href = href + self.imageFilter = imageFilter + self.length = length + self.margin = margin + self.marginBottom = marginBottom + self.marginLeft = marginLeft + self.marginRight = marginRight + self.marginTop = marginTop + self.mark = mark + self.mixBlendMode = mixBlendMode + self.opacity = opacity + self.paintOrder = paintOrder + self.pointerEvents = pointerEvents + self.r = r + self.reverse = reverse + self.rotate = rotate + self.select = select + self.shape = shape + self.shapeRendering = shapeRendering + self.sort = sort + self.stroke = stroke + self.strokeDasharray = strokeDasharray + self.strokeDashoffset = strokeDashoffset + self.strokeLinecap = strokeLinecap + self.strokeLinejoin = strokeLinejoin + self.strokeMiterlimit = strokeMiterlimit + self.strokeOpacity = strokeOpacity + self.strokeWidth = strokeWidth + self.target = target + self.tip = tip + self.title = title + self.x = x + self.y = y + + +class Text: + def __init__(self, mark: str, ariaDescription: Union[str, "ParamRef"] = None, ariaHidden: Union[str, "ParamRef"] = None, ariaLabel: "ChannelValue" = None, clip: Union[str, str, bool, Any, "ParamRef"] = None, data: "PlotMarkData" = None, dx: Union[float, "ParamRef"] = None, dy: Union[float, "ParamRef"] = None, facet: Union[str, str, str, str, bool, Any, "ParamRef"] = None, facetAnchor: Union[str, str, str, str, str, str, str, str, str, str, str, str, str, Any, "ParamRef"] = None, fill: Union["ChannelValueSpec", "ParamRef"] = None, fillOpacity: Union["ChannelValueSpec", "ParamRef"] = None, filter: "ChannelValue" = None, fontFamily: Union[str, "ParamRef"] = None, fontSize: Union["ChannelValue", "ParamRef"] = None, fontStyle: Union[str, "ParamRef"] = None, fontVariant: Union[str, "ParamRef"] = None, fontWeight: Union[str, float, "ParamRef"] = None, frameAnchor: Union["FrameAnchor", "ParamRef"] = None, fx: "ChannelValue" = None, fy: "ChannelValue" = None, href: "ChannelValue" = None, imageFilter: Union[str, "ParamRef"] = None, lineAnchor: Union[str, str, str, "ParamRef"] = None, lineHeight: Union[float, "ParamRef"] = None, lineWidth: Union[float, "ParamRef"] = None, margin: Union[float, "ParamRef"] = None, marginBottom: Union[float, "ParamRef"] = None, marginLeft: Union[float, "ParamRef"] = None, marginRight: Union[float, "ParamRef"] = None, marginTop: Union[float, "ParamRef"] = None, mixBlendMode: Union[str, "ParamRef"] = None, monospace: Union[bool, "ParamRef"] = None, opacity: "ChannelValueSpec" = None, paintOrder: Union[str, "ParamRef"] = None, pointerEvents: Union[str, "ParamRef"] = None, reverse: Union[bool, "ParamRef"] = None, rotate: Union["ChannelValue", "ParamRef"] = None, select: "SelectFilter" = None, shapeRendering: Union[str, "ParamRef"] = None, sort: Union["SortOrder", "ChannelDomainSort"] = None, stroke: Union["ChannelValueSpec", "ParamRef"] = None, strokeDasharray: Union[str, float, "ParamRef"] = None, strokeDashoffset: Union[str, float, "ParamRef"] = None, strokeLinecap: Union[str, "ParamRef"] = None, strokeLinejoin: Union[str, "ParamRef"] = None, strokeMiterlimit: Union[float, "ParamRef"] = None, strokeOpacity: "ChannelValueSpec" = None, strokeWidth: "ChannelValueSpec" = None, target: Union[str, "ParamRef"] = None, text: "ChannelValue" = None, textAnchor: Union[str, str, str, "ParamRef"] = None, textOverflow: Union[Any, str, str, str, str, str, str, str, "ParamRef"] = None, tip: Union[bool, "TipPointer", Dict[str, Any], "ParamRef"] = None, title: "ChannelValue" = None, x: "ChannelValueSpec" = None, y: "ChannelValueSpec" = None, z: "ChannelValue" = None): + self.ariaDescription = ariaDescription + self.ariaHidden = ariaHidden + self.ariaLabel = ariaLabel + self.clip = clip + self.data = data + self.dx = dx + self.dy = dy + self.facet = facet + self.facetAnchor = facetAnchor + self.fill = fill + self.fillOpacity = fillOpacity + self.filter = filter + self.fontFamily = fontFamily + self.fontSize = fontSize + self.fontStyle = fontStyle + self.fontVariant = fontVariant + self.fontWeight = fontWeight + self.frameAnchor = frameAnchor + self.fx = fx + self.fy = fy + self.href = href + self.imageFilter = imageFilter + self.lineAnchor = lineAnchor + self.lineHeight = lineHeight + self.lineWidth = lineWidth + self.margin = margin + self.marginBottom = marginBottom + self.marginLeft = marginLeft + self.marginRight = marginRight + self.marginTop = marginTop + self.mark = mark + self.mixBlendMode = mixBlendMode + self.monospace = monospace + self.opacity = opacity + self.paintOrder = paintOrder + self.pointerEvents = pointerEvents + self.reverse = reverse + self.rotate = rotate + self.select = select + self.shapeRendering = shapeRendering + self.sort = sort + self.stroke = stroke + self.strokeDasharray = strokeDasharray + self.strokeDashoffset = strokeDashoffset + self.strokeLinecap = strokeLinecap + self.strokeLinejoin = strokeLinejoin + self.strokeMiterlimit = strokeMiterlimit + self.strokeOpacity = strokeOpacity + self.strokeWidth = strokeWidth + self.target = target + self.text = text + self.textAnchor = textAnchor + self.textOverflow = textOverflow + self.tip = tip + self.title = title + self.x = x + self.y = y + self.z = z + + +class TickX: + def __init__(self, data: "PlotMarkData", mark: str, ariaDescription: Union[str, "ParamRef"] = None, ariaHidden: Union[str, "ParamRef"] = None, ariaLabel: "ChannelValue" = None, clip: Union[str, str, bool, Any, "ParamRef"] = None, dx: Union[float, "ParamRef"] = None, dy: Union[float, "ParamRef"] = None, facet: Union[str, str, str, str, bool, Any, "ParamRef"] = None, facetAnchor: Union[str, str, str, str, str, str, str, str, str, str, str, str, str, Any, "ParamRef"] = None, fill: Union["ChannelValueSpec", "ParamRef"] = None, fillOpacity: Union["ChannelValueSpec", "ParamRef"] = None, filter: "ChannelValue" = None, fx: "ChannelValue" = None, fy: "ChannelValue" = None, href: "ChannelValue" = None, imageFilter: Union[str, "ParamRef"] = None, inset: Union[float, "ParamRef"] = None, insetBottom: Union[float, "ParamRef"] = None, insetTop: Union[float, "ParamRef"] = None, margin: Union[float, "ParamRef"] = None, marginBottom: Union[float, "ParamRef"] = None, marginLeft: Union[float, "ParamRef"] = None, marginRight: Union[float, "ParamRef"] = None, marginTop: Union[float, "ParamRef"] = None, marker: Union["MarkerName", str, bool, Any, "ParamRef"] = None, markerEnd: Union["MarkerName", str, bool, Any, "ParamRef"] = None, markerMid: Union["MarkerName", str, bool, Any, "ParamRef"] = None, markerStart: Union["MarkerName", str, bool, Any, "ParamRef"] = None, mixBlendMode: Union[str, "ParamRef"] = None, opacity: "ChannelValueSpec" = None, paintOrder: Union[str, "ParamRef"] = None, pointerEvents: Union[str, "ParamRef"] = None, reverse: Union[bool, "ParamRef"] = None, select: "SelectFilter" = None, shapeRendering: Union[str, "ParamRef"] = None, sort: Union["SortOrder", "ChannelDomainSort"] = None, stroke: Union["ChannelValueSpec", "ParamRef"] = None, strokeDasharray: Union[str, float, "ParamRef"] = None, strokeDashoffset: Union[str, float, "ParamRef"] = None, strokeLinecap: Union[str, "ParamRef"] = None, strokeLinejoin: Union[str, "ParamRef"] = None, strokeMiterlimit: Union[float, "ParamRef"] = None, strokeOpacity: "ChannelValueSpec" = None, strokeWidth: "ChannelValueSpec" = None, target: Union[str, "ParamRef"] = None, tip: Union[bool, "TipPointer", Dict[str, Any], "ParamRef"] = None, title: "ChannelValue" = None, x: "ChannelValueSpec" = None, y: "ChannelValueSpec" = None): + self.ariaDescription = ariaDescription + self.ariaHidden = ariaHidden + self.ariaLabel = ariaLabel + self.clip = clip + self.data = data + self.dx = dx + self.dy = dy + self.facet = facet + self.facetAnchor = facetAnchor + self.fill = fill + self.fillOpacity = fillOpacity + self.filter = filter + self.fx = fx + self.fy = fy + self.href = href + self.imageFilter = imageFilter + self.inset = inset + self.insetBottom = insetBottom + self.insetTop = insetTop + self.margin = margin + self.marginBottom = marginBottom + self.marginLeft = marginLeft + self.marginRight = marginRight + self.marginTop = marginTop + self.mark = mark + self.marker = marker + self.markerEnd = markerEnd + self.markerMid = markerMid + self.markerStart = markerStart + self.mixBlendMode = mixBlendMode + self.opacity = opacity + self.paintOrder = paintOrder + self.pointerEvents = pointerEvents + self.reverse = reverse + self.select = select + self.shapeRendering = shapeRendering + self.sort = sort + self.stroke = stroke + self.strokeDasharray = strokeDasharray + self.strokeDashoffset = strokeDashoffset + self.strokeLinecap = strokeLinecap + self.strokeLinejoin = strokeLinejoin + self.strokeMiterlimit = strokeMiterlimit + self.strokeOpacity = strokeOpacity + self.strokeWidth = strokeWidth + self.target = target + self.tip = tip + self.title = title + self.x = x + self.y = y + + +class TickY: + def __init__(self, data: "PlotMarkData", mark: str, ariaDescription: Union[str, "ParamRef"] = None, ariaHidden: Union[str, "ParamRef"] = None, ariaLabel: "ChannelValue" = None, clip: Union[str, str, bool, Any, "ParamRef"] = None, dx: Union[float, "ParamRef"] = None, dy: Union[float, "ParamRef"] = None, facet: Union[str, str, str, str, bool, Any, "ParamRef"] = None, facetAnchor: Union[str, str, str, str, str, str, str, str, str, str, str, str, str, Any, "ParamRef"] = None, fill: Union["ChannelValueSpec", "ParamRef"] = None, fillOpacity: Union["ChannelValueSpec", "ParamRef"] = None, filter: "ChannelValue" = None, fx: "ChannelValue" = None, fy: "ChannelValue" = None, href: "ChannelValue" = None, imageFilter: Union[str, "ParamRef"] = None, inset: Union[float, "ParamRef"] = None, insetLeft: Union[float, "ParamRef"] = None, insetRight: Union[float, "ParamRef"] = None, margin: Union[float, "ParamRef"] = None, marginBottom: Union[float, "ParamRef"] = None, marginLeft: Union[float, "ParamRef"] = None, marginRight: Union[float, "ParamRef"] = None, marginTop: Union[float, "ParamRef"] = None, marker: Union["MarkerName", str, bool, Any, "ParamRef"] = None, markerEnd: Union["MarkerName", str, bool, Any, "ParamRef"] = None, markerMid: Union["MarkerName", str, bool, Any, "ParamRef"] = None, markerStart: Union["MarkerName", str, bool, Any, "ParamRef"] = None, mixBlendMode: Union[str, "ParamRef"] = None, opacity: "ChannelValueSpec" = None, paintOrder: Union[str, "ParamRef"] = None, pointerEvents: Union[str, "ParamRef"] = None, reverse: Union[bool, "ParamRef"] = None, select: "SelectFilter" = None, shapeRendering: Union[str, "ParamRef"] = None, sort: Union["SortOrder", "ChannelDomainSort"] = None, stroke: Union["ChannelValueSpec", "ParamRef"] = None, strokeDasharray: Union[str, float, "ParamRef"] = None, strokeDashoffset: Union[str, float, "ParamRef"] = None, strokeLinecap: Union[str, "ParamRef"] = None, strokeLinejoin: Union[str, "ParamRef"] = None, strokeMiterlimit: Union[float, "ParamRef"] = None, strokeOpacity: "ChannelValueSpec" = None, strokeWidth: "ChannelValueSpec" = None, target: Union[str, "ParamRef"] = None, tip: Union[bool, "TipPointer", Dict[str, Any], "ParamRef"] = None, title: "ChannelValue" = None, x: "ChannelValueSpec" = None, y: "ChannelValueSpec" = None): + self.ariaDescription = ariaDescription + self.ariaHidden = ariaHidden + self.ariaLabel = ariaLabel + self.clip = clip + self.data = data + self.dx = dx + self.dy = dy + self.facet = facet + self.facetAnchor = facetAnchor + self.fill = fill + self.fillOpacity = fillOpacity + self.filter = filter + self.fx = fx + self.fy = fy + self.href = href + self.imageFilter = imageFilter + self.inset = inset + self.insetLeft = insetLeft + self.insetRight = insetRight + self.margin = margin + self.marginBottom = marginBottom + self.marginLeft = marginLeft + self.marginRight = marginRight + self.marginTop = marginTop + self.mark = mark + self.marker = marker + self.markerEnd = markerEnd + self.markerMid = markerMid + self.markerStart = markerStart + self.mixBlendMode = mixBlendMode + self.opacity = opacity + self.paintOrder = paintOrder + self.pointerEvents = pointerEvents + self.reverse = reverse + self.select = select + self.shapeRendering = shapeRendering + self.sort = sort + self.stroke = stroke + self.strokeDasharray = strokeDasharray + self.strokeDashoffset = strokeDashoffset + self.strokeLinecap = strokeLinecap + self.strokeLinejoin = strokeLinejoin + self.strokeMiterlimit = strokeMiterlimit + self.strokeOpacity = strokeOpacity + self.strokeWidth = strokeWidth + self.target = target + self.tip = tip + self.title = title + self.x = x + self.y = y + + +class Vector: + def __init__(self, data: "PlotMarkData", mark: str, anchor: Union[str, str, str, "ParamRef"] = None, ariaDescription: Union[str, "ParamRef"] = None, ariaHidden: Union[str, "ParamRef"] = None, ariaLabel: "ChannelValue" = None, clip: Union[str, str, bool, Any, "ParamRef"] = None, dx: Union[float, "ParamRef"] = None, dy: Union[float, "ParamRef"] = None, facet: Union[str, str, str, str, bool, Any, "ParamRef"] = None, facetAnchor: Union[str, str, str, str, str, str, str, str, str, str, str, str, str, Any, "ParamRef"] = None, fill: Union["ChannelValueSpec", "ParamRef"] = None, fillOpacity: Union["ChannelValueSpec", "ParamRef"] = None, filter: "ChannelValue" = None, frameAnchor: Union["FrameAnchor", "ParamRef"] = None, fx: "ChannelValue" = None, fy: "ChannelValue" = None, href: "ChannelValue" = None, imageFilter: Union[str, "ParamRef"] = None, length: "ChannelValueSpec" = None, margin: Union[float, "ParamRef"] = None, marginBottom: Union[float, "ParamRef"] = None, marginLeft: Union[float, "ParamRef"] = None, marginRight: Union[float, "ParamRef"] = None, marginTop: Union[float, "ParamRef"] = None, mixBlendMode: Union[str, "ParamRef"] = None, opacity: "ChannelValueSpec" = None, paintOrder: Union[str, "ParamRef"] = None, pointerEvents: Union[str, "ParamRef"] = None, r: Union[float, "ParamRef"] = None, reverse: Union[bool, "ParamRef"] = None, rotate: "ChannelValue" = None, select: "SelectFilter" = None, shape: Union["VectorShape", "ParamRef"] = None, shapeRendering: Union[str, "ParamRef"] = None, sort: Union["SortOrder", "ChannelDomainSort"] = None, stroke: Union["ChannelValueSpec", "ParamRef"] = None, strokeDasharray: Union[str, float, "ParamRef"] = None, strokeDashoffset: Union[str, float, "ParamRef"] = None, strokeLinecap: Union[str, "ParamRef"] = None, strokeLinejoin: Union[str, "ParamRef"] = None, strokeMiterlimit: Union[float, "ParamRef"] = None, strokeOpacity: "ChannelValueSpec" = None, strokeWidth: "ChannelValueSpec" = None, target: Union[str, "ParamRef"] = None, tip: Union[bool, "TipPointer", Dict[str, Any], "ParamRef"] = None, title: "ChannelValue" = None, x: "ChannelValueSpec" = None, y: "ChannelValueSpec" = None): + self.anchor = anchor + self.ariaDescription = ariaDescription + self.ariaHidden = ariaHidden + self.ariaLabel = ariaLabel + self.clip = clip + self.data = data + self.dx = dx + self.dy = dy + self.facet = facet + self.facetAnchor = facetAnchor + self.fill = fill + self.fillOpacity = fillOpacity + self.filter = filter + self.frameAnchor = frameAnchor + self.fx = fx + self.fy = fy + self.href = href + self.imageFilter = imageFilter + self.length = length + self.margin = margin + self.marginBottom = marginBottom + self.marginLeft = marginLeft + self.marginRight = marginRight + self.marginTop = marginTop + self.mark = mark + self.mixBlendMode = mixBlendMode + self.opacity = opacity + self.paintOrder = paintOrder + self.pointerEvents = pointerEvents + self.r = r + self.reverse = reverse + self.rotate = rotate + self.select = select + self.shape = shape + self.shapeRendering = shapeRendering + self.sort = sort + self.stroke = stroke + self.strokeDasharray = strokeDasharray + self.strokeDashoffset = strokeDashoffset + self.strokeLinecap = strokeLinecap + self.strokeLinejoin = strokeLinejoin + self.strokeMiterlimit = strokeMiterlimit + self.strokeOpacity = strokeOpacity + self.strokeWidth = strokeWidth + self.target = target + self.tip = tip + self.title = title + self.x = x + self.y = y + + +class VectorX: + def __init__(self, data: "PlotMarkData", mark: str, anchor: Union[str, str, str, "ParamRef"] = None, ariaDescription: Union[str, "ParamRef"] = None, ariaHidden: Union[str, "ParamRef"] = None, ariaLabel: "ChannelValue" = None, clip: Union[str, str, bool, Any, "ParamRef"] = None, dx: Union[float, "ParamRef"] = None, dy: Union[float, "ParamRef"] = None, facet: Union[str, str, str, str, bool, Any, "ParamRef"] = None, facetAnchor: Union[str, str, str, str, str, str, str, str, str, str, str, str, str, Any, "ParamRef"] = None, fill: Union["ChannelValueSpec", "ParamRef"] = None, fillOpacity: Union["ChannelValueSpec", "ParamRef"] = None, filter: "ChannelValue" = None, frameAnchor: Union["FrameAnchor", "ParamRef"] = None, fx: "ChannelValue" = None, fy: "ChannelValue" = None, href: "ChannelValue" = None, imageFilter: Union[str, "ParamRef"] = None, length: "ChannelValueSpec" = None, margin: Union[float, "ParamRef"] = None, marginBottom: Union[float, "ParamRef"] = None, marginLeft: Union[float, "ParamRef"] = None, marginRight: Union[float, "ParamRef"] = None, marginTop: Union[float, "ParamRef"] = None, mixBlendMode: Union[str, "ParamRef"] = None, opacity: "ChannelValueSpec" = None, paintOrder: Union[str, "ParamRef"] = None, pointerEvents: Union[str, "ParamRef"] = None, r: Union[float, "ParamRef"] = None, reverse: Union[bool, "ParamRef"] = None, rotate: "ChannelValue" = None, select: "SelectFilter" = None, shape: Union["VectorShape", "ParamRef"] = None, shapeRendering: Union[str, "ParamRef"] = None, sort: Union["SortOrder", "ChannelDomainSort"] = None, stroke: Union["ChannelValueSpec", "ParamRef"] = None, strokeDasharray: Union[str, float, "ParamRef"] = None, strokeDashoffset: Union[str, float, "ParamRef"] = None, strokeLinecap: Union[str, "ParamRef"] = None, strokeLinejoin: Union[str, "ParamRef"] = None, strokeMiterlimit: Union[float, "ParamRef"] = None, strokeOpacity: "ChannelValueSpec" = None, strokeWidth: "ChannelValueSpec" = None, target: Union[str, "ParamRef"] = None, tip: Union[bool, "TipPointer", Dict[str, Any], "ParamRef"] = None, title: "ChannelValue" = None, x: "ChannelValueSpec" = None, y: "ChannelValueSpec" = None): + self.anchor = anchor + self.ariaDescription = ariaDescription + self.ariaHidden = ariaHidden + self.ariaLabel = ariaLabel + self.clip = clip + self.data = data + self.dx = dx + self.dy = dy + self.facet = facet + self.facetAnchor = facetAnchor + self.fill = fill + self.fillOpacity = fillOpacity + self.filter = filter + self.frameAnchor = frameAnchor + self.fx = fx + self.fy = fy + self.href = href + self.imageFilter = imageFilter + self.length = length + self.margin = margin + self.marginBottom = marginBottom + self.marginLeft = marginLeft + self.marginRight = marginRight + self.marginTop = marginTop + self.mark = mark + self.mixBlendMode = mixBlendMode + self.opacity = opacity + self.paintOrder = paintOrder + self.pointerEvents = pointerEvents + self.r = r + self.reverse = reverse + self.rotate = rotate + self.select = select + self.shape = shape + self.shapeRendering = shapeRendering + self.sort = sort + self.stroke = stroke + self.strokeDasharray = strokeDasharray + self.strokeDashoffset = strokeDashoffset + self.strokeLinecap = strokeLinecap + self.strokeLinejoin = strokeLinejoin + self.strokeMiterlimit = strokeMiterlimit + self.strokeOpacity = strokeOpacity + self.strokeWidth = strokeWidth + self.target = target + self.tip = tip + self.title = title + self.x = x + self.y = y + + +class VectorY: + def __init__(self, data: "PlotMarkData", mark: str, anchor: Union[str, str, str, "ParamRef"] = None, ariaDescription: Union[str, "ParamRef"] = None, ariaHidden: Union[str, "ParamRef"] = None, ariaLabel: "ChannelValue" = None, clip: Union[str, str, bool, Any, "ParamRef"] = None, dx: Union[float, "ParamRef"] = None, dy: Union[float, "ParamRef"] = None, facet: Union[str, str, str, str, bool, Any, "ParamRef"] = None, facetAnchor: Union[str, str, str, str, str, str, str, str, str, str, str, str, str, Any, "ParamRef"] = None, fill: Union["ChannelValueSpec", "ParamRef"] = None, fillOpacity: Union["ChannelValueSpec", "ParamRef"] = None, filter: "ChannelValue" = None, frameAnchor: Union["FrameAnchor", "ParamRef"] = None, fx: "ChannelValue" = None, fy: "ChannelValue" = None, href: "ChannelValue" = None, imageFilter: Union[str, "ParamRef"] = None, length: "ChannelValueSpec" = None, margin: Union[float, "ParamRef"] = None, marginBottom: Union[float, "ParamRef"] = None, marginLeft: Union[float, "ParamRef"] = None, marginRight: Union[float, "ParamRef"] = None, marginTop: Union[float, "ParamRef"] = None, mixBlendMode: Union[str, "ParamRef"] = None, opacity: "ChannelValueSpec" = None, paintOrder: Union[str, "ParamRef"] = None, pointerEvents: Union[str, "ParamRef"] = None, r: Union[float, "ParamRef"] = None, reverse: Union[bool, "ParamRef"] = None, rotate: "ChannelValue" = None, select: "SelectFilter" = None, shape: Union["VectorShape", "ParamRef"] = None, shapeRendering: Union[str, "ParamRef"] = None, sort: Union["SortOrder", "ChannelDomainSort"] = None, stroke: Union["ChannelValueSpec", "ParamRef"] = None, strokeDasharray: Union[str, float, "ParamRef"] = None, strokeDashoffset: Union[str, float, "ParamRef"] = None, strokeLinecap: Union[str, "ParamRef"] = None, strokeLinejoin: Union[str, "ParamRef"] = None, strokeMiterlimit: Union[float, "ParamRef"] = None, strokeOpacity: "ChannelValueSpec" = None, strokeWidth: "ChannelValueSpec" = None, target: Union[str, "ParamRef"] = None, tip: Union[bool, "TipPointer", Dict[str, Any], "ParamRef"] = None, title: "ChannelValue" = None, x: "ChannelValueSpec" = None, y: "ChannelValueSpec" = None): + self.anchor = anchor + self.ariaDescription = ariaDescription + self.ariaHidden = ariaHidden + self.ariaLabel = ariaLabel + self.clip = clip + self.data = data + self.dx = dx + self.dy = dy + self.facet = facet + self.facetAnchor = facetAnchor + self.fill = fill + self.fillOpacity = fillOpacity + self.filter = filter + self.frameAnchor = frameAnchor + self.fx = fx + self.fy = fy + self.href = href + self.imageFilter = imageFilter + self.length = length + self.margin = margin + self.marginBottom = marginBottom + self.marginLeft = marginLeft + self.marginRight = marginRight + self.marginTop = marginTop + self.mark = mark + self.mixBlendMode = mixBlendMode + self.opacity = opacity + self.paintOrder = paintOrder + self.pointerEvents = pointerEvents + self.r = r + self.reverse = reverse + self.rotate = rotate + self.select = select + self.shape = shape + self.shapeRendering = shapeRendering + self.sort = sort + self.stroke = stroke + self.strokeDasharray = strokeDasharray + self.strokeDashoffset = strokeDashoffset + self.strokeLinecap = strokeLinecap + self.strokeLinejoin = strokeLinejoin + self.strokeMiterlimit = strokeMiterlimit + self.strokeOpacity = strokeOpacity + self.strokeWidth = strokeWidth + self.target = target + self.tip = tip + self.title = title + self.x = x + self.y = y + + +class Voronoi: + def __init__(self, data: "PlotMarkData", mark: str, ariaDescription: Union[str, "ParamRef"] = None, ariaHidden: Union[str, "ParamRef"] = None, ariaLabel: "ChannelValue" = None, clip: Union[str, str, bool, Any, "ParamRef"] = None, curve: Union["Curve", "ParamRef"] = None, dx: Union[float, "ParamRef"] = None, dy: Union[float, "ParamRef"] = None, facet: Union[str, str, str, str, bool, Any, "ParamRef"] = None, facetAnchor: Union[str, str, str, str, str, str, str, str, str, str, str, str, str, Any, "ParamRef"] = None, fill: Union["ChannelValueSpec", "ParamRef"] = None, fillOpacity: Union["ChannelValueSpec", "ParamRef"] = None, filter: "ChannelValue" = None, fx: "ChannelValue" = None, fy: "ChannelValue" = None, href: "ChannelValue" = None, imageFilter: Union[str, "ParamRef"] = None, margin: Union[float, "ParamRef"] = None, marginBottom: Union[float, "ParamRef"] = None, marginLeft: Union[float, "ParamRef"] = None, marginRight: Union[float, "ParamRef"] = None, marginTop: Union[float, "ParamRef"] = None, marker: Union["MarkerName", str, bool, Any, "ParamRef"] = None, markerEnd: Union["MarkerName", str, bool, Any, "ParamRef"] = None, markerMid: Union["MarkerName", str, bool, Any, "ParamRef"] = None, markerStart: Union["MarkerName", str, bool, Any, "ParamRef"] = None, mixBlendMode: Union[str, "ParamRef"] = None, opacity: "ChannelValueSpec" = None, paintOrder: Union[str, "ParamRef"] = None, pointerEvents: Union[str, "ParamRef"] = None, reverse: Union[bool, "ParamRef"] = None, select: "SelectFilter" = None, shapeRendering: Union[str, "ParamRef"] = None, sort: Union["SortOrder", "ChannelDomainSort"] = None, stroke: Union["ChannelValueSpec", "ParamRef"] = None, strokeDasharray: Union[str, float, "ParamRef"] = None, strokeDashoffset: Union[str, float, "ParamRef"] = None, strokeLinecap: Union[str, "ParamRef"] = None, strokeLinejoin: Union[str, "ParamRef"] = None, strokeMiterlimit: Union[float, "ParamRef"] = None, strokeOpacity: "ChannelValueSpec" = None, strokeWidth: "ChannelValueSpec" = None, target: Union[str, "ParamRef"] = None, tension: Union[float, "ParamRef"] = None, tip: Union[bool, "TipPointer", Dict[str, Any], "ParamRef"] = None, title: "ChannelValue" = None, x: "ChannelValueSpec" = None, y: "ChannelValueSpec" = None, z: "ChannelValue" = None): + self.ariaDescription = ariaDescription + self.ariaHidden = ariaHidden + self.ariaLabel = ariaLabel + self.clip = clip + self.curve = curve + self.data = data + self.dx = dx + self.dy = dy + self.facet = facet + self.facetAnchor = facetAnchor + self.fill = fill + self.fillOpacity = fillOpacity + self.filter = filter + self.fx = fx + self.fy = fy + self.href = href + self.imageFilter = imageFilter + self.margin = margin + self.marginBottom = marginBottom + self.marginLeft = marginLeft + self.marginRight = marginRight + self.marginTop = marginTop + self.mark = mark + self.marker = marker + self.markerEnd = markerEnd + self.markerMid = markerMid + self.markerStart = markerStart + self.mixBlendMode = mixBlendMode + self.opacity = opacity + self.paintOrder = paintOrder + self.pointerEvents = pointerEvents + self.reverse = reverse + self.select = select + self.shapeRendering = shapeRendering + self.sort = sort + self.stroke = stroke + self.strokeDasharray = strokeDasharray + self.strokeDashoffset = strokeDashoffset + self.strokeLinecap = strokeLinecap + self.strokeLinejoin = strokeLinejoin + self.strokeMiterlimit = strokeMiterlimit + self.strokeOpacity = strokeOpacity + self.strokeWidth = strokeWidth + self.target = target + self.tension = tension + self.tip = tip + self.title = title + self.x = x + self.y = y + self.z = z + + +class VoronoiMesh: + def __init__(self, data: "PlotMarkData", mark: str, ariaDescription: Union[str, "ParamRef"] = None, ariaHidden: Union[str, "ParamRef"] = None, ariaLabel: "ChannelValue" = None, clip: Union[str, str, bool, Any, "ParamRef"] = None, curve: Union["Curve", "ParamRef"] = None, dx: Union[float, "ParamRef"] = None, dy: Union[float, "ParamRef"] = None, facet: Union[str, str, str, str, bool, Any, "ParamRef"] = None, facetAnchor: Union[str, str, str, str, str, str, str, str, str, str, str, str, str, Any, "ParamRef"] = None, fill: Union["ChannelValueSpec", "ParamRef"] = None, fillOpacity: Union["ChannelValueSpec", "ParamRef"] = None, filter: "ChannelValue" = None, fx: "ChannelValue" = None, fy: "ChannelValue" = None, href: "ChannelValue" = None, imageFilter: Union[str, "ParamRef"] = None, margin: Union[float, "ParamRef"] = None, marginBottom: Union[float, "ParamRef"] = None, marginLeft: Union[float, "ParamRef"] = None, marginRight: Union[float, "ParamRef"] = None, marginTop: Union[float, "ParamRef"] = None, marker: Union["MarkerName", str, bool, Any, "ParamRef"] = None, markerEnd: Union["MarkerName", str, bool, Any, "ParamRef"] = None, markerMid: Union["MarkerName", str, bool, Any, "ParamRef"] = None, markerStart: Union["MarkerName", str, bool, Any, "ParamRef"] = None, mixBlendMode: Union[str, "ParamRef"] = None, opacity: "ChannelValueSpec" = None, paintOrder: Union[str, "ParamRef"] = None, pointerEvents: Union[str, "ParamRef"] = None, reverse: Union[bool, "ParamRef"] = None, select: "SelectFilter" = None, shapeRendering: Union[str, "ParamRef"] = None, sort: Union["SortOrder", "ChannelDomainSort"] = None, stroke: Union["ChannelValueSpec", "ParamRef"] = None, strokeDasharray: Union[str, float, "ParamRef"] = None, strokeDashoffset: Union[str, float, "ParamRef"] = None, strokeLinecap: Union[str, "ParamRef"] = None, strokeLinejoin: Union[str, "ParamRef"] = None, strokeMiterlimit: Union[float, "ParamRef"] = None, strokeOpacity: "ChannelValueSpec" = None, strokeWidth: "ChannelValueSpec" = None, target: Union[str, "ParamRef"] = None, tension: Union[float, "ParamRef"] = None, tip: Union[bool, "TipPointer", Dict[str, Any], "ParamRef"] = None, title: "ChannelValue" = None, x: "ChannelValueSpec" = None, y: "ChannelValueSpec" = None, z: "ChannelValue" = None): + self.ariaDescription = ariaDescription + self.ariaHidden = ariaHidden + self.ariaLabel = ariaLabel + self.clip = clip + self.curve = curve + self.data = data + self.dx = dx + self.dy = dy + self.facet = facet + self.facetAnchor = facetAnchor + self.fill = fill + self.fillOpacity = fillOpacity + self.filter = filter + self.fx = fx + self.fy = fy + self.href = href + self.imageFilter = imageFilter + self.margin = margin + self.marginBottom = marginBottom + self.marginLeft = marginLeft + self.marginRight = marginRight + self.marginTop = marginTop + self.mark = mark + self.marker = marker + self.markerEnd = markerEnd + self.markerMid = markerMid + self.markerStart = markerStart + self.mixBlendMode = mixBlendMode + self.opacity = opacity + self.paintOrder = paintOrder + self.pointerEvents = pointerEvents + self.reverse = reverse + self.select = select + self.shapeRendering = shapeRendering + self.sort = sort + self.stroke = stroke + self.strokeDasharray = strokeDasharray + self.strokeDashoffset = strokeDashoffset + self.strokeLinecap = strokeLinecap + self.strokeLinejoin = strokeLinejoin + self.strokeMiterlimit = strokeMiterlimit + self.strokeOpacity = strokeOpacity + self.strokeWidth = strokeWidth + self.target = target + self.tension = tension + self.tip = tip + self.title = title + self.x = x + self.y = y + self.z = z + + +class BarX: + def __init__(self, data: "PlotMarkData", mark: str, ariaDescription: Union[str, "ParamRef"] = None, ariaHidden: Union[str, "ParamRef"] = None, ariaLabel: "ChannelValue" = None, clip: Union[str, str, bool, Any, "ParamRef"] = None, dx: Union[float, "ParamRef"] = None, dy: Union[float, "ParamRef"] = None, facet: Union[str, str, str, str, bool, Any, "ParamRef"] = None, facetAnchor: Union[str, str, str, str, str, str, str, str, str, str, str, str, str, Any, "ParamRef"] = None, fill: Union["ChannelValueSpec", "ParamRef"] = None, fillOpacity: Union["ChannelValueSpec", "ParamRef"] = None, filter: "ChannelValue" = None, fx: "ChannelValue" = None, fy: "ChannelValue" = None, href: "ChannelValue" = None, imageFilter: Union[str, "ParamRef"] = None, inset: Union[float, "ParamRef"] = None, insetBottom: Union[float, "ParamRef"] = None, insetLeft: Union[float, "ParamRef"] = None, insetRight: Union[float, "ParamRef"] = None, insetTop: Union[float, "ParamRef"] = None, interval: Union["Interval", "ParamRef"] = None, margin: Union[float, "ParamRef"] = None, marginBottom: Union[float, "ParamRef"] = None, marginLeft: Union[float, "ParamRef"] = None, marginRight: Union[float, "ParamRef"] = None, marginTop: Union[float, "ParamRef"] = None, mixBlendMode: Union[str, "ParamRef"] = None, offset: Union["StackOffset", Any, "ParamRef"] = None, opacity: "ChannelValueSpec" = None, order: Union["StackOrder", Any, "ParamRef"] = None, paintOrder: Union[str, "ParamRef"] = None, pointerEvents: Union[str, "ParamRef"] = None, reverse: Union[bool, "ParamRef"] = None, rx: Union[float, str, "ParamRef"] = None, ry: Union[float, str, "ParamRef"] = None, select: "SelectFilter" = None, shapeRendering: Union[str, "ParamRef"] = None, sort: Union["SortOrder", "ChannelDomainSort"] = None, stroke: Union["ChannelValueSpec", "ParamRef"] = None, strokeDasharray: Union[str, float, "ParamRef"] = None, strokeDashoffset: Union[str, float, "ParamRef"] = None, strokeLinecap: Union[str, "ParamRef"] = None, strokeLinejoin: Union[str, "ParamRef"] = None, strokeMiterlimit: Union[float, "ParamRef"] = None, strokeOpacity: "ChannelValueSpec" = None, strokeWidth: "ChannelValueSpec" = None, target: Union[str, "ParamRef"] = None, tip: Union[bool, "TipPointer", Dict[str, Any], "ParamRef"] = None, title: "ChannelValue" = None, x: "ChannelValueIntervalSpec" = None, x1: "ChannelValueSpec" = None, x2: "ChannelValueSpec" = None, y: "ChannelValueSpec" = None, z: "ChannelValue" = None): + self.ariaDescription = ariaDescription + self.ariaHidden = ariaHidden + self.ariaLabel = ariaLabel + self.clip = clip + self.data = data + self.dx = dx + self.dy = dy + self.facet = facet + self.facetAnchor = facetAnchor + self.fill = fill + self.fillOpacity = fillOpacity + self.filter = filter + self.fx = fx + self.fy = fy + self.href = href + self.imageFilter = imageFilter + self.inset = inset + self.insetBottom = insetBottom + self.insetLeft = insetLeft + self.insetRight = insetRight + self.insetTop = insetTop + self.interval = interval + self.margin = margin + self.marginBottom = marginBottom + self.marginLeft = marginLeft + self.marginRight = marginRight + self.marginTop = marginTop + self.mark = mark + self.mixBlendMode = mixBlendMode + self.offset = offset + self.opacity = opacity + self.order = order + self.paintOrder = paintOrder + self.pointerEvents = pointerEvents + self.reverse = reverse + self.rx = rx + self.ry = ry + self.select = select + self.shapeRendering = shapeRendering + self.sort = sort + self.stroke = stroke + self.strokeDasharray = strokeDasharray + self.strokeDashoffset = strokeDashoffset + self.strokeLinecap = strokeLinecap + self.strokeLinejoin = strokeLinejoin + self.strokeMiterlimit = strokeMiterlimit + self.strokeOpacity = strokeOpacity + self.strokeWidth = strokeWidth + self.target = target + self.tip = tip + self.title = title + self.x = x + self.x1 = x1 + self.x2 = x2 + self.y = y + self.z = z + + +class BarY: + def __init__(self, data: "PlotMarkData", mark: str, ariaDescription: Union[str, "ParamRef"] = None, ariaHidden: Union[str, "ParamRef"] = None, ariaLabel: "ChannelValue" = None, clip: Union[str, str, bool, Any, "ParamRef"] = None, dx: Union[float, "ParamRef"] = None, dy: Union[float, "ParamRef"] = None, facet: Union[str, str, str, str, bool, Any, "ParamRef"] = None, facetAnchor: Union[str, str, str, str, str, str, str, str, str, str, str, str, str, Any, "ParamRef"] = None, fill: Union["ChannelValueSpec", "ParamRef"] = None, fillOpacity: Union["ChannelValueSpec", "ParamRef"] = None, filter: "ChannelValue" = None, fx: "ChannelValue" = None, fy: "ChannelValue" = None, href: "ChannelValue" = None, imageFilter: Union[str, "ParamRef"] = None, inset: Union[float, "ParamRef"] = None, insetBottom: Union[float, "ParamRef"] = None, insetLeft: Union[float, "ParamRef"] = None, insetRight: Union[float, "ParamRef"] = None, insetTop: Union[float, "ParamRef"] = None, interval: Union["Interval", "ParamRef"] = None, margin: Union[float, "ParamRef"] = None, marginBottom: Union[float, "ParamRef"] = None, marginLeft: Union[float, "ParamRef"] = None, marginRight: Union[float, "ParamRef"] = None, marginTop: Union[float, "ParamRef"] = None, mixBlendMode: Union[str, "ParamRef"] = None, offset: Union["StackOffset", Any, "ParamRef"] = None, opacity: "ChannelValueSpec" = None, order: Union["StackOrder", Any, "ParamRef"] = None, paintOrder: Union[str, "ParamRef"] = None, pointerEvents: Union[str, "ParamRef"] = None, reverse: Union[bool, "ParamRef"] = None, rx: Union[float, str, "ParamRef"] = None, ry: Union[float, str, "ParamRef"] = None, select: "SelectFilter" = None, shapeRendering: Union[str, "ParamRef"] = None, sort: Union["SortOrder", "ChannelDomainSort"] = None, stroke: Union["ChannelValueSpec", "ParamRef"] = None, strokeDasharray: Union[str, float, "ParamRef"] = None, strokeDashoffset: Union[str, float, "ParamRef"] = None, strokeLinecap: Union[str, "ParamRef"] = None, strokeLinejoin: Union[str, "ParamRef"] = None, strokeMiterlimit: Union[float, "ParamRef"] = None, strokeOpacity: "ChannelValueSpec" = None, strokeWidth: "ChannelValueSpec" = None, target: Union[str, "ParamRef"] = None, tip: Union[bool, "TipPointer", Dict[str, Any], "ParamRef"] = None, title: "ChannelValue" = None, x: "ChannelValueSpec" = None, y: "ChannelValueIntervalSpec" = None, y1: "ChannelValueSpec" = None, y2: "ChannelValueSpec" = None, z: "ChannelValue" = None): + self.ariaDescription = ariaDescription + self.ariaHidden = ariaHidden + self.ariaLabel = ariaLabel + self.clip = clip + self.data = data + self.dx = dx + self.dy = dy + self.facet = facet + self.facetAnchor = facetAnchor + self.fill = fill + self.fillOpacity = fillOpacity + self.filter = filter + self.fx = fx + self.fy = fy + self.href = href + self.imageFilter = imageFilter + self.inset = inset + self.insetBottom = insetBottom + self.insetLeft = insetLeft + self.insetRight = insetRight + self.insetTop = insetTop + self.interval = interval + self.margin = margin + self.marginBottom = marginBottom + self.marginLeft = marginLeft + self.marginRight = marginRight + self.marginTop = marginTop + self.mark = mark + self.mixBlendMode = mixBlendMode + self.offset = offset + self.opacity = opacity + self.order = order + self.paintOrder = paintOrder + self.pointerEvents = pointerEvents + self.reverse = reverse + self.rx = rx + self.ry = ry + self.select = select + self.shapeRendering = shapeRendering + self.sort = sort + self.stroke = stroke + self.strokeDasharray = strokeDasharray + self.strokeDashoffset = strokeDashoffset + self.strokeLinecap = strokeLinecap + self.strokeLinejoin = strokeLinejoin + self.strokeMiterlimit = strokeMiterlimit + self.strokeOpacity = strokeOpacity + self.strokeWidth = strokeWidth + self.target = target + self.tip = tip + self.title = title + self.x = x + self.y = y + self.y1 = y1 + self.y2 = y2 + self.z = z + + +class DotX: + def __init__(self, data: "PlotMarkData", mark: str, ariaDescription: Union[str, "ParamRef"] = None, ariaHidden: Union[str, "ParamRef"] = None, ariaLabel: "ChannelValue" = None, clip: Union[str, str, bool, Any, "ParamRef"] = None, dx: Union[float, "ParamRef"] = None, dy: Union[float, "ParamRef"] = None, facet: Union[str, str, str, str, bool, Any, "ParamRef"] = None, facetAnchor: Union[str, str, str, str, str, str, str, str, str, str, str, str, str, Any, "ParamRef"] = None, fill: Union["ChannelValueSpec", "ParamRef"] = None, fillOpacity: Union["ChannelValueSpec", "ParamRef"] = None, filter: "ChannelValue" = None, frameAnchor: Union["FrameAnchor", "ParamRef"] = None, fx: "ChannelValue" = None, fy: "ChannelValue" = None, href: "ChannelValue" = None, imageFilter: Union[str, "ParamRef"] = None, interval: Union["Interval", "ParamRef"] = None, margin: Union[float, "ParamRef"] = None, marginBottom: Union[float, "ParamRef"] = None, marginLeft: Union[float, "ParamRef"] = None, marginRight: Union[float, "ParamRef"] = None, marginTop: Union[float, "ParamRef"] = None, mixBlendMode: Union[str, "ParamRef"] = None, opacity: "ChannelValueSpec" = None, paintOrder: Union[str, "ParamRef"] = None, pointerEvents: Union[str, "ParamRef"] = None, r: Union["ChannelValueSpec", float, "ParamRef"] = None, reverse: Union[bool, "ParamRef"] = None, rotate: Union["ChannelValue", float, "ParamRef"] = None, select: "SelectFilter" = None, shapeRendering: Union[str, "ParamRef"] = None, sort: Union["SortOrder", "ChannelDomainSort"] = None, stroke: Union["ChannelValueSpec", "ParamRef"] = None, strokeDasharray: Union[str, float, "ParamRef"] = None, strokeDashoffset: Union[str, float, "ParamRef"] = None, strokeLinecap: Union[str, "ParamRef"] = None, strokeLinejoin: Union[str, "ParamRef"] = None, strokeMiterlimit: Union[float, "ParamRef"] = None, strokeOpacity: "ChannelValueSpec" = None, strokeWidth: "ChannelValueSpec" = None, symbol: Union["ChannelValueSpec", "SymbolType", "ParamRef"] = None, target: Union[str, "ParamRef"] = None, tip: Union[bool, "TipPointer", Dict[str, Any], "ParamRef"] = None, title: "ChannelValue" = None, x: "ChannelValueSpec" = None, y: "ChannelValueIntervalSpec" = None, z: "ChannelValue" = None): + self.ariaDescription = ariaDescription + self.ariaHidden = ariaHidden + self.ariaLabel = ariaLabel + self.clip = clip + self.data = data + self.dx = dx + self.dy = dy + self.facet = facet + self.facetAnchor = facetAnchor + self.fill = fill + self.fillOpacity = fillOpacity + self.filter = filter + self.frameAnchor = frameAnchor + self.fx = fx + self.fy = fy + self.href = href + self.imageFilter = imageFilter + self.interval = interval + self.margin = margin + self.marginBottom = marginBottom + self.marginLeft = marginLeft + self.marginRight = marginRight + self.marginTop = marginTop + self.mark = mark + self.mixBlendMode = mixBlendMode + self.opacity = opacity + self.paintOrder = paintOrder + self.pointerEvents = pointerEvents + self.r = r + self.reverse = reverse + self.rotate = rotate + self.select = select + self.shapeRendering = shapeRendering + self.sort = sort + self.stroke = stroke + self.strokeDasharray = strokeDasharray + self.strokeDashoffset = strokeDashoffset + self.strokeLinecap = strokeLinecap + self.strokeLinejoin = strokeLinejoin + self.strokeMiterlimit = strokeMiterlimit + self.strokeOpacity = strokeOpacity + self.strokeWidth = strokeWidth + self.symbol = symbol + self.target = target + self.tip = tip + self.title = title + self.x = x + self.y = y + self.z = z + + +class DotY: + def __init__(self, data: "PlotMarkData", mark: str, ariaDescription: Union[str, "ParamRef"] = None, ariaHidden: Union[str, "ParamRef"] = None, ariaLabel: "ChannelValue" = None, clip: Union[str, str, bool, Any, "ParamRef"] = None, dx: Union[float, "ParamRef"] = None, dy: Union[float, "ParamRef"] = None, facet: Union[str, str, str, str, bool, Any, "ParamRef"] = None, facetAnchor: Union[str, str, str, str, str, str, str, str, str, str, str, str, str, Any, "ParamRef"] = None, fill: Union["ChannelValueSpec", "ParamRef"] = None, fillOpacity: Union["ChannelValueSpec", "ParamRef"] = None, filter: "ChannelValue" = None, frameAnchor: Union["FrameAnchor", "ParamRef"] = None, fx: "ChannelValue" = None, fy: "ChannelValue" = None, href: "ChannelValue" = None, imageFilter: Union[str, "ParamRef"] = None, interval: Union["Interval", "ParamRef"] = None, margin: Union[float, "ParamRef"] = None, marginBottom: Union[float, "ParamRef"] = None, marginLeft: Union[float, "ParamRef"] = None, marginRight: Union[float, "ParamRef"] = None, marginTop: Union[float, "ParamRef"] = None, mixBlendMode: Union[str, "ParamRef"] = None, opacity: "ChannelValueSpec" = None, paintOrder: Union[str, "ParamRef"] = None, pointerEvents: Union[str, "ParamRef"] = None, r: Union["ChannelValueSpec", float, "ParamRef"] = None, reverse: Union[bool, "ParamRef"] = None, rotate: Union["ChannelValue", float, "ParamRef"] = None, select: "SelectFilter" = None, shapeRendering: Union[str, "ParamRef"] = None, sort: Union["SortOrder", "ChannelDomainSort"] = None, stroke: Union["ChannelValueSpec", "ParamRef"] = None, strokeDasharray: Union[str, float, "ParamRef"] = None, strokeDashoffset: Union[str, float, "ParamRef"] = None, strokeLinecap: Union[str, "ParamRef"] = None, strokeLinejoin: Union[str, "ParamRef"] = None, strokeMiterlimit: Union[float, "ParamRef"] = None, strokeOpacity: "ChannelValueSpec" = None, strokeWidth: "ChannelValueSpec" = None, symbol: Union["ChannelValueSpec", "SymbolType", "ParamRef"] = None, target: Union[str, "ParamRef"] = None, tip: Union[bool, "TipPointer", Dict[str, Any], "ParamRef"] = None, title: "ChannelValue" = None, x: "ChannelValueIntervalSpec" = None, y: "ChannelValueSpec" = None, z: "ChannelValue" = None): + self.ariaDescription = ariaDescription + self.ariaHidden = ariaHidden + self.ariaLabel = ariaLabel + self.clip = clip + self.data = data + self.dx = dx + self.dy = dy + self.facet = facet + self.facetAnchor = facetAnchor + self.fill = fill + self.fillOpacity = fillOpacity + self.filter = filter + self.frameAnchor = frameAnchor + self.fx = fx + self.fy = fy + self.href = href + self.imageFilter = imageFilter + self.interval = interval + self.margin = margin + self.marginBottom = marginBottom + self.marginLeft = marginLeft + self.marginRight = marginRight + self.marginTop = marginTop + self.mark = mark + self.mixBlendMode = mixBlendMode + self.opacity = opacity + self.paintOrder = paintOrder + self.pointerEvents = pointerEvents + self.r = r + self.reverse = reverse + self.rotate = rotate + self.select = select + self.shapeRendering = shapeRendering + self.sort = sort + self.stroke = stroke + self.strokeDasharray = strokeDasharray + self.strokeDashoffset = strokeDashoffset + self.strokeLinecap = strokeLinecap + self.strokeLinejoin = strokeLinejoin + self.strokeMiterlimit = strokeMiterlimit + self.strokeOpacity = strokeOpacity + self.strokeWidth = strokeWidth + self.symbol = symbol + self.target = target + self.tip = tip + self.title = title + self.x = x + self.y = y + self.z = z + + +class GridFx: + def __init__(self, mark: str, anchor: Union[str, str, str, str, "ParamRef"] = None, ariaDescription: Union[str, "ParamRef"] = None, ariaHidden: Union[str, "ParamRef"] = None, ariaLabel: "ChannelValue" = None, clip: Union[str, str, bool, Any, "ParamRef"] = None, color: Union["ChannelValueSpec", "ParamRef"] = None, dx: Union[float, "ParamRef"] = None, dy: Union[float, "ParamRef"] = None, facet: Union[str, str, str, str, bool, Any, "ParamRef"] = None, facetAnchor: Union[str, str, str, str, str, str, str, str, str, str, str, str, str, Any, "ParamRef"] = None, fill: Union["ChannelValueSpec", "ParamRef"] = None, fillOpacity: Union["ChannelValueSpec", "ParamRef"] = None, filter: "ChannelValue" = None, fx: "ChannelValue" = None, fy: "ChannelValue" = None, href: "ChannelValue" = None, imageFilter: Union[str, "ParamRef"] = None, inset: Union[float, "ParamRef"] = None, insetBottom: Union[float, "ParamRef"] = None, insetTop: Union[float, "ParamRef"] = None, interval: Union["Interval", "ParamRef"] = None, margin: Union[float, "ParamRef"] = None, marginBottom: Union[float, "ParamRef"] = None, marginLeft: Union[float, "ParamRef"] = None, marginRight: Union[float, "ParamRef"] = None, marginTop: Union[float, "ParamRef"] = None, marker: Union["MarkerName", str, bool, Any, "ParamRef"] = None, markerEnd: Union["MarkerName", str, bool, Any, "ParamRef"] = None, markerMid: Union["MarkerName", str, bool, Any, "ParamRef"] = None, markerStart: Union["MarkerName", str, bool, Any, "ParamRef"] = None, mixBlendMode: Union[str, "ParamRef"] = None, opacity: "ChannelValueSpec" = None, paintOrder: Union[str, "ParamRef"] = None, pointerEvents: Union[str, "ParamRef"] = None, reverse: Union[bool, "ParamRef"] = None, select: "SelectFilter" = None, shapeRendering: Union[str, "ParamRef"] = None, sort: Union["SortOrder", "ChannelDomainSort"] = None, stroke: Union["ChannelValueSpec", "ParamRef"] = None, strokeDasharray: Union[str, float, "ParamRef"] = None, strokeDashoffset: Union[str, float, "ParamRef"] = None, strokeLinecap: Union[str, "ParamRef"] = None, strokeLinejoin: Union[str, "ParamRef"] = None, strokeMiterlimit: Union[float, "ParamRef"] = None, strokeOpacity: "ChannelValueSpec" = None, strokeWidth: "ChannelValueSpec" = None, target: Union[str, "ParamRef"] = None, tickSpacing: Union[float, "ParamRef"] = None, ticks: Union[float, "Interval", List[Any], "ParamRef"] = None, tip: Union[bool, "TipPointer", Dict[str, Any], "ParamRef"] = None, title: "ChannelValue" = None, x: "ChannelValueSpec" = None, y: "ChannelValueIntervalSpec" = None, y1: "ChannelValueSpec" = None, y2: "ChannelValueSpec" = None): + self.anchor = anchor + self.ariaDescription = ariaDescription + self.ariaHidden = ariaHidden + self.ariaLabel = ariaLabel + self.clip = clip + self.color = color + self.dx = dx + self.dy = dy + self.facet = facet + self.facetAnchor = facetAnchor + self.fill = fill + self.fillOpacity = fillOpacity + self.filter = filter + self.fx = fx + self.fy = fy + self.href = href + self.imageFilter = imageFilter + self.inset = inset + self.insetBottom = insetBottom + self.insetTop = insetTop + self.interval = interval + self.margin = margin + self.marginBottom = marginBottom + self.marginLeft = marginLeft + self.marginRight = marginRight + self.marginTop = marginTop + self.mark = mark + self.marker = marker + self.markerEnd = markerEnd + self.markerMid = markerMid + self.markerStart = markerStart + self.mixBlendMode = mixBlendMode + self.opacity = opacity + self.paintOrder = paintOrder + self.pointerEvents = pointerEvents + self.reverse = reverse + self.select = select + self.shapeRendering = shapeRendering + self.sort = sort + self.stroke = stroke + self.strokeDasharray = strokeDasharray + self.strokeDashoffset = strokeDashoffset + self.strokeLinecap = strokeLinecap + self.strokeLinejoin = strokeLinejoin + self.strokeMiterlimit = strokeMiterlimit + self.strokeOpacity = strokeOpacity + self.strokeWidth = strokeWidth + self.target = target + self.tickSpacing = tickSpacing + self.ticks = ticks + self.tip = tip + self.title = title + self.x = x + self.y = y + self.y1 = y1 + self.y2 = y2 + + +class GridFy: + def __init__(self, mark: str, anchor: Union[str, str, str, str, "ParamRef"] = None, ariaDescription: Union[str, "ParamRef"] = None, ariaHidden: Union[str, "ParamRef"] = None, ariaLabel: "ChannelValue" = None, clip: Union[str, str, bool, Any, "ParamRef"] = None, color: Union["ChannelValueSpec", "ParamRef"] = None, dx: Union[float, "ParamRef"] = None, dy: Union[float, "ParamRef"] = None, facet: Union[str, str, str, str, bool, Any, "ParamRef"] = None, facetAnchor: Union[str, str, str, str, str, str, str, str, str, str, str, str, str, Any, "ParamRef"] = None, fill: Union["ChannelValueSpec", "ParamRef"] = None, fillOpacity: Union["ChannelValueSpec", "ParamRef"] = None, filter: "ChannelValue" = None, fx: "ChannelValue" = None, fy: "ChannelValue" = None, href: "ChannelValue" = None, imageFilter: Union[str, "ParamRef"] = None, inset: Union[float, "ParamRef"] = None, insetLeft: Union[float, "ParamRef"] = None, insetRight: Union[float, "ParamRef"] = None, interval: Union["Interval", "ParamRef"] = None, margin: Union[float, "ParamRef"] = None, marginBottom: Union[float, "ParamRef"] = None, marginLeft: Union[float, "ParamRef"] = None, marginRight: Union[float, "ParamRef"] = None, marginTop: Union[float, "ParamRef"] = None, marker: Union["MarkerName", str, bool, Any, "ParamRef"] = None, markerEnd: Union["MarkerName", str, bool, Any, "ParamRef"] = None, markerMid: Union["MarkerName", str, bool, Any, "ParamRef"] = None, markerStart: Union["MarkerName", str, bool, Any, "ParamRef"] = None, mixBlendMode: Union[str, "ParamRef"] = None, opacity: "ChannelValueSpec" = None, paintOrder: Union[str, "ParamRef"] = None, pointerEvents: Union[str, "ParamRef"] = None, reverse: Union[bool, "ParamRef"] = None, select: "SelectFilter" = None, shapeRendering: Union[str, "ParamRef"] = None, sort: Union["SortOrder", "ChannelDomainSort"] = None, stroke: Union["ChannelValueSpec", "ParamRef"] = None, strokeDasharray: Union[str, float, "ParamRef"] = None, strokeDashoffset: Union[str, float, "ParamRef"] = None, strokeLinecap: Union[str, "ParamRef"] = None, strokeLinejoin: Union[str, "ParamRef"] = None, strokeMiterlimit: Union[float, "ParamRef"] = None, strokeOpacity: "ChannelValueSpec" = None, strokeWidth: "ChannelValueSpec" = None, target: Union[str, "ParamRef"] = None, tickSpacing: Union[float, "ParamRef"] = None, ticks: Union[float, "Interval", List[Any], "ParamRef"] = None, tip: Union[bool, "TipPointer", Dict[str, Any], "ParamRef"] = None, title: "ChannelValue" = None, x: "ChannelValueIntervalSpec" = None, x1: "ChannelValueSpec" = None, x2: "ChannelValueSpec" = None, y: "ChannelValueSpec" = None): + self.anchor = anchor + self.ariaDescription = ariaDescription + self.ariaHidden = ariaHidden + self.ariaLabel = ariaLabel + self.clip = clip + self.color = color + self.dx = dx + self.dy = dy + self.facet = facet + self.facetAnchor = facetAnchor + self.fill = fill + self.fillOpacity = fillOpacity + self.filter = filter + self.fx = fx + self.fy = fy + self.href = href + self.imageFilter = imageFilter + self.inset = inset + self.insetLeft = insetLeft + self.insetRight = insetRight + self.interval = interval + self.margin = margin + self.marginBottom = marginBottom + self.marginLeft = marginLeft + self.marginRight = marginRight + self.marginTop = marginTop + self.mark = mark + self.marker = marker + self.markerEnd = markerEnd + self.markerMid = markerMid + self.markerStart = markerStart + self.mixBlendMode = mixBlendMode + self.opacity = opacity + self.paintOrder = paintOrder + self.pointerEvents = pointerEvents + self.reverse = reverse + self.select = select + self.shapeRendering = shapeRendering + self.sort = sort + self.stroke = stroke + self.strokeDasharray = strokeDasharray + self.strokeDashoffset = strokeDashoffset + self.strokeLinecap = strokeLinecap + self.strokeLinejoin = strokeLinejoin + self.strokeMiterlimit = strokeMiterlimit + self.strokeOpacity = strokeOpacity + self.strokeWidth = strokeWidth + self.target = target + self.tickSpacing = tickSpacing + self.ticks = ticks + self.tip = tip + self.title = title + self.x = x + self.x1 = x1 + self.x2 = x2 + self.y = y + + +class GridX: + def __init__(self, mark: str, anchor: Union[str, str, str, str, "ParamRef"] = None, ariaDescription: Union[str, "ParamRef"] = None, ariaHidden: Union[str, "ParamRef"] = None, ariaLabel: "ChannelValue" = None, clip: Union[str, str, bool, Any, "ParamRef"] = None, color: Union["ChannelValueSpec", "ParamRef"] = None, dx: Union[float, "ParamRef"] = None, dy: Union[float, "ParamRef"] = None, facet: Union[str, str, str, str, bool, Any, "ParamRef"] = None, facetAnchor: Union[str, str, str, str, str, str, str, str, str, str, str, str, str, Any, "ParamRef"] = None, fill: Union["ChannelValueSpec", "ParamRef"] = None, fillOpacity: Union["ChannelValueSpec", "ParamRef"] = None, filter: "ChannelValue" = None, fx: "ChannelValue" = None, fy: "ChannelValue" = None, href: "ChannelValue" = None, imageFilter: Union[str, "ParamRef"] = None, inset: Union[float, "ParamRef"] = None, insetBottom: Union[float, "ParamRef"] = None, insetTop: Union[float, "ParamRef"] = None, interval: Union["Interval", "ParamRef"] = None, margin: Union[float, "ParamRef"] = None, marginBottom: Union[float, "ParamRef"] = None, marginLeft: Union[float, "ParamRef"] = None, marginRight: Union[float, "ParamRef"] = None, marginTop: Union[float, "ParamRef"] = None, marker: Union["MarkerName", str, bool, Any, "ParamRef"] = None, markerEnd: Union["MarkerName", str, bool, Any, "ParamRef"] = None, markerMid: Union["MarkerName", str, bool, Any, "ParamRef"] = None, markerStart: Union["MarkerName", str, bool, Any, "ParamRef"] = None, mixBlendMode: Union[str, "ParamRef"] = None, opacity: "ChannelValueSpec" = None, paintOrder: Union[str, "ParamRef"] = None, pointerEvents: Union[str, "ParamRef"] = None, reverse: Union[bool, "ParamRef"] = None, select: "SelectFilter" = None, shapeRendering: Union[str, "ParamRef"] = None, sort: Union["SortOrder", "ChannelDomainSort"] = None, stroke: Union["ChannelValueSpec", "ParamRef"] = None, strokeDasharray: Union[str, float, "ParamRef"] = None, strokeDashoffset: Union[str, float, "ParamRef"] = None, strokeLinecap: Union[str, "ParamRef"] = None, strokeLinejoin: Union[str, "ParamRef"] = None, strokeMiterlimit: Union[float, "ParamRef"] = None, strokeOpacity: "ChannelValueSpec" = None, strokeWidth: "ChannelValueSpec" = None, target: Union[str, "ParamRef"] = None, tickSpacing: Union[float, "ParamRef"] = None, ticks: Union[float, "Interval", List[Any], "ParamRef"] = None, tip: Union[bool, "TipPointer", Dict[str, Any], "ParamRef"] = None, title: "ChannelValue" = None, x: "ChannelValueSpec" = None, y: "ChannelValueIntervalSpec" = None, y1: "ChannelValueSpec" = None, y2: "ChannelValueSpec" = None): + self.anchor = anchor + self.ariaDescription = ariaDescription + self.ariaHidden = ariaHidden + self.ariaLabel = ariaLabel + self.clip = clip + self.color = color + self.dx = dx + self.dy = dy + self.facet = facet + self.facetAnchor = facetAnchor + self.fill = fill + self.fillOpacity = fillOpacity + self.filter = filter + self.fx = fx + self.fy = fy + self.href = href + self.imageFilter = imageFilter + self.inset = inset + self.insetBottom = insetBottom + self.insetTop = insetTop + self.interval = interval + self.margin = margin + self.marginBottom = marginBottom + self.marginLeft = marginLeft + self.marginRight = marginRight + self.marginTop = marginTop + self.mark = mark + self.marker = marker + self.markerEnd = markerEnd + self.markerMid = markerMid + self.markerStart = markerStart + self.mixBlendMode = mixBlendMode + self.opacity = opacity + self.paintOrder = paintOrder + self.pointerEvents = pointerEvents + self.reverse = reverse + self.select = select + self.shapeRendering = shapeRendering + self.sort = sort + self.stroke = stroke + self.strokeDasharray = strokeDasharray + self.strokeDashoffset = strokeDashoffset + self.strokeLinecap = strokeLinecap + self.strokeLinejoin = strokeLinejoin + self.strokeMiterlimit = strokeMiterlimit + self.strokeOpacity = strokeOpacity + self.strokeWidth = strokeWidth + self.target = target + self.tickSpacing = tickSpacing + self.ticks = ticks + self.tip = tip + self.title = title + self.x = x + self.y = y + self.y1 = y1 + self.y2 = y2 + + +class GridY: + def __init__(self, mark: str, anchor: Union[str, str, str, str, "ParamRef"] = None, ariaDescription: Union[str, "ParamRef"] = None, ariaHidden: Union[str, "ParamRef"] = None, ariaLabel: "ChannelValue" = None, clip: Union[str, str, bool, Any, "ParamRef"] = None, color: Union["ChannelValueSpec", "ParamRef"] = None, dx: Union[float, "ParamRef"] = None, dy: Union[float, "ParamRef"] = None, facet: Union[str, str, str, str, bool, Any, "ParamRef"] = None, facetAnchor: Union[str, str, str, str, str, str, str, str, str, str, str, str, str, Any, "ParamRef"] = None, fill: Union["ChannelValueSpec", "ParamRef"] = None, fillOpacity: Union["ChannelValueSpec", "ParamRef"] = None, filter: "ChannelValue" = None, fx: "ChannelValue" = None, fy: "ChannelValue" = None, href: "ChannelValue" = None, imageFilter: Union[str, "ParamRef"] = None, inset: Union[float, "ParamRef"] = None, insetLeft: Union[float, "ParamRef"] = None, insetRight: Union[float, "ParamRef"] = None, interval: Union["Interval", "ParamRef"] = None, margin: Union[float, "ParamRef"] = None, marginBottom: Union[float, "ParamRef"] = None, marginLeft: Union[float, "ParamRef"] = None, marginRight: Union[float, "ParamRef"] = None, marginTop: Union[float, "ParamRef"] = None, marker: Union["MarkerName", str, bool, Any, "ParamRef"] = None, markerEnd: Union["MarkerName", str, bool, Any, "ParamRef"] = None, markerMid: Union["MarkerName", str, bool, Any, "ParamRef"] = None, markerStart: Union["MarkerName", str, bool, Any, "ParamRef"] = None, mixBlendMode: Union[str, "ParamRef"] = None, opacity: "ChannelValueSpec" = None, paintOrder: Union[str, "ParamRef"] = None, pointerEvents: Union[str, "ParamRef"] = None, reverse: Union[bool, "ParamRef"] = None, select: "SelectFilter" = None, shapeRendering: Union[str, "ParamRef"] = None, sort: Union["SortOrder", "ChannelDomainSort"] = None, stroke: Union["ChannelValueSpec", "ParamRef"] = None, strokeDasharray: Union[str, float, "ParamRef"] = None, strokeDashoffset: Union[str, float, "ParamRef"] = None, strokeLinecap: Union[str, "ParamRef"] = None, strokeLinejoin: Union[str, "ParamRef"] = None, strokeMiterlimit: Union[float, "ParamRef"] = None, strokeOpacity: "ChannelValueSpec" = None, strokeWidth: "ChannelValueSpec" = None, target: Union[str, "ParamRef"] = None, tickSpacing: Union[float, "ParamRef"] = None, ticks: Union[float, "Interval", List[Any], "ParamRef"] = None, tip: Union[bool, "TipPointer", Dict[str, Any], "ParamRef"] = None, title: "ChannelValue" = None, x: "ChannelValueIntervalSpec" = None, x1: "ChannelValueSpec" = None, x2: "ChannelValueSpec" = None, y: "ChannelValueSpec" = None): + self.anchor = anchor + self.ariaDescription = ariaDescription + self.ariaHidden = ariaHidden + self.ariaLabel = ariaLabel + self.clip = clip + self.color = color + self.dx = dx + self.dy = dy + self.facet = facet + self.facetAnchor = facetAnchor + self.fill = fill + self.fillOpacity = fillOpacity + self.filter = filter + self.fx = fx + self.fy = fy + self.href = href + self.imageFilter = imageFilter + self.inset = inset + self.insetLeft = insetLeft + self.insetRight = insetRight + self.interval = interval + self.margin = margin + self.marginBottom = marginBottom + self.marginLeft = marginLeft + self.marginRight = marginRight + self.marginTop = marginTop + self.mark = mark + self.marker = marker + self.markerEnd = markerEnd + self.markerMid = markerMid + self.markerStart = markerStart + self.mixBlendMode = mixBlendMode + self.opacity = opacity + self.paintOrder = paintOrder + self.pointerEvents = pointerEvents + self.reverse = reverse + self.select = select + self.shapeRendering = shapeRendering + self.sort = sort + self.stroke = stroke + self.strokeDasharray = strokeDasharray + self.strokeDashoffset = strokeDashoffset + self.strokeLinecap = strokeLinecap + self.strokeLinejoin = strokeLinejoin + self.strokeMiterlimit = strokeMiterlimit + self.strokeOpacity = strokeOpacity + self.strokeWidth = strokeWidth + self.target = target + self.tickSpacing = tickSpacing + self.ticks = ticks + self.tip = tip + self.title = title + self.x = x + self.x1 = x1 + self.x2 = x2 + self.y = y + + +class Rect: + def __init__(self, data: "PlotMarkData", mark: str, ariaDescription: Union[str, "ParamRef"] = None, ariaHidden: Union[str, "ParamRef"] = None, ariaLabel: "ChannelValue" = None, clip: Union[str, str, bool, Any, "ParamRef"] = None, dx: Union[float, "ParamRef"] = None, dy: Union[float, "ParamRef"] = None, facet: Union[str, str, str, str, bool, Any, "ParamRef"] = None, facetAnchor: Union[str, str, str, str, str, str, str, str, str, str, str, str, str, Any, "ParamRef"] = None, fill: Union["ChannelValueSpec", "ParamRef"] = None, fillOpacity: Union["ChannelValueSpec", "ParamRef"] = None, filter: "ChannelValue" = None, fx: "ChannelValue" = None, fy: "ChannelValue" = None, href: "ChannelValue" = None, imageFilter: Union[str, "ParamRef"] = None, inset: Union[float, "ParamRef"] = None, insetBottom: Union[float, "ParamRef"] = None, insetLeft: Union[float, "ParamRef"] = None, insetRight: Union[float, "ParamRef"] = None, insetTop: Union[float, "ParamRef"] = None, interval: Union["Interval", "ParamRef"] = None, margin: Union[float, "ParamRef"] = None, marginBottom: Union[float, "ParamRef"] = None, marginLeft: Union[float, "ParamRef"] = None, marginRight: Union[float, "ParamRef"] = None, marginTop: Union[float, "ParamRef"] = None, mixBlendMode: Union[str, "ParamRef"] = None, offset: Union["StackOffset", Any, "ParamRef"] = None, opacity: "ChannelValueSpec" = None, order: Union["StackOrder", Any, "ParamRef"] = None, paintOrder: Union[str, "ParamRef"] = None, pointerEvents: Union[str, "ParamRef"] = None, reverse: Union[bool, "ParamRef"] = None, rx: Union[float, str, "ParamRef"] = None, ry: Union[float, str, "ParamRef"] = None, select: "SelectFilter" = None, shapeRendering: Union[str, "ParamRef"] = None, sort: Union["SortOrder", "ChannelDomainSort"] = None, stroke: Union["ChannelValueSpec", "ParamRef"] = None, strokeDasharray: Union[str, float, "ParamRef"] = None, strokeDashoffset: Union[str, float, "ParamRef"] = None, strokeLinecap: Union[str, "ParamRef"] = None, strokeLinejoin: Union[str, "ParamRef"] = None, strokeMiterlimit: Union[float, "ParamRef"] = None, strokeOpacity: "ChannelValueSpec" = None, strokeWidth: "ChannelValueSpec" = None, target: Union[str, "ParamRef"] = None, tip: Union[bool, "TipPointer", Dict[str, Any], "ParamRef"] = None, title: "ChannelValue" = None, x: "ChannelValueIntervalSpec" = None, x1: "ChannelValueSpec" = None, x2: "ChannelValueSpec" = None, y: "ChannelValueIntervalSpec" = None, y1: "ChannelValueSpec" = None, y2: "ChannelValueSpec" = None, z: "ChannelValue" = None): + self.ariaDescription = ariaDescription + self.ariaHidden = ariaHidden + self.ariaLabel = ariaLabel + self.clip = clip + self.data = data + self.dx = dx + self.dy = dy + self.facet = facet + self.facetAnchor = facetAnchor + self.fill = fill + self.fillOpacity = fillOpacity + self.filter = filter + self.fx = fx + self.fy = fy + self.href = href + self.imageFilter = imageFilter + self.inset = inset + self.insetBottom = insetBottom + self.insetLeft = insetLeft + self.insetRight = insetRight + self.insetTop = insetTop + self.interval = interval + self.margin = margin + self.marginBottom = marginBottom + self.marginLeft = marginLeft + self.marginRight = marginRight + self.marginTop = marginTop + self.mark = mark + self.mixBlendMode = mixBlendMode + self.offset = offset + self.opacity = opacity + self.order = order + self.paintOrder = paintOrder + self.pointerEvents = pointerEvents + self.reverse = reverse + self.rx = rx + self.ry = ry + self.select = select + self.shapeRendering = shapeRendering + self.sort = sort + self.stroke = stroke + self.strokeDasharray = strokeDasharray + self.strokeDashoffset = strokeDashoffset + self.strokeLinecap = strokeLinecap + self.strokeLinejoin = strokeLinejoin + self.strokeMiterlimit = strokeMiterlimit + self.strokeOpacity = strokeOpacity + self.strokeWidth = strokeWidth + self.target = target + self.tip = tip + self.title = title + self.x = x + self.x1 = x1 + self.x2 = x2 + self.y = y + self.y1 = y1 + self.y2 = y2 + self.z = z + + +class RectX: + def __init__(self, data: "PlotMarkData", mark: str, ariaDescription: Union[str, "ParamRef"] = None, ariaHidden: Union[str, "ParamRef"] = None, ariaLabel: "ChannelValue" = None, clip: Union[str, str, bool, Any, "ParamRef"] = None, dx: Union[float, "ParamRef"] = None, dy: Union[float, "ParamRef"] = None, facet: Union[str, str, str, str, bool, Any, "ParamRef"] = None, facetAnchor: Union[str, str, str, str, str, str, str, str, str, str, str, str, str, Any, "ParamRef"] = None, fill: Union["ChannelValueSpec", "ParamRef"] = None, fillOpacity: Union["ChannelValueSpec", "ParamRef"] = None, filter: "ChannelValue" = None, fx: "ChannelValue" = None, fy: "ChannelValue" = None, href: "ChannelValue" = None, imageFilter: Union[str, "ParamRef"] = None, inset: Union[float, "ParamRef"] = None, insetBottom: Union[float, "ParamRef"] = None, insetLeft: Union[float, "ParamRef"] = None, insetRight: Union[float, "ParamRef"] = None, insetTop: Union[float, "ParamRef"] = None, interval: Union["Interval", "ParamRef"] = None, margin: Union[float, "ParamRef"] = None, marginBottom: Union[float, "ParamRef"] = None, marginLeft: Union[float, "ParamRef"] = None, marginRight: Union[float, "ParamRef"] = None, marginTop: Union[float, "ParamRef"] = None, mixBlendMode: Union[str, "ParamRef"] = None, offset: Union["StackOffset", Any, "ParamRef"] = None, opacity: "ChannelValueSpec" = None, order: Union["StackOrder", Any, "ParamRef"] = None, paintOrder: Union[str, "ParamRef"] = None, pointerEvents: Union[str, "ParamRef"] = None, reverse: Union[bool, "ParamRef"] = None, rx: Union[float, str, "ParamRef"] = None, ry: Union[float, str, "ParamRef"] = None, select: "SelectFilter" = None, shapeRendering: Union[str, "ParamRef"] = None, sort: Union["SortOrder", "ChannelDomainSort"] = None, stroke: Union["ChannelValueSpec", "ParamRef"] = None, strokeDasharray: Union[str, float, "ParamRef"] = None, strokeDashoffset: Union[str, float, "ParamRef"] = None, strokeLinecap: Union[str, "ParamRef"] = None, strokeLinejoin: Union[str, "ParamRef"] = None, strokeMiterlimit: Union[float, "ParamRef"] = None, strokeOpacity: "ChannelValueSpec" = None, strokeWidth: "ChannelValueSpec" = None, target: Union[str, "ParamRef"] = None, tip: Union[bool, "TipPointer", Dict[str, Any], "ParamRef"] = None, title: "ChannelValue" = None, x: "ChannelValueSpec" = None, x1: "ChannelValueSpec" = None, x2: "ChannelValueSpec" = None, y: "ChannelValueIntervalSpec" = None, y1: "ChannelValueSpec" = None, y2: "ChannelValueSpec" = None, z: "ChannelValue" = None): + self.ariaDescription = ariaDescription + self.ariaHidden = ariaHidden + self.ariaLabel = ariaLabel + self.clip = clip + self.data = data + self.dx = dx + self.dy = dy + self.facet = facet + self.facetAnchor = facetAnchor + self.fill = fill + self.fillOpacity = fillOpacity + self.filter = filter + self.fx = fx + self.fy = fy + self.href = href + self.imageFilter = imageFilter + self.inset = inset + self.insetBottom = insetBottom + self.insetLeft = insetLeft + self.insetRight = insetRight + self.insetTop = insetTop + self.interval = interval + self.margin = margin + self.marginBottom = marginBottom + self.marginLeft = marginLeft + self.marginRight = marginRight + self.marginTop = marginTop + self.mark = mark + self.mixBlendMode = mixBlendMode + self.offset = offset + self.opacity = opacity + self.order = order + self.paintOrder = paintOrder + self.pointerEvents = pointerEvents + self.reverse = reverse + self.rx = rx + self.ry = ry + self.select = select + self.shapeRendering = shapeRendering + self.sort = sort + self.stroke = stroke + self.strokeDasharray = strokeDasharray + self.strokeDashoffset = strokeDashoffset + self.strokeLinecap = strokeLinecap + self.strokeLinejoin = strokeLinejoin + self.strokeMiterlimit = strokeMiterlimit + self.strokeOpacity = strokeOpacity + self.strokeWidth = strokeWidth + self.target = target + self.tip = tip + self.title = title + self.x = x + self.x1 = x1 + self.x2 = x2 + self.y = y + self.y1 = y1 + self.y2 = y2 + self.z = z + + +class RectY: + def __init__(self, data: "PlotMarkData", mark: str, ariaDescription: Union[str, "ParamRef"] = None, ariaHidden: Union[str, "ParamRef"] = None, ariaLabel: "ChannelValue" = None, clip: Union[str, str, bool, Any, "ParamRef"] = None, dx: Union[float, "ParamRef"] = None, dy: Union[float, "ParamRef"] = None, facet: Union[str, str, str, str, bool, Any, "ParamRef"] = None, facetAnchor: Union[str, str, str, str, str, str, str, str, str, str, str, str, str, Any, "ParamRef"] = None, fill: Union["ChannelValueSpec", "ParamRef"] = None, fillOpacity: Union["ChannelValueSpec", "ParamRef"] = None, filter: "ChannelValue" = None, fx: "ChannelValue" = None, fy: "ChannelValue" = None, href: "ChannelValue" = None, imageFilter: Union[str, "ParamRef"] = None, inset: Union[float, "ParamRef"] = None, insetBottom: Union[float, "ParamRef"] = None, insetLeft: Union[float, "ParamRef"] = None, insetRight: Union[float, "ParamRef"] = None, insetTop: Union[float, "ParamRef"] = None, interval: Union["Interval", "ParamRef"] = None, margin: Union[float, "ParamRef"] = None, marginBottom: Union[float, "ParamRef"] = None, marginLeft: Union[float, "ParamRef"] = None, marginRight: Union[float, "ParamRef"] = None, marginTop: Union[float, "ParamRef"] = None, mixBlendMode: Union[str, "ParamRef"] = None, offset: Union["StackOffset", Any, "ParamRef"] = None, opacity: "ChannelValueSpec" = None, order: Union["StackOrder", Any, "ParamRef"] = None, paintOrder: Union[str, "ParamRef"] = None, pointerEvents: Union[str, "ParamRef"] = None, reverse: Union[bool, "ParamRef"] = None, rx: Union[float, str, "ParamRef"] = None, ry: Union[float, str, "ParamRef"] = None, select: "SelectFilter" = None, shapeRendering: Union[str, "ParamRef"] = None, sort: Union["SortOrder", "ChannelDomainSort"] = None, stroke: Union["ChannelValueSpec", "ParamRef"] = None, strokeDasharray: Union[str, float, "ParamRef"] = None, strokeDashoffset: Union[str, float, "ParamRef"] = None, strokeLinecap: Union[str, "ParamRef"] = None, strokeLinejoin: Union[str, "ParamRef"] = None, strokeMiterlimit: Union[float, "ParamRef"] = None, strokeOpacity: "ChannelValueSpec" = None, strokeWidth: "ChannelValueSpec" = None, target: Union[str, "ParamRef"] = None, tip: Union[bool, "TipPointer", Dict[str, Any], "ParamRef"] = None, title: "ChannelValue" = None, x: "ChannelValueIntervalSpec" = None, x1: "ChannelValueSpec" = None, x2: "ChannelValueSpec" = None, y: "ChannelValueSpec" = None, y1: "ChannelValueSpec" = None, y2: "ChannelValueSpec" = None, z: "ChannelValue" = None): + self.ariaDescription = ariaDescription + self.ariaHidden = ariaHidden + self.ariaLabel = ariaLabel + self.clip = clip + self.data = data + self.dx = dx + self.dy = dy + self.facet = facet + self.facetAnchor = facetAnchor + self.fill = fill + self.fillOpacity = fillOpacity + self.filter = filter + self.fx = fx + self.fy = fy + self.href = href + self.imageFilter = imageFilter + self.inset = inset + self.insetBottom = insetBottom + self.insetLeft = insetLeft + self.insetRight = insetRight + self.insetTop = insetTop + self.interval = interval + self.margin = margin + self.marginBottom = marginBottom + self.marginLeft = marginLeft + self.marginRight = marginRight + self.marginTop = marginTop + self.mark = mark + self.mixBlendMode = mixBlendMode + self.offset = offset + self.opacity = opacity + self.order = order + self.paintOrder = paintOrder + self.pointerEvents = pointerEvents + self.reverse = reverse + self.rx = rx + self.ry = ry + self.select = select + self.shapeRendering = shapeRendering + self.sort = sort + self.stroke = stroke + self.strokeDasharray = strokeDasharray + self.strokeDashoffset = strokeDashoffset + self.strokeLinecap = strokeLinecap + self.strokeLinejoin = strokeLinejoin + self.strokeMiterlimit = strokeMiterlimit + self.strokeOpacity = strokeOpacity + self.strokeWidth = strokeWidth + self.target = target + self.tip = tip + self.title = title + self.x = x + self.x1 = x1 + self.x2 = x2 + self.y = y + self.y1 = y1 + self.y2 = y2 + self.z = z + + +class RuleX: + def __init__(self, mark: str, ariaDescription: Union[str, "ParamRef"] = None, ariaHidden: Union[str, "ParamRef"] = None, ariaLabel: "ChannelValue" = None, clip: Union[str, str, bool, Any, "ParamRef"] = None, data: "PlotMarkData" = None, dx: Union[float, "ParamRef"] = None, dy: Union[float, "ParamRef"] = None, facet: Union[str, str, str, str, bool, Any, "ParamRef"] = None, facetAnchor: Union[str, str, str, str, str, str, str, str, str, str, str, str, str, Any, "ParamRef"] = None, fill: Union["ChannelValueSpec", "ParamRef"] = None, fillOpacity: Union["ChannelValueSpec", "ParamRef"] = None, filter: "ChannelValue" = None, fx: "ChannelValue" = None, fy: "ChannelValue" = None, href: "ChannelValue" = None, imageFilter: Union[str, "ParamRef"] = None, inset: Union[float, "ParamRef"] = None, insetBottom: Union[float, "ParamRef"] = None, insetTop: Union[float, "ParamRef"] = None, interval: Union["Interval", "ParamRef"] = None, margin: Union[float, "ParamRef"] = None, marginBottom: Union[float, "ParamRef"] = None, marginLeft: Union[float, "ParamRef"] = None, marginRight: Union[float, "ParamRef"] = None, marginTop: Union[float, "ParamRef"] = None, marker: Union["MarkerName", str, bool, Any, "ParamRef"] = None, markerEnd: Union["MarkerName", str, bool, Any, "ParamRef"] = None, markerMid: Union["MarkerName", str, bool, Any, "ParamRef"] = None, markerStart: Union["MarkerName", str, bool, Any, "ParamRef"] = None, mixBlendMode: Union[str, "ParamRef"] = None, opacity: "ChannelValueSpec" = None, paintOrder: Union[str, "ParamRef"] = None, pointerEvents: Union[str, "ParamRef"] = None, reverse: Union[bool, "ParamRef"] = None, select: "SelectFilter" = None, shapeRendering: Union[str, "ParamRef"] = None, sort: Union["SortOrder", "ChannelDomainSort"] = None, stroke: Union["ChannelValueSpec", "ParamRef"] = None, strokeDasharray: Union[str, float, "ParamRef"] = None, strokeDashoffset: Union[str, float, "ParamRef"] = None, strokeLinecap: Union[str, "ParamRef"] = None, strokeLinejoin: Union[str, "ParamRef"] = None, strokeMiterlimit: Union[float, "ParamRef"] = None, strokeOpacity: "ChannelValueSpec" = None, strokeWidth: "ChannelValueSpec" = None, target: Union[str, "ParamRef"] = None, tip: Union[bool, "TipPointer", Dict[str, Any], "ParamRef"] = None, title: "ChannelValue" = None, x: "ChannelValueSpec" = None, y: "ChannelValueIntervalSpec" = None, y1: "ChannelValueSpec" = None, y2: "ChannelValueSpec" = None): + self.ariaDescription = ariaDescription + self.ariaHidden = ariaHidden + self.ariaLabel = ariaLabel + self.clip = clip + self.data = data + self.dx = dx + self.dy = dy + self.facet = facet + self.facetAnchor = facetAnchor + self.fill = fill + self.fillOpacity = fillOpacity + self.filter = filter + self.fx = fx + self.fy = fy + self.href = href + self.imageFilter = imageFilter + self.inset = inset + self.insetBottom = insetBottom + self.insetTop = insetTop + self.interval = interval + self.margin = margin + self.marginBottom = marginBottom + self.marginLeft = marginLeft + self.marginRight = marginRight + self.marginTop = marginTop + self.mark = mark + self.marker = marker + self.markerEnd = markerEnd + self.markerMid = markerMid + self.markerStart = markerStart + self.mixBlendMode = mixBlendMode + self.opacity = opacity + self.paintOrder = paintOrder + self.pointerEvents = pointerEvents + self.reverse = reverse + self.select = select + self.shapeRendering = shapeRendering + self.sort = sort + self.stroke = stroke + self.strokeDasharray = strokeDasharray + self.strokeDashoffset = strokeDashoffset + self.strokeLinecap = strokeLinecap + self.strokeLinejoin = strokeLinejoin + self.strokeMiterlimit = strokeMiterlimit + self.strokeOpacity = strokeOpacity + self.strokeWidth = strokeWidth + self.target = target + self.tip = tip + self.title = title + self.x = x + self.y = y + self.y1 = y1 + self.y2 = y2 + + +class RuleY: + def __init__(self, mark: str, ariaDescription: Union[str, "ParamRef"] = None, ariaHidden: Union[str, "ParamRef"] = None, ariaLabel: "ChannelValue" = None, clip: Union[str, str, bool, Any, "ParamRef"] = None, data: "PlotMarkData" = None, dx: Union[float, "ParamRef"] = None, dy: Union[float, "ParamRef"] = None, facet: Union[str, str, str, str, bool, Any, "ParamRef"] = None, facetAnchor: Union[str, str, str, str, str, str, str, str, str, str, str, str, str, Any, "ParamRef"] = None, fill: Union["ChannelValueSpec", "ParamRef"] = None, fillOpacity: Union["ChannelValueSpec", "ParamRef"] = None, filter: "ChannelValue" = None, fx: "ChannelValue" = None, fy: "ChannelValue" = None, href: "ChannelValue" = None, imageFilter: Union[str, "ParamRef"] = None, inset: Union[float, "ParamRef"] = None, insetBottom: Union[float, "ParamRef"] = None, insetTop: Union[float, "ParamRef"] = None, interval: Union["Interval", "ParamRef"] = None, margin: Union[float, "ParamRef"] = None, marginBottom: Union[float, "ParamRef"] = None, marginLeft: Union[float, "ParamRef"] = None, marginRight: Union[float, "ParamRef"] = None, marginTop: Union[float, "ParamRef"] = None, marker: Union["MarkerName", str, bool, Any, "ParamRef"] = None, markerEnd: Union["MarkerName", str, bool, Any, "ParamRef"] = None, markerMid: Union["MarkerName", str, bool, Any, "ParamRef"] = None, markerStart: Union["MarkerName", str, bool, Any, "ParamRef"] = None, mixBlendMode: Union[str, "ParamRef"] = None, opacity: "ChannelValueSpec" = None, paintOrder: Union[str, "ParamRef"] = None, pointerEvents: Union[str, "ParamRef"] = None, reverse: Union[bool, "ParamRef"] = None, select: "SelectFilter" = None, shapeRendering: Union[str, "ParamRef"] = None, sort: Union["SortOrder", "ChannelDomainSort"] = None, stroke: Union["ChannelValueSpec", "ParamRef"] = None, strokeDasharray: Union[str, float, "ParamRef"] = None, strokeDashoffset: Union[str, float, "ParamRef"] = None, strokeLinecap: Union[str, "ParamRef"] = None, strokeLinejoin: Union[str, "ParamRef"] = None, strokeMiterlimit: Union[float, "ParamRef"] = None, strokeOpacity: "ChannelValueSpec" = None, strokeWidth: "ChannelValueSpec" = None, target: Union[str, "ParamRef"] = None, tip: Union[bool, "TipPointer", Dict[str, Any], "ParamRef"] = None, title: "ChannelValue" = None, x: "ChannelValueSpec" = None, y: "ChannelValueIntervalSpec" = None, y1: "ChannelValueSpec" = None, y2: "ChannelValueSpec" = None): + self.ariaDescription = ariaDescription + self.ariaHidden = ariaHidden + self.ariaLabel = ariaLabel + self.clip = clip + self.data = data + self.dx = dx + self.dy = dy + self.facet = facet + self.facetAnchor = facetAnchor + self.fill = fill + self.fillOpacity = fillOpacity + self.filter = filter + self.fx = fx + self.fy = fy + self.href = href + self.imageFilter = imageFilter + self.inset = inset + self.insetBottom = insetBottom + self.insetTop = insetTop + self.interval = interval + self.margin = margin + self.marginBottom = marginBottom + self.marginLeft = marginLeft + self.marginRight = marginRight + self.marginTop = marginTop + self.mark = mark + self.marker = marker + self.markerEnd = markerEnd + self.markerMid = markerMid + self.markerStart = markerStart + self.mixBlendMode = mixBlendMode + self.opacity = opacity + self.paintOrder = paintOrder + self.pointerEvents = pointerEvents + self.reverse = reverse + self.select = select + self.shapeRendering = shapeRendering + self.sort = sort + self.stroke = stroke + self.strokeDasharray = strokeDasharray + self.strokeDashoffset = strokeDashoffset + self.strokeLinecap = strokeLinecap + self.strokeLinejoin = strokeLinejoin + self.strokeMiterlimit = strokeMiterlimit + self.strokeOpacity = strokeOpacity + self.strokeWidth = strokeWidth + self.target = target + self.tip = tip + self.title = title + self.x = x + self.y = y + self.y1 = y1 + self.y2 = y2 + + +class TextX: + def __init__(self, mark: str, ariaDescription: Union[str, "ParamRef"] = None, ariaHidden: Union[str, "ParamRef"] = None, ariaLabel: "ChannelValue" = None, clip: Union[str, str, bool, Any, "ParamRef"] = None, data: "PlotMarkData" = None, dx: Union[float, "ParamRef"] = None, dy: Union[float, "ParamRef"] = None, facet: Union[str, str, str, str, bool, Any, "ParamRef"] = None, facetAnchor: Union[str, str, str, str, str, str, str, str, str, str, str, str, str, Any, "ParamRef"] = None, fill: Union["ChannelValueSpec", "ParamRef"] = None, fillOpacity: Union["ChannelValueSpec", "ParamRef"] = None, filter: "ChannelValue" = None, fontFamily: Union[str, "ParamRef"] = None, fontSize: Union["ChannelValue", "ParamRef"] = None, fontStyle: Union[str, "ParamRef"] = None, fontVariant: Union[str, "ParamRef"] = None, fontWeight: Union[str, float, "ParamRef"] = None, frameAnchor: Union["FrameAnchor", "ParamRef"] = None, fx: "ChannelValue" = None, fy: "ChannelValue" = None, href: "ChannelValue" = None, imageFilter: Union[str, "ParamRef"] = None, interval: Union["Interval", "ParamRef"] = None, lineAnchor: Union[str, str, str, "ParamRef"] = None, lineHeight: Union[float, "ParamRef"] = None, lineWidth: Union[float, "ParamRef"] = None, margin: Union[float, "ParamRef"] = None, marginBottom: Union[float, "ParamRef"] = None, marginLeft: Union[float, "ParamRef"] = None, marginRight: Union[float, "ParamRef"] = None, marginTop: Union[float, "ParamRef"] = None, mixBlendMode: Union[str, "ParamRef"] = None, monospace: Union[bool, "ParamRef"] = None, opacity: "ChannelValueSpec" = None, paintOrder: Union[str, "ParamRef"] = None, pointerEvents: Union[str, "ParamRef"] = None, reverse: Union[bool, "ParamRef"] = None, rotate: Union["ChannelValue", "ParamRef"] = None, select: "SelectFilter" = None, shapeRendering: Union[str, "ParamRef"] = None, sort: Union["SortOrder", "ChannelDomainSort"] = None, stroke: Union["ChannelValueSpec", "ParamRef"] = None, strokeDasharray: Union[str, float, "ParamRef"] = None, strokeDashoffset: Union[str, float, "ParamRef"] = None, strokeLinecap: Union[str, "ParamRef"] = None, strokeLinejoin: Union[str, "ParamRef"] = None, strokeMiterlimit: Union[float, "ParamRef"] = None, strokeOpacity: "ChannelValueSpec" = None, strokeWidth: "ChannelValueSpec" = None, target: Union[str, "ParamRef"] = None, text: "ChannelValue" = None, textAnchor: Union[str, str, str, "ParamRef"] = None, textOverflow: Union[Any, str, str, str, str, str, str, str, "ParamRef"] = None, tip: Union[bool, "TipPointer", Dict[str, Any], "ParamRef"] = None, title: "ChannelValue" = None, x: "ChannelValueSpec" = None, y: "ChannelValueIntervalSpec" = None, z: "ChannelValue" = None): + self.ariaDescription = ariaDescription + self.ariaHidden = ariaHidden + self.ariaLabel = ariaLabel + self.clip = clip + self.data = data + self.dx = dx + self.dy = dy + self.facet = facet + self.facetAnchor = facetAnchor + self.fill = fill + self.fillOpacity = fillOpacity + self.filter = filter + self.fontFamily = fontFamily + self.fontSize = fontSize + self.fontStyle = fontStyle + self.fontVariant = fontVariant + self.fontWeight = fontWeight + self.frameAnchor = frameAnchor + self.fx = fx + self.fy = fy + self.href = href + self.imageFilter = imageFilter + self.interval = interval + self.lineAnchor = lineAnchor + self.lineHeight = lineHeight + self.lineWidth = lineWidth + self.margin = margin + self.marginBottom = marginBottom + self.marginLeft = marginLeft + self.marginRight = marginRight + self.marginTop = marginTop + self.mark = mark + self.mixBlendMode = mixBlendMode + self.monospace = monospace + self.opacity = opacity + self.paintOrder = paintOrder + self.pointerEvents = pointerEvents + self.reverse = reverse + self.rotate = rotate + self.select = select + self.shapeRendering = shapeRendering + self.sort = sort + self.stroke = stroke + self.strokeDasharray = strokeDasharray + self.strokeDashoffset = strokeDashoffset + self.strokeLinecap = strokeLinecap + self.strokeLinejoin = strokeLinejoin + self.strokeMiterlimit = strokeMiterlimit + self.strokeOpacity = strokeOpacity + self.strokeWidth = strokeWidth + self.target = target + self.text = text + self.textAnchor = textAnchor + self.textOverflow = textOverflow + self.tip = tip + self.title = title + self.x = x + self.y = y + self.z = z + + +class Bin: + def __init__(self, bin: Union[Union[str, float, bool], List[Union[str, float, bool]]], interval: "BinInterval" = None, minstep: float = None, nice: bool = None, offset: float = None, step: float = None, steps: float = None): + self.bin = bin + self.interval = interval + self.minstep = minstep + self.nice = nice + self.offset = offset + self.step = step + self.steps = steps + + +class ChannelDomainSort: + def __init__(self, color: "ChannelDomainValueSpec" = None, fx: "ChannelDomainValueSpec" = None, fy: "ChannelDomainValueSpec" = None, length: "ChannelDomainValueSpec" = None, limit: Union[float, List[Any]] = None, opacity: "ChannelDomainValueSpec" = None, order: Union[str, Any] = None, r: "ChannelDomainValueSpec" = None, reduce: Union["Reducer", bool, Any] = None, reverse: bool = None, symbol: "ChannelDomainValueSpec" = None, x: "ChannelDomainValueSpec" = None, y: "ChannelDomainValueSpec" = None): + self.color = color + self.fx = fx + self.fy = fy + self.length = length + self.limit = limit + self.opacity = opacity + self.order = order + self.r = r + self.reduce = reduce + self.reverse = reverse + self.symbol = symbol + self.x = x + self.y = y + + +class HConcat: + def __init__(self, hconcat: List["Component"]): + self.hconcat = hconcat + + +class VConcat: + def __init__(self, vconcat: List["Component"]): + self.vconcat = vconcat + + + +class Curve: + pass # This is a reference to 'CurveName' + + +class Data: + def __init__(self): + pass + + +class Highlight: + def __init__(self, by: "ParamRef", select: str, fill: str = None, fillOpacity: float = None, opacity: float = None, stroke: str = None, strokeOpacity: float = None): + self.by = by + self.fill = fill + self.fillOpacity = fillOpacity + self.opacity = opacity + self.select = select + self.stroke = stroke + self.strokeOpacity = strokeOpacity + + +class IntervalX: + def __init__(self, select: str, as_: "ParamRef" = None, brush: "BrushStyles" = None, field: str = None, peers: bool = None, pixelSize: float = None): + self.as_ = as_ + self.brush = brush + self.field = field + self.peers = peers + self.pixelSize = pixelSize + self.select = select + + +class IntervalXY: + def __init__(self, select: str, as_: "ParamRef" = None, brush: "BrushStyles" = None, peers: bool = None, pixelSize: float = None, xfield: str = None, yfield: str = None): + self.as_ = as_ + self.brush = brush + self.peers = peers + self.pixelSize = pixelSize + self.select = select + self.xfield = xfield + self.yfield = yfield + + +class IntervalY: + def __init__(self, select: str, as_: "ParamRef" = None, brush: "BrushStyles" = None, field: str = None, peers: bool = None, pixelSize: float = None): + self.as_ = as_ + self.brush = brush + self.field = field + self.peers = peers + self.pixelSize = pixelSize + self.select = select + + +class Legend: + def __init__(self, legend: str, as_: "ParamRef" = None, columns: float = None, field: str = None, for_: str = None, height: float = None, label: str = None, marginBottom: float = None, marginLeft: float = None, marginRight: float = None, marginTop: float = None, tickSize: float = None, width: float = None): + self.as_ = as_ + self.columns = columns + self.field = field + self.for_ = for_ + self.height = height + self.label = label + self.legend = legend + self.marginBottom = marginBottom + self.marginLeft = marginLeft + self.marginRight = marginRight + self.marginTop = marginTop + self.tickSize = tickSize + self.width = width + + +class Menu: + def __init__(self, input: str, as_: "ParamRef" = None, column: str = None, field: str = None, filterBy: "ParamRef" = None, from_: str = None, label: str = None, options: List[Union[Dict[str, Any], Any]] = None, value: Any = None): + self.as_ = as_ + self.column = column + self.field = field + self.filterBy = filterBy + self.from_ = from_ + self.input = input + self.label = label + self.options = options + self.value = value + + +class NearestX: + def __init__(self, select: str, as_: "ParamRef" = None, channels: List[str] = None, fields: List[str] = None, maxRadius: float = None): + self.as_ = as_ + self.channels = channels + self.fields = fields + self.maxRadius = maxRadius + self.select = select + + +class NearestY: + def __init__(self, select: str, as_: "ParamRef" = None, channels: List[str] = None, fields: List[str] = None, maxRadius: float = None): + self.as_ = as_ + self.channels = channels + self.fields = fields + self.maxRadius = maxRadius + self.select = select + + +class Pan: + def __init__(self, select: str, x: "ParamRef" = None, xfield: str = None, y: "ParamRef" = None, yfield: str = None): + self.select = select + self.x = x + self.xfield = xfield + self.y = y + self.yfield = yfield + + +class PanX: + def __init__(self, select: str, x: "ParamRef" = None, xfield: str = None, y: "ParamRef" = None, yfield: str = None): + self.select = select + self.x = x + self.xfield = xfield + self.y = y + self.yfield = yfield + + +class PanY: + def __init__(self, select: str, x: "ParamRef" = None, xfield: str = None, y: "ParamRef" = None, yfield: str = None): + self.select = select + self.x = x + self.xfield = xfield + self.y = y + self.yfield = yfield + + +class PanZoom: + def __init__(self, select: str, x: "ParamRef" = None, xfield: str = None, y: "ParamRef" = None, yfield: str = None): + self.select = select + self.x = x + self.xfield = xfield + self.y = y + self.yfield = yfield + + +class PanZoomX: + def __init__(self, select: str, x: "ParamRef" = None, xfield: str = None, y: "ParamRef" = None, yfield: str = None): + self.select = select + self.x = x + self.xfield = xfield + self.y = y + self.yfield = yfield + + +class PanZoomY: + def __init__(self, select: str, x: "ParamRef" = None, xfield: str = None, y: "ParamRef" = None, yfield: str = None): + self.select = select + self.x = x + self.xfield = xfield + self.y = y + self.yfield = yfield + + +class PlotFrom: + def __init__(self, filterBy: "ParamRef" = None, from_: str = None, optimize: bool = None): + self.filterBy = filterBy + self.from_ = from_ + self.optimize = optimize + + +class PlotLegend: + def __init__(self, legend: str, as_: "ParamRef" = None, columns: float = None, field: str = None, height: float = None, label: str = None, marginBottom: float = None, marginLeft: float = None, marginRight: float = None, marginTop: float = None, tickSize: float = None, width: float = None): + self.as_ = as_ + self.columns = columns + self.field = field + self.height = height + self.label = label + self.legend = legend + self.marginBottom = marginBottom + self.marginLeft = marginLeft + self.marginRight = marginRight + self.marginTop = marginTop + self.tickSize = tickSize + self.width = width + + +class Search: + def __init__(self, input: str, as_: "ParamRef" = None, column: str = None, field: str = None, filterBy: "ParamRef" = None, from_: str = None, label: str = None, type: str = None): + self.as_ = as_ + self.column = column + self.field = field + self.filterBy = filterBy + self.from_ = from_ + self.input = input + self.label = label + self.type = type + + +class Slider: + def __init__(self, input: str, as_: "ParamRef" = None, column: str = None, field: str = None, filterBy: "ParamRef" = None, from_: str = None, label: str = None, max: float = None, min: float = None, select: str = None, step: float = None, value: float = None, width: float = None): + self.as_ = as_ + self.column = column + self.field = field + self.filterBy = filterBy + self.from_ = from_ + self.input = input + self.label = label + self.max = max + self.min = min + self.select = select + self.step = step + self.value = value + self.width = width + + +class Table: + def __init__(self, input: str, align: Dict[str, Any] = None, as_: "ParamRef" = None, columns: List[str] = None, filterBy: "ParamRef" = None, from_: str = None, height: float = None, maxWidth: float = None, rowBatch: float = None, width: Union[float, Dict[str, Any]] = None): + self.align = align + self.as_ = as_ + self.columns = columns + self.filterBy = filterBy + self.from_ = from_ + self.height = height + self.input = input + self.maxWidth = maxWidth + self.rowBatch = rowBatch + self.width = width + + +class Toggle: + def __init__(self, channels: List[str], select: str, as_: "ParamRef" = None, peers: bool = None): + self.as_ = as_ + self.channels = channels + self.peers = peers + self.select = select + + +class ToggleColor: + def __init__(self, select: str, as_: "ParamRef" = None, peers: bool = None): + self.as_ = as_ + self.peers = peers + self.select = select + + +class ToggleX: + def __init__(self, select: str, as_: "ParamRef" = None, peers: bool = None): + self.as_ = as_ + self.peers = peers + self.select = select + + +class ToggleY: + def __init__(self, select: str, as_: "ParamRef" = None, peers: bool = None): + self.as_ = as_ + self.peers = peers + self.select = select + + + +class Interval: + pass # This is a reference to 'LiteralTimeInterval' + + +class Param: + def __init__(self, value: "ParamValue", select: str = None): + self.select = select + self.value = value + + +class Params: + def __init__(self): + pass + + + +class StackOffset: + pass # This is a reference to 'StackOffsetName' + + + +class VectorShape: + pass # This is a reference to 'VectorShapeName' + + +class TextY: + def __init__(self, mark: str, ariaDescription: Union[str, "ParamRef"] = None, ariaHidden: Union[str, "ParamRef"] = None, ariaLabel: "ChannelValue" = None, clip: Union[str, str, bool, Any, "ParamRef"] = None, data: "PlotMarkData" = None, dx: Union[float, "ParamRef"] = None, dy: Union[float, "ParamRef"] = None, facet: Union[str, str, str, str, bool, Any, "ParamRef"] = None, facetAnchor: Union[str, str, str, str, str, str, str, str, str, str, str, str, str, Any, "ParamRef"] = None, fill: Union["ChannelValueSpec", "ParamRef"] = None, fillOpacity: Union["ChannelValueSpec", "ParamRef"] = None, filter: "ChannelValue" = None, fontFamily: Union[str, "ParamRef"] = None, fontSize: Union["ChannelValue", "ParamRef"] = None, fontStyle: Union[str, "ParamRef"] = None, fontVariant: Union[str, "ParamRef"] = None, fontWeight: Union[str, float, "ParamRef"] = None, frameAnchor: Union["FrameAnchor", "ParamRef"] = None, fx: "ChannelValue" = None, fy: "ChannelValue" = None, href: "ChannelValue" = None, imageFilter: Union[str, "ParamRef"] = None, interval: "Interval" = None, lineAnchor: Union[str, str, str, "ParamRef"] = None, lineHeight: Union[float, "ParamRef"] = None, lineWidth: Union[float, "ParamRef"] = None, margin: Union[float, "ParamRef"] = None, marginBottom: Union[float, "ParamRef"] = None, marginLeft: Union[float, "ParamRef"] = None, marginRight: Union[float, "ParamRef"] = None, marginTop: Union[float, "ParamRef"] = None, mixBlendMode: Union[str, "ParamRef"] = None, monospace: Union[bool, "ParamRef"] = None, opacity: "ChannelValueSpec" = None, paintOrder: Union[str, "ParamRef"] = None, pointerEvents: Union[str, "ParamRef"] = None, reverse: Union[bool, "ParamRef"] = None, rotate: Union["ChannelValue", "ParamRef"] = None, select: "SelectFilter" = None, shapeRendering: Union[str, "ParamRef"] = None, sort: Union["SortOrder", "ChannelDomainSort"] = None, stroke: Union["ChannelValueSpec", "ParamRef"] = None, strokeDasharray: Union[str, float, "ParamRef"] = None, strokeDashoffset: Union[str, float, "ParamRef"] = None, strokeLinecap: Union[str, "ParamRef"] = None, strokeLinejoin: Union[str, "ParamRef"] = None, strokeMiterlimit: Union[float, "ParamRef"] = None, strokeOpacity: "ChannelValueSpec" = None, strokeWidth: "ChannelValueSpec" = None, target: Union[str, "ParamRef"] = None, text: "ChannelValue" = None, textAnchor: Union[str, str, str, "ParamRef"] = None, textOverflow: Union[Any, str, str, str, str, str, str, str, "ParamRef"] = None, tip: Union[bool, "TipPointer", Dict[str, Any], "ParamRef"] = None, title: "ChannelValue" = None, x: "ChannelValueIntervalSpec" = None, y: "ChannelValueSpec" = None, z: "ChannelValue" = None): + self.ariaDescription = ariaDescription + self.ariaHidden = ariaHidden + self.ariaLabel = ariaLabel + self.clip = clip + self.data = data + self.dx = dx + self.dy = dy + self.facet = facet + self.facetAnchor = facetAnchor + self.fill = fill + self.fillOpacity = fillOpacity + self.filter = filter + self.fontFamily = fontFamily + self.fontSize = fontSize + self.fontStyle = fontStyle + self.fontVariant = fontVariant + self.fontWeight = fontWeight + self.frameAnchor = frameAnchor + self.fx = fx + self.fy = fy + self.href = href + self.imageFilter = imageFilter + self.interval = interval + self.lineAnchor = lineAnchor + self.lineHeight = lineHeight + self.lineWidth = lineWidth + self.margin = margin + self.marginBottom = marginBottom + self.marginLeft = marginLeft + self.marginRight = marginRight + self.marginTop = marginTop + self.mark = mark + self.mixBlendMode = mixBlendMode + self.monospace = monospace + self.opacity = opacity + self.paintOrder = paintOrder + self.pointerEvents = pointerEvents + self.reverse = reverse + self.rotate = rotate + self.select = select + self.shapeRendering = shapeRendering + self.sort = sort + self.stroke = stroke + self.strokeDasharray = strokeDasharray + self.strokeDashoffset = strokeDashoffset + self.strokeLinecap = strokeLinecap + self.strokeLinejoin = strokeLinejoin + self.strokeMiterlimit = strokeMiterlimit + self.strokeOpacity = strokeOpacity + self.strokeWidth = strokeWidth + self.target = target + self.text = text + self.textAnchor = textAnchor + self.textOverflow = textOverflow + self.tip = tip + self.title = title + self.x = x + self.y = y + self.z = z diff --git a/packages/schema_wrapper/pyproject.toml b/packages/schema_wrapper/pyproject.toml new file mode 100644 index 00000000..fdfe040e --- /dev/null +++ b/packages/schema_wrapper/pyproject.toml @@ -0,0 +1,59 @@ +[build-system] +requires = ["hatchling"] +build-backend = "hatchling.build" + +[project] +name = "schema-wrapper" +version = "0.1.0" +description = "Schema wrapper classes for Mosaic" +readme = "README.md" +requires-python = ">=3.9" +dependencies = [ + "pyyaml", +] + +# Add development dependencies +[project.optional-dependencies] +dev = [ + "pytest>=7.0", + "pytest-cov>=4.0", +] + +[tool.hatch.envs.default] +python = "3.11" +features = ["dev"] +installer = "uv" + +[tool.hatch.envs.test] +installer = "uv" +dependencies = [ + "coverage[toml]", + "pytest", + "pytest-cov", +] + +[tool.hatch.envs.test.scripts] +cov = "pytest --cov-report=term-missing --cov-config=pyproject.toml --cov=." + +[tool.hatch.build.targets.wheel] +packages = ["."] + +[tool.pytest.ini_options] +testpaths = ["test"] +python_files = ["test_*.py"] +addopts = "-v" + +[tool.coverage.run] +source = ["."] + +[tool.coverage.report] +exclude_lines = [ + "pragma: no cover", + "def __repr__", + "if __name__ == .__main__.:", + "raise NotImplementedError", +] + +[tool.ruff] +line-length = 88 +target-version = "py39" \ No newline at end of file diff --git a/packages/schema_wrapper/src/__init__.py b/packages/schema_wrapper/src/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/packages/schema_wrapper/src/__pycache__/generated_classes.cpython-312.pyc b/packages/schema_wrapper/src/__pycache__/generated_classes.cpython-312.pyc new file mode 100644 index 00000000..91f52dc6 Binary files /dev/null and b/packages/schema_wrapper/src/__pycache__/generated_classes.cpython-312.pyc differ diff --git a/packages/schema_wrapper/src/__pycache__/utils.cpython-312.pyc b/packages/schema_wrapper/src/__pycache__/utils.cpython-312.pyc new file mode 100644 index 00000000..792f0569 Binary files /dev/null and b/packages/schema_wrapper/src/__pycache__/utils.cpython-312.pyc differ diff --git a/packages/schema_wrapper/src/generate_schema_wrapper.py b/packages/schema_wrapper/src/generate_schema_wrapper.py new file mode 100644 index 00000000..a8fc206a --- /dev/null +++ b/packages/schema_wrapper/src/generate_schema_wrapper.py @@ -0,0 +1,200 @@ +import json +from typing import Any, Dict, List, Final +import sys +import argparse +from pathlib import Path +from urllib import request +import graphlib +from .utils import get_valid_identifier, get_dependencies + +sys.path.insert(0, str(Path.cwd())) + +SCHEMA_VERSION: Final = "v0.10.0" +SCHEMA_URL_TEMPLATE: Final = "https://raw.githubusercontent.com/uwdata/mosaic/refs/heads/main/docs/public/schema/{version}.json" +KNOWN_PRIMITIVES = {"string": "str", "boolean": "bool", "number": "float", "object": "Dict[str, Any]"} + +def schema_url(version: str = SCHEMA_VERSION) -> str: + return SCHEMA_URL_TEMPLATE.format(version=version) + +def download_schemafile( + version: str, schemapath: Path, download: bool = False +) -> Path: + url = schema_url(version=version) + if download: + request.urlretrieve(url, schemapath) + elif not schemapath.exists(): + msg = f"Cannot skip download: {schemapath!s} does not exist" + raise ValueError(msg) + return schemapath + +def generate_class(class_name: str, class_schema: Dict[str, Any]) -> str: + class_name = get_valid_identifier(class_name) + + # Check if the schema defines a simple type (like string, number) without properties + if 'type' in class_schema and 'properties' not in class_schema: + return f"class {class_name}:\n def __init__(self):\n pass\n" + + # Check for '$ref' and handle it + if '$ref' in class_schema: + ref_class_name = class_schema['$ref'].split('/')[-1] + return f"\nclass {class_name}:\n pass # This is a reference to '{ref_class_name}'\n" + if 'anyOf' in class_schema: + return generate_any_of_class(class_name, class_schema['anyOf']) + + # Extract properties and required fields + properties = class_schema.get('properties', {}) + required = class_schema.get('required', []) + + class_def = f"class {class_name}:\n" + class_def += " def __init__(self" + + # Generate __init__ method parameters + optional_params = [] + + # Ensuring all the property names are valid Python identifiers + valid_properties = {} + for prop, prop_schema in properties.items(): + valid_prop = get_valid_identifier(prop) + valid_properties[valid_prop] = prop_schema + + for prop, prop_schema in valid_properties.items(): + if 'anyOf' in prop_schema: + # Handle anyOf case + type_hint = f"Union[{', '.join(get_type_hint(item) for item in prop_schema['anyOf'])}]" + else: + type_hint = get_type_hint(prop_schema) + + if prop in required: + # Required parameters should not have default values + class_def += f", {prop}: {type_hint}" + else: + # Ensure we add optional parameters last + optional_params.append((prop, type_hint)) + + for prop, type_hint in optional_params: + class_def += f", {prop}: {type_hint} = None" + + class_def += "):\n" + + # Generate attribute assignments in __init__ + for prop in valid_properties: + class_def += f" self.{prop} = {prop}\n" + + return class_def + +def get_type_union(types: List[str]): + unique_types = list(set(types)) + if len(unique_types) == 1: + return unique_types[0] + + # Moving the potential "Any" to the end of the list + if "Any" in unique_types: + unique_types.remove("Any") + unique_types.append("Any") + return f'Union[{", ".join(unique_types)}]' + +def generate_any_of_class(class_name: str, any_of_schemas: List[Dict[str, Any]]) -> str: + types = [get_type_hint(schema) for schema in any_of_schemas] + type_union = get_type_union(types) + + class_def = f"class {class_name}:\n" + class_def += f" def __init__(self, value: {type_union}):\n" + class_def += " self.value = value\n" + + return class_def + +def get_type_hint(type_schema: Dict[str, Any]) -> str: + """Get type hint for a property schema.""" + if 'items' in type_schema: + assert type_schema['type'] == 'array' + + items_schema = type_schema['items'] + # items_schema contains the types which are stored in the list + + datatype = get_type_hint(items_schema) + return f"List[{datatype}]" + + if 'type' in type_schema: + if isinstance(type_schema['type'], list): + types = [] + for t in type_schema['type']: + datatype = KNOWN_PRIMITIVES.get(t) + if datatype == None: + types.append('Any') + else: + types.append(datatype) + + return get_type_union(types) + else: + datatype = KNOWN_PRIMITIVES.get(type_schema['type']) + if datatype == None: + return 'Any' + return datatype + elif 'anyOf' in type_schema: + types = [get_type_hint(option) for option in type_schema['anyOf']] + return get_type_union(types) + elif '$ref' in type_schema: + ref_class_name = type_schema['$ref'].split('/')[-1] + return f'"{ref_class_name}"' + return 'Any' + +def load_schema(schema_path: Path) -> dict: + """Load a JSON schema from the specified path.""" + with schema_path.open(encoding="utf8") as f: + return json.load(f) + +def generate_schema_wrapper(schema_file: Path, output_file: Path) -> str: + """Generate a schema wrapper for the given schema file.""" + rootschema = load_schema(schema_file) + + rootschema_definitions = rootschema.get("definitions", {}) + ts = graphlib.TopologicalSorter() + + for name, schema in rootschema_definitions.items(): + dependencies = get_dependencies(schema) + if dependencies: + ts.add(name, *dependencies) + else: + ts.add(name) + + class_order = list(ts.static_order()) + + definitions: Dict[str, str] = {} + + for name in class_order: + schema = rootschema_definitions.get(name) + class_code = generate_class(name, schema) + definitions[name] = class_code + + generated_classes = "\n\n".join(definitions.values()) + generated_classes = "from typing import List, Dict, Any, Union\n\n" + generated_classes + + + with open(output_file, 'w') as f: + f.write(generated_classes) + +def main(): + parser = argparse.ArgumentParser( + prog="our_schema_generator", description="Generate the JSON schema for mosaic apps" + ) + parser.add_argument("schema_file", help="Path to the JSON schema file") + + parser.add_argument( + "--download", action="store_true", help="download the schema" + ) + args = parser.parse_args() + + #vn = '.'.join(version.split(".")[:1]) #Not using this currently + schemapath = Path(args.schema_file).resolve() + schemapath = download_schemafile( + version=SCHEMA_VERSION, + schemapath=schemapath, + download = args.download + ) + + output_file = Path("packages/schema_wrapper/generated_classes.py") + generate_schema_wrapper(schemapath, output_file) + +# Main execution +if __name__ == "__main__": + main() diff --git a/packages/schema_wrapper/src/utils.py b/packages/schema_wrapper/src/utils.py new file mode 100644 index 00000000..b18dad78 --- /dev/null +++ b/packages/schema_wrapper/src/utils.py @@ -0,0 +1,133 @@ +"""Utilities for working with schemas.""" + +from __future__ import annotations + +import keyword +import re +import urllib +from typing import ( + TYPE_CHECKING, + Final +) + +if TYPE_CHECKING: + from pathlib import Path + from typing_extensions import LiteralString + + from mistune import BlockState + +EXCLUDE_KEYS: Final = ("definitions", "title", "description", "$schema", "id") + +jsonschema_to_python_types = { + "string": "str", + "number": "float", + "integer": "int", + "object": "Map", + "boolean": "bool", + "array": "list", + "null": "None", +} + + +def get_valid_identifier( + prop: str, + replacement_character: str = "", + allow_unicode: bool = False, + url_decode: bool = True, +) -> str: + """ + Given a string property, generate a valid Python identifier. + + Parameters + ---------- + prop: string + Name of property to decode. + replacement_character: string, default '' + The character to replace invalid characters with. + allow_unicode: boolean, default False + If True, then allow Python 3-style unicode identifiers. + url_decode: boolean, default True + If True, decode URL characters in identifier names. + + Examples + -------- + >>> get_valid_identifier("my-var") + 'myvar' + + >>> get_valid_identifier("if") + 'if_' + + >>> get_valid_identifier("$schema", "_") + '_schema' + + >>> get_valid_identifier("$*#$") + '_' + + >>> get_valid_identifier("Name%3Cstring%3E") + 'Namestring' + """ + # Decode URL characters. + if url_decode: + prop = urllib.parse.unquote(prop) + + # Deal with [] + prop = prop.replace("[]", "Array") + + # First substitute-out all non-valid characters. + flags = re.UNICODE if allow_unicode else re.ASCII + valid = re.sub(r"\W", replacement_character, prop, flags=flags) + + # If nothing is left, use just an underscore + if not valid: + valid = "_" + + # first character must be a non-digit. Prefix with an underscore + # if needed + if re.match(r"^[\d\W]", valid): + valid = "_" + valid + + # if the result is a reserved keyword, then add an underscore at the end + if keyword.iskeyword(valid): + valid += "_" + return valid + +def revert_validation(field): + return field.strip('_') + +def get_key_by_value(dictionary, target_value): + for key, value in dictionary.items(): + if value == target_value: + return key + +def get_dependencies(data) -> List[str]: + dependencies = [] + + if isinstance(data, dict): + if "$ref" in data: + refVal = data["$ref"] + dependencies.append(refVal.split('/')[-1]) + + for key, value in data.items(): + if key != "anyOf": + dependencies = dependencies + get_dependencies(value) + elif isinstance(data, list): + for item in data: + dependencies = dependencies + get_dependencies(item) + + return dependencies + +def to_dict(cur_object): + if isinstance(cur_object, dict): + return {revert_validation(k): to_dict(v) for k, v in cur_object.items() if v is not None} + elif isinstance(cur_object, list): + return [to_dict(i) for i in cur_object if i is not None] + elif hasattr(cur_object, '__dict__'): + obj_asdict = cur_object.__dict__ + if len(obj_asdict.keys()) == 1: + return to_dict(list(obj_asdict.values())[0]) + else: + return {revert_validation(k): to_dict(v) for k, v in obj_asdict.items() if v is not None} + elif isinstance(cur_object, (str, int, float, bool)): + return cur_object + elif cur_object != None: + return str(cur_object) diff --git a/packages/schema_wrapper/test/__init__.py b/packages/schema_wrapper/test/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/packages/schema_wrapper/test/test_generated_classes.py b/packages/schema_wrapper/test/test_generated_classes.py new file mode 100644 index 00000000..df24be54 --- /dev/null +++ b/packages/schema_wrapper/test/test_generated_classes.py @@ -0,0 +1,169 @@ +""" +pytest packages/schema_wrapper/test/test.py +""" +import unittest +from pathlib import Path +import pytest +from ..src.utils import to_dict + +from ..generated_classes import * + +@pytest.fixture +def sample_data(): + return { + "csv_data": { + "file": "data.csv", + "type": "csv", + "delimiter": ",", + "temp": True + }, + "spatial_data": { + "file": "map.geojson", + "type": "geojson", + "layer": "features" + }, + "table_data": { + "query": "SELECT * FROM table", + "type": "table" + } + } + +def test_aggregate_expression(): + agg_expr = AggregateExpression("sum", "total") + assert agg_expr.agg == "sum" + assert agg_expr.label == "total" + +def test_aggregate_transform(): + # Test with string value + avg = Avg(avg="value") + agg_transform = AggregateTransform(avg) + assert isinstance(agg_transform.value, Avg) + assert agg_transform.value.avg == "value" + + # Test with numeric value + agg_transform = AggregateTransform(Avg(avg=2)) + assert agg_transform.value.avg == 2 + + # Test with boolean value + agg_transform = AggregateTransform(Avg(avg=True)) + assert agg_transform.value.avg == True + +def test_data_classes(sample_data): + # Test CSV data + csv_data = DataCSV(**sample_data["csv_data"]) + assert csv_data.file == "data.csv" + assert csv_data.type == "csv" + assert csv_data.delimiter == "," + assert csv_data.temp == True + + # Test Spatial data + spatial_data = DataSpatial(**sample_data["spatial_data"]) + assert spatial_data.file == "map.geojson" + assert spatial_data.type == "geojson" + assert spatial_data.layer == "features" + + # Test Table data + table_data = DataTable(**sample_data["table_data"]) + assert table_data.query == "SELECT * FROM table" + assert table_data.type == "table" + +def test_plot_components(): + # Test Plot class + plot = Plot( + "scatter", + width=500, + height=300, + xLabel="X Axis", + yLabel="Y Axis" + ) + assert plot.plot == "scatter" + assert plot.width == 500 + assert plot.height == 300 + assert plot.xLabel == "X Axis" + assert plot.yLabel == "Y Axis" + + # Test BrushStyles + styles = BrushStyles( + fill="red", + fillOpacity=0.5, + opacity=0.7, + stroke="black", + strokeOpacity=0.3 + ) + assert styles.fill == "red" + assert styles.fillOpacity == 0.5 + assert styles.opacity == 0.7 + assert styles.stroke == "black" + assert styles.strokeOpacity == 0.3 + print(to_dict(styles)) + +def test_argmin_argmax(): + # Test Argmin + argmin = Argmin([1.0, 2.0], distinct=True, orderby="date") + assert argmin.argmin == [1.0, 2.0] + assert argmin.distinct == True + assert argmin.orderby == "date" + assert isinstance(argmin.argmin, list) + assert all(isinstance(item, (float, bool, str)) for item in argmin.argmin) + + # Test Argmax + argmax = Argmax("value", distinct=True, orderby="date") + assert argmax.argmax == "value" + assert argmax.distinct == True + assert argmax.orderby == "date" + +def test_composite(): + argmax = Argmax([5, 6, True, 0.5], False, TransformField("test"), [TransformField("1"), TransformField("2"), TransformField("3")], ParamRef()) + print(to_dict(argmax)) + +def test_weather_plot(): + plot_spec = Plot( + + plot = [PlotMark(Dot(mark="dot", data=PlotFrom(from_="weather", filterBy="$click"), x=ChannelValueSpec(ChannelValue({"dateMonthDay": "date"})), y=ChannelValueSpec(ChannelValue("temp_max")), fill="weather", r="precipitation"))], + xyDomain = "Fixed", + xTickFormat = "%b", + colorDomain = "$domain", + colorRange = "$colors", + rDomain = "Fixed", + rRange = [2, 10], + width = 800 + ) + assert({'colorDomain': '$domain', + 'colorRange': '$colors', + 'plot': [ + {'data': {'filterBy': '$click', 'from': 'weather'}, + 'fill': 'weather', + 'mark': 'dot', + 'r': 'precipitation', + 'x': {'dateMonthDay': 'date'}, + 'y': 'temp_max'} + ], + 'rDomain': 'Fixed', + 'rRange': [2, 10], + 'width': 800, + 'xTickFormat': '%b', + 'xyDomain': 'Fixed'} == to_dict(plot_spec)) + +def test_stock_plot(): + plot_spec = Plot( + plot = [PlotMark(LineY( + mark="lineY", + data=PlotFrom(from_="aapl"), + x=ChannelValueSpec(ChannelValue("Date")), + y=ChannelValueSpec(ChannelValue("Close")) + ))], + width = 680, + height = 200 + ) + assert({'height': 200, + 'plot': [ + {'data': {'from': 'aapl'}, + 'mark': 'lineY', + 'x': 'Date', + 'y': 'Close'} + ], + 'width': 680} == to_dict(plot_spec)) + +if __name__ == '__main__': + pytest.main([__file__]) + diff --git a/packages/schema_wrapper/test/widget_plot.ipynb b/packages/schema_wrapper/test/widget_plot.ipynb new file mode 100644 index 00000000..64c216df --- /dev/null +++ b/packages/schema_wrapper/test/widget_plot.ipynb @@ -0,0 +1,1863 @@ +{ + "nbformat": 4, + "nbformat_minor": 0, + "metadata": { + "colab": { + "provenance": [] + }, + "kernelspec": { + "name": "python3", + "display_name": "Python 3" + }, + "language_info": { + "name": "python" + }, + "widgets": { + "application/vnd.jupyter.widget-state+json": { + "eb92c981b51c4bc29cca78b2cd5a3f50": { + "model_module": "anywidget", + "model_name": "AnyModel", + "model_module_version": "~0.9.*", + "state": { + "_anywidget_id": "mosaic_widget.MosaicWidget", + "_css": "/* src/style.css */\n.mosaic-widget .input {\n margin-right: 1em;\n}\n.mosaic-widget .input > * {\n vertical-align: middle;\n}\n.mosaic-widget table {\n position: relative;\n table-layout: fixed;\n border-collapse: separate;\n border-spacing: 0;\n font-variant-numeric: tabular-nums;\n box-sizing: border-box;\n max-width: initial;\n min-height: 33px;\n margin: 0;\n width: 100%;\n font-size: 13px;\n line-height: 15.6px;\n}\n.mosaic-widget thead tr th {\n position: sticky;\n top: 0;\n background: #fff;\n cursor: ns-resize;\n border-bottom: solid 1px #ccc;\n}\n.mosaic-widget tbody tr:hover {\n background: #eef;\n}\n.mosaic-widget th {\n color: #111;\n text-align: left;\n vertical-align: bottom;\n}\n.mosaic-widget td,\nth {\n white-space: nowrap;\n text-overflow: ellipsis;\n overflow: hidden;\n padding: 3px 6.5px 3px 0;\n}\n.mosaic-widget tbody tr:first-child td {\n padding-top: 4px;\n}\n.mosaic-widget td,\ntr:not(:last-child) th {\n border-bottom: solid 1px #eee;\n}\n.mosaic-widget td {\n color: #444;\n vertical-align: top;\n}\n", + "_dom_classes": [], + "_esm": "var __create = Object.create;\nvar __defProp = Object.defineProperty;\nvar __getOwnPropDesc = Object.getOwnPropertyDescriptor;\nvar __getOwnPropNames = Object.getOwnPropertyNames;\nvar __getProtoOf = Object.getPrototypeOf;\nvar __hasOwnProp = Object.prototype.hasOwnProperty;\nvar __commonJS = (cb, mod) => function __require() {\n return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;\n};\nvar __export = (target, all2) => {\n for (var name2 in all2)\n __defProp(target, name2, { get: all2[name2], enumerable: true });\n};\nvar __copyProps = (to, from2, except, desc2) => {\n if (from2 && typeof from2 === \"object\" || typeof from2 === \"function\") {\n for (let key of __getOwnPropNames(from2))\n if (!__hasOwnProp.call(to, key) && key !== except)\n __defProp(to, key, { get: () => from2[key], enumerable: !(desc2 = __getOwnPropDesc(from2, key)) || desc2.enumerable });\n }\n return to;\n};\nvar __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(\n // If the importer is in node compatibility mode or this is not an ESM\n // file that has been converted to a CommonJS file using a Babel-\n // compatible transform (i.e. \"__esModule\" has not been set), then set\n // \"default\" to the CommonJS \"module.exports\" for node compatibility.\n isNodeMode || !mod || !mod.__esModule ? __defProp(target, \"default\", { value: mod, enumerable: true }) : target,\n mod\n));\n\n// ../../node_modules/binary-search-bounds/search-bounds.js\nvar require_search_bounds = __commonJS({\n \"../../node_modules/binary-search-bounds/search-bounds.js\"(exports, module) {\n \"use strict\";\n function ge(a2, y3, c4, l, h) {\n var i = h + 1;\n while (l <= h) {\n var m = l + h >>> 1, x3 = a2[m];\n var p = c4 !== void 0 ? c4(x3, y3) : x3 - y3;\n if (p >= 0) {\n i = m;\n h = m - 1;\n } else {\n l = m + 1;\n }\n }\n return i;\n }\n function gt2(a2, y3, c4, l, h) {\n var i = h + 1;\n while (l <= h) {\n var m = l + h >>> 1, x3 = a2[m];\n var p = c4 !== void 0 ? c4(x3, y3) : x3 - y3;\n if (p > 0) {\n i = m;\n h = m - 1;\n } else {\n l = m + 1;\n }\n }\n return i;\n }\n function lt2(a2, y3, c4, l, h) {\n var i = l - 1;\n while (l <= h) {\n var m = l + h >>> 1, x3 = a2[m];\n var p = c4 !== void 0 ? c4(x3, y3) : x3 - y3;\n if (p < 0) {\n i = m;\n l = m + 1;\n } else {\n h = m - 1;\n }\n }\n return i;\n }\n function le(a2, y3, c4, l, h) {\n var i = l - 1;\n while (l <= h) {\n var m = l + h >>> 1, x3 = a2[m];\n var p = c4 !== void 0 ? c4(x3, y3) : x3 - y3;\n if (p <= 0) {\n i = m;\n l = m + 1;\n } else {\n h = m - 1;\n }\n }\n return i;\n }\n function eq2(a2, y3, c4, l, h) {\n while (l <= h) {\n var m = l + h >>> 1, x3 = a2[m];\n var p = c4 !== void 0 ? c4(x3, y3) : x3 - y3;\n if (p === 0) {\n return m;\n }\n if (p <= 0) {\n l = m + 1;\n } else {\n h = m - 1;\n }\n }\n return -1;\n }\n function norm(a2, y3, c4, l, h, f) {\n if (typeof c4 === \"function\") {\n return f(a2, y3, c4, l === void 0 ? 0 : l | 0, h === void 0 ? a2.length - 1 : h | 0);\n }\n return f(a2, y3, void 0, c4 === void 0 ? 0 : c4 | 0, l === void 0 ? a2.length - 1 : l | 0);\n }\n module.exports = {\n ge: function(a2, y3, c4, l, h) {\n return norm(a2, y3, c4, l, h, ge);\n },\n gt: function(a2, y3, c4, l, h) {\n return norm(a2, y3, c4, l, h, gt2);\n },\n lt: function(a2, y3, c4, l, h) {\n return norm(a2, y3, c4, l, h, lt2);\n },\n le: function(a2, y3, c4, l, h) {\n return norm(a2, y3, c4, l, h, le);\n },\n eq: function(a2, y3, c4, l, h) {\n return norm(a2, y3, c4, l, h, eq2);\n }\n };\n }\n});\n\n// ../../node_modules/interval-tree-1d/interval-tree.js\nvar require_interval_tree = __commonJS({\n \"../../node_modules/interval-tree-1d/interval-tree.js\"(exports, module) {\n \"use strict\";\n var bounds = require_search_bounds();\n var NOT_FOUND = 0;\n var SUCCESS = 1;\n var EMPTY = 2;\n module.exports = createWrapper;\n function IntervalTreeNode(mid2, left2, right2, leftPoints, rightPoints) {\n this.mid = mid2;\n this.left = left2;\n this.right = right2;\n this.leftPoints = leftPoints;\n this.rightPoints = rightPoints;\n this.count = (left2 ? left2.count : 0) + (right2 ? right2.count : 0) + leftPoints.length;\n }\n var proto = IntervalTreeNode.prototype;\n function copy4(a2, b) {\n a2.mid = b.mid;\n a2.left = b.left;\n a2.right = b.right;\n a2.leftPoints = b.leftPoints;\n a2.rightPoints = b.rightPoints;\n a2.count = b.count;\n }\n function rebuild(node, intervals2) {\n var ntree = createIntervalTree(intervals2);\n node.mid = ntree.mid;\n node.left = ntree.left;\n node.right = ntree.right;\n node.leftPoints = ntree.leftPoints;\n node.rightPoints = ntree.rightPoints;\n node.count = ntree.count;\n }\n function rebuildWithInterval(node, interval3) {\n var intervals2 = node.intervals([]);\n intervals2.push(interval3);\n rebuild(node, intervals2);\n }\n function rebuildWithoutInterval(node, interval3) {\n var intervals2 = node.intervals([]);\n var idx = intervals2.indexOf(interval3);\n if (idx < 0) {\n return NOT_FOUND;\n }\n intervals2.splice(idx, 1);\n rebuild(node, intervals2);\n return SUCCESS;\n }\n proto.intervals = function(result) {\n result.push.apply(result, this.leftPoints);\n if (this.left) {\n this.left.intervals(result);\n }\n if (this.right) {\n this.right.intervals(result);\n }\n return result;\n };\n proto.insert = function(interval3) {\n var weight = this.count - this.leftPoints.length;\n this.count += 1;\n if (interval3[1] < this.mid) {\n if (this.left) {\n if (4 * (this.left.count + 1) > 3 * (weight + 1)) {\n rebuildWithInterval(this, interval3);\n } else {\n this.left.insert(interval3);\n }\n } else {\n this.left = createIntervalTree([interval3]);\n }\n } else if (interval3[0] > this.mid) {\n if (this.right) {\n if (4 * (this.right.count + 1) > 3 * (weight + 1)) {\n rebuildWithInterval(this, interval3);\n } else {\n this.right.insert(interval3);\n }\n } else {\n this.right = createIntervalTree([interval3]);\n }\n } else {\n var l = bounds.ge(this.leftPoints, interval3, compareBegin);\n var r = bounds.ge(this.rightPoints, interval3, compareEnd);\n this.leftPoints.splice(l, 0, interval3);\n this.rightPoints.splice(r, 0, interval3);\n }\n };\n proto.remove = function(interval3) {\n var weight = this.count - this.leftPoints;\n if (interval3[1] < this.mid) {\n if (!this.left) {\n return NOT_FOUND;\n }\n var rw = this.right ? this.right.count : 0;\n if (4 * rw > 3 * (weight - 1)) {\n return rebuildWithoutInterval(this, interval3);\n }\n var r = this.left.remove(interval3);\n if (r === EMPTY) {\n this.left = null;\n this.count -= 1;\n return SUCCESS;\n } else if (r === SUCCESS) {\n this.count -= 1;\n }\n return r;\n } else if (interval3[0] > this.mid) {\n if (!this.right) {\n return NOT_FOUND;\n }\n var lw = this.left ? this.left.count : 0;\n if (4 * lw > 3 * (weight - 1)) {\n return rebuildWithoutInterval(this, interval3);\n }\n var r = this.right.remove(interval3);\n if (r === EMPTY) {\n this.right = null;\n this.count -= 1;\n return SUCCESS;\n } else if (r === SUCCESS) {\n this.count -= 1;\n }\n return r;\n } else {\n if (this.count === 1) {\n if (this.leftPoints[0] === interval3) {\n return EMPTY;\n } else {\n return NOT_FOUND;\n }\n }\n if (this.leftPoints.length === 1 && this.leftPoints[0] === interval3) {\n if (this.left && this.right) {\n var p = this;\n var n = this.left;\n while (n.right) {\n p = n;\n n = n.right;\n }\n if (p === this) {\n n.right = this.right;\n } else {\n var l = this.left;\n var r = this.right;\n p.count -= n.count;\n p.right = n.left;\n n.left = l;\n n.right = r;\n }\n copy4(this, n);\n this.count = (this.left ? this.left.count : 0) + (this.right ? this.right.count : 0) + this.leftPoints.length;\n } else if (this.left) {\n copy4(this, this.left);\n } else {\n copy4(this, this.right);\n }\n return SUCCESS;\n }\n for (var l = bounds.ge(this.leftPoints, interval3, compareBegin); l < this.leftPoints.length; ++l) {\n if (this.leftPoints[l][0] !== interval3[0]) {\n break;\n }\n if (this.leftPoints[l] === interval3) {\n this.count -= 1;\n this.leftPoints.splice(l, 1);\n for (var r = bounds.ge(this.rightPoints, interval3, compareEnd); r < this.rightPoints.length; ++r) {\n if (this.rightPoints[r][1] !== interval3[1]) {\n break;\n } else if (this.rightPoints[r] === interval3) {\n this.rightPoints.splice(r, 1);\n return SUCCESS;\n }\n }\n }\n }\n return NOT_FOUND;\n }\n };\n function reportLeftRange(arr, hi, cb) {\n for (var i = 0; i < arr.length && arr[i][0] <= hi; ++i) {\n var r = cb(arr[i]);\n if (r) {\n return r;\n }\n }\n }\n function reportRightRange(arr, lo, cb) {\n for (var i = arr.length - 1; i >= 0 && arr[i][1] >= lo; --i) {\n var r = cb(arr[i]);\n if (r) {\n return r;\n }\n }\n }\n function reportRange(arr, cb) {\n for (var i = 0; i < arr.length; ++i) {\n var r = cb(arr[i]);\n if (r) {\n return r;\n }\n }\n }\n proto.queryPoint = function(x3, cb) {\n if (x3 < this.mid) {\n if (this.left) {\n var r = this.left.queryPoint(x3, cb);\n if (r) {\n return r;\n }\n }\n return reportLeftRange(this.leftPoints, x3, cb);\n } else if (x3 > this.mid) {\n if (this.right) {\n var r = this.right.queryPoint(x3, cb);\n if (r) {\n return r;\n }\n }\n return reportRightRange(this.rightPoints, x3, cb);\n } else {\n return reportRange(this.leftPoints, cb);\n }\n };\n proto.queryInterval = function(lo, hi, cb) {\n if (lo < this.mid && this.left) {\n var r = this.left.queryInterval(lo, hi, cb);\n if (r) {\n return r;\n }\n }\n if (hi > this.mid && this.right) {\n var r = this.right.queryInterval(lo, hi, cb);\n if (r) {\n return r;\n }\n }\n if (hi < this.mid) {\n return reportLeftRange(this.leftPoints, hi, cb);\n } else if (lo > this.mid) {\n return reportRightRange(this.rightPoints, lo, cb);\n } else {\n return reportRange(this.leftPoints, cb);\n }\n };\n function compareNumbers(a2, b) {\n return a2 - b;\n }\n function compareBegin(a2, b) {\n var d = a2[0] - b[0];\n if (d) {\n return d;\n }\n return a2[1] - b[1];\n }\n function compareEnd(a2, b) {\n var d = a2[1] - b[1];\n if (d) {\n return d;\n }\n return a2[0] - b[0];\n }\n function createIntervalTree(intervals2) {\n if (intervals2.length === 0) {\n return null;\n }\n var pts = [];\n for (var i = 0; i < intervals2.length; ++i) {\n pts.push(intervals2[i][0], intervals2[i][1]);\n }\n pts.sort(compareNumbers);\n var mid2 = pts[pts.length >> 1];\n var leftIntervals = [];\n var rightIntervals = [];\n var centerIntervals = [];\n for (var i = 0; i < intervals2.length; ++i) {\n var s2 = intervals2[i];\n if (s2[1] < mid2) {\n leftIntervals.push(s2);\n } else if (mid2 < s2[0]) {\n rightIntervals.push(s2);\n } else {\n centerIntervals.push(s2);\n }\n }\n var leftPoints = centerIntervals;\n var rightPoints = centerIntervals.slice();\n leftPoints.sort(compareBegin);\n rightPoints.sort(compareEnd);\n return new IntervalTreeNode(\n mid2,\n createIntervalTree(leftIntervals),\n createIntervalTree(rightIntervals),\n leftPoints,\n rightPoints\n );\n }\n function IntervalTree2(root2) {\n this.root = root2;\n }\n var tproto = IntervalTree2.prototype;\n tproto.insert = function(interval3) {\n if (this.root) {\n this.root.insert(interval3);\n } else {\n this.root = new IntervalTreeNode(interval3[0], null, null, [interval3], [interval3]);\n }\n };\n tproto.remove = function(interval3) {\n if (this.root) {\n var r = this.root.remove(interval3);\n if (r === EMPTY) {\n this.root = null;\n }\n return r !== NOT_FOUND;\n }\n return false;\n };\n tproto.queryPoint = function(p, cb) {\n if (this.root) {\n return this.root.queryPoint(p, cb);\n }\n };\n tproto.queryInterval = function(lo, hi, cb) {\n if (lo <= hi && this.root) {\n return this.root.queryInterval(lo, hi, cb);\n }\n };\n Object.defineProperty(tproto, \"count\", {\n get: function() {\n if (this.root) {\n return this.root.count;\n }\n return 0;\n }\n });\n Object.defineProperty(tproto, \"intervals\", {\n get: function() {\n if (this.root) {\n return this.root.intervals([]);\n }\n return [];\n }\n });\n function createWrapper(intervals2) {\n if (!intervals2 || intervals2.length === 0) {\n return new IntervalTree2(null);\n }\n return new IntervalTree2(createIntervalTree(intervals2));\n }\n }\n});\n\n// ../core/src/util/throttle.js\nvar NIL = {};\nfunction throttle(callback, debounce = false) {\n let curr;\n let next;\n let pending = NIL;\n function invoke(event) {\n curr = callback(event).finally(() => {\n if (next) {\n const { value } = next;\n next = null;\n invoke(value);\n } else {\n curr = null;\n }\n });\n }\n function enqueue(event) {\n next = { event };\n }\n function process(event) {\n curr ? enqueue(event) : invoke(event);\n }\n function delay(event) {\n if (pending !== event) {\n requestAnimationFrame(() => {\n const e = pending;\n pending = NIL;\n process(e);\n });\n }\n pending = event;\n }\n return debounce ? delay : process;\n}\n\n// ../core/src/MosaicClient.js\nvar MosaicClient = class {\n /**\n * Constructor.\n * @param {*} filterSelection An optional selection to interactively filter\n * this client's data. If provided, a coordinator will re-query and update\n * the client when the selection updates.\n */\n constructor(filterSelection) {\n this._filterBy = filterSelection;\n this._requestUpdate = throttle(() => this.requestQuery(), true);\n this._coordinator = null;\n }\n /**\n * Return this client's connected coordinator.\n */\n get coordinator() {\n return this._coordinator;\n }\n /**\n * Set this client's connected coordinator.\n */\n set coordinator(coordinator2) {\n this._coordinator = coordinator2;\n }\n /**\n * Return this client's filter selection.\n */\n get filterBy() {\n return this._filterBy;\n }\n /**\n * Return a boolean indicating if the client query can be indexed. Should\n * return true if changes to the filterBy selection does not change the\n * groupby domain of the client query.\n */\n get filterIndexable() {\n return true;\n }\n /**\n * Return an array of fields queried by this client.\n * @returns {object[]|null} The fields to retrieve info for.\n */\n fields() {\n return null;\n }\n /**\n * Called by the coordinator to set the field info for this client.\n * @param {*} info The field info result.\n * @returns {this}\n */\n fieldInfo(info) {\n return this;\n }\n /**\n * Return a query specifying the data needed by this client.\n * @param {*} [filter] The filtering criteria to apply in the query.\n * @returns {*} The client query\n */\n query(filter3) {\n return null;\n }\n /**\n * Called by the coordinator to inform the client that a query is pending.\n * @returns {this}\n */\n queryPending() {\n return this;\n }\n /**\n * Called by the coordinator to return a query result.\n * @param {*} data The query result.\n * @returns {this}\n */\n queryResult(data) {\n return this;\n }\n /**\n * Called by the coordinator to report a query execution error.\n * @param {*} error\n * @returns {this}\n */\n queryError(error2) {\n return this;\n }\n /**\n * Request the coordinator to execute a query for this client.\n * If an explicit query is not provided, the client query method will\n * be called, filtered by the current filterBy selection.\n * @returns {Promise}\n */\n requestQuery(query) {\n const q = query || this.query(this.filterBy?.predicate(this));\n return this._coordinator.requestQuery(this, q);\n }\n /**\n * Request that the coordinator perform a throttled update of this client\n * using the default query. Unlike requestQuery, for which every call will\n * result in an executed query, multiple calls to requestUpdate may be\n * consolidated into a single update.\n */\n requestUpdate() {\n this._requestUpdate();\n }\n /**\n * Reset this client, initiating new field info and query requests.\n * @returns {Promise}\n */\n initialize() {\n return this._coordinator.initializeClient(this);\n }\n /**\n * Requests a client update.\n * For example to (re-)render an interface component.\n *\n * @returns {this | Promise}\n */\n update() {\n return this;\n }\n};\n\n// ../../node_modules/@uwdata/flechette/src/constants.js\nvar MAGIC = Uint8Array.of(65, 82, 82, 79, 87, 49);\nvar Version = (\n /** @type {const} */\n {\n /** 0.1.0 (October 2016). */\n V1: 0,\n /** 0.2.0 (February 2017). Non-backwards compatible with V1. */\n V2: 1,\n /** 0.3.0 -> 0.7.1 (May - December 2017). Non-backwards compatible with V2. */\n V3: 2,\n /** >= 0.8.0 (December 2017). Non-backwards compatible with V3. */\n V4: 3,\n /**\n * >= 1.0.0 (July 2020). Backwards compatible with V4 (V5 readers can read V4\n * metadata and IPC messages). Implementations are recommended to provide a\n * V4 compatibility mode with V5 format changes disabled.\n *\n * Incompatible changes between V4 and V5:\n * - Union buffer layout has changed.\n * In V5, Unions don't have a validity bitmap buffer.\n */\n V5: 4\n }\n);\nvar MessageHeader = (\n /** @type {const} */\n {\n NONE: 0,\n /**\n * A Schema describes the columns in a record batch.\n */\n Schema: 1,\n /**\n * For sending dictionary encoding information. Any Field can be\n * dictionary-encoded, but in this case none of its children may be\n * dictionary-encoded.\n * There is one vector / column per dictionary, but that vector / column\n * may be spread across multiple dictionary batches by using the isDelta\n * flag.\n */\n DictionaryBatch: 2,\n /**\n * A data header describing the shared memory layout of a \"record\" or \"row\"\n * batch. Some systems call this a \"row batch\" internally and others a \"record\n * batch\".\n */\n RecordBatch: 3,\n /**\n * EXPERIMENTAL: Metadata for n-dimensional arrays, aka \"tensors\" or\n * \"ndarrays\". Arrow implementations in general are not required to implement\n * this type.\n *\n * Not currently supported by Flechette.\n */\n Tensor: 4,\n /**\n * EXPERIMENTAL: Metadata for n-dimensional sparse arrays, aka \"sparse\n * tensors\". Arrow implementations in general are not required to implement\n * this type.\n *\n * Not currently supported by Flechette.\n */\n SparseTensor: 5\n }\n);\nvar Type = (\n /** @type {const} */\n {\n /**\n * Dictionary types compress data by using a set of integer indices to\n * lookup potentially repeated vales in a separate dictionary of values.\n *\n * This type entry is provided for API convenience, it does not occur\n * in actual Arrow IPC binary data.\n */\n Dictionary: -1,\n /** No data type. Included for flatbuffer compatibility. */\n NONE: 0,\n /** Null values only. */\n Null: 1,\n /** Integers, either signed or unsigned, with 8, 16, 32, or 64 bit widths. */\n Int: 2,\n /** Floating point numbers with 16, 32, or 64 bit precision. */\n Float: 3,\n /** Opaque binary data. */\n Binary: 4,\n /** Unicode with UTF-8 encoding. */\n Utf8: 5,\n /** Booleans represented as 8 bit bytes. */\n Bool: 6,\n /**\n * Exact decimal value represented as an integer value in two's complement.\n * Currently only 128-bit (16-byte) and 256-bit (32-byte) integers are used.\n * The representation uses the endianness indicated in the schema.\n */\n Decimal: 7,\n /**\n * Date is either a 32-bit or 64-bit signed integer type representing an\n * elapsed time since UNIX epoch (1970-01-01), stored in either of two units:\n * - Milliseconds (64 bits) indicating UNIX time elapsed since the epoch (no\n * leap seconds), where the values are evenly divisible by 86400000\n * - Days (32 bits) since the UNIX epoch\n */\n Date: 8,\n /**\n * Time is either a 32-bit or 64-bit signed integer type representing an\n * elapsed time since midnight, stored in either of four units: seconds,\n * milliseconds, microseconds or nanoseconds.\n *\n * The integer `bitWidth` depends on the `unit` and must be one of the following:\n * - SECOND and MILLISECOND: 32 bits\n * - MICROSECOND and NANOSECOND: 64 bits\n *\n * The allowed values are between 0 (inclusive) and 86400 (=24*60*60) seconds\n * (exclusive), adjusted for the time unit (for example, up to 86400000\n * exclusive for the MILLISECOND unit).\n * This definition doesn't allow for leap seconds. Time values from\n * measurements with leap seconds will need to be corrected when ingesting\n * into Arrow (for example by replacing the value 86400 with 86399).\n */\n Time: 9,\n /**\n * Timestamp is a 64-bit signed integer representing an elapsed time since a\n * fixed epoch, stored in either of four units: seconds, milliseconds,\n * microseconds or nanoseconds, and is optionally annotated with a timezone.\n *\n * Timestamp values do not include any leap seconds (in other words, all\n * days are considered 86400 seconds long).\n *\n * The timezone is an optional string for the name of a timezone, one of:\n *\n * - As used in the Olson timezone database (the \"tz database\" or\n * \"tzdata\"), such as \"America/New_York\".\n * - An absolute timezone offset of the form \"+XX:XX\" or \"-XX:XX\",\n * such as \"+07:30\".\n *\n * Whether a timezone string is present indicates different semantics about\n * the data.\n */\n Timestamp: 10,\n /**\n * A \"calendar\" interval which models types that don't necessarily\n * have a precise duration without the context of a base timestamp (e.g.\n * days can differ in length during day light savings time transitions).\n * All integers in the units below are stored in the endianness indicated\n * by the schema.\n *\n * - YEAR_MONTH - Indicates the number of elapsed whole months, stored as\n * 4-byte signed integers.\n * - DAY_TIME - Indicates the number of elapsed days and milliseconds (no\n * leap seconds), stored as 2 contiguous 32-bit signed integers (8-bytes\n * in total). Support of this IntervalUnit is not required for full arrow\n * compatibility.\n * - MONTH_DAY_NANO - A triple of the number of elapsed months, days, and\n * nanoseconds. The values are stored contiguously in 16-byte blocks.\n * Months and days are encoded as 32-bit signed integers and nanoseconds\n * is encoded as a 64-bit signed integer. Nanoseconds does not allow for\n * leap seconds. Each field is independent (e.g. there is no constraint\n * that nanoseconds have the same sign as days or that the quantity of\n * nanoseconds represents less than a day's worth of time).\n */\n Interval: 11,\n /**\n * List (vector) data supporting variably-sized lists.\n * A list has a single child data type for list entries.\n */\n List: 12,\n /**\n * A struct consisting of multiple named child data types.\n */\n Struct: 13,\n /**\n * A union is a complex type with parallel child data types. By default ids\n * in the type vector refer to the offsets in the children. Optionally\n * typeIds provides an indirection between the child offset and the type id.\n * For each child `typeIds[offset]` is the id used in the type vector.\n */\n Union: 14,\n /**\n * Binary data where each entry has the same fixed size.\n */\n FixedSizeBinary: 15,\n /**\n * List (vector) data where every list has the same fixed size.\n * A list has a single child data type for list entries.\n */\n FixedSizeList: 16,\n /**\n * A Map is a logical nested type that is represented as\n * List>\n *\n * In this layout, the keys and values are each respectively contiguous. We do\n * not constrain the key and value types, so the application is responsible\n * for ensuring that the keys are hashable and unique. Whether the keys are sorted\n * may be set in the metadata for this field.\n *\n * In a field with Map type, the field has a child Struct field, which then\n * has two children: key type and the second the value type. The names of the\n * child fields may be respectively \"entries\", \"key\", and \"value\", but this is\n * not enforced.\n *\n * Map\n * ```text\n * - child[0] entries: Struct\n * - child[0] key: K\n * - child[1] value: V\n * ```\n * Neither the \"entries\" field nor the \"key\" field may be nullable.\n *\n * The metadata is structured so that Arrow systems without special handling\n * for Map can make Map an alias for List. The \"layout\" attribute for the Map\n * field must have the same contents as a List.\n */\n Map: 17,\n /**\n * An absolute length of time unrelated to any calendar artifacts. For the\n * purposes of Arrow implementations, adding this value to a Timestamp\n * (\"t1\") naively (i.e. simply summing the two numbers) is acceptable even\n * though in some cases the resulting Timestamp (t2) would not account for\n * leap-seconds during the elapsed time between \"t1\" and \"t2\". Similarly,\n * representing the difference between two Unix timestamp is acceptable, but\n * would yield a value that is possibly a few seconds off from the true\n * elapsed time.\n *\n * The resolution defaults to millisecond, but can be any of the other\n * supported TimeUnit values as with Timestamp and Time types. This type is\n * always represented as an 8-byte integer.\n */\n Duration: 18,\n /**\n * Same as Binary, but with 64-bit offsets, allowing representation of\n * extremely large data values.\n */\n LargeBinary: 19,\n /**\n * Same as Utf8, but with 64-bit offsets, allowing representation of\n * extremely large data values.\n */\n LargeUtf8: 20,\n /**\n * Same as List, but with 64-bit offsets, allowing representation of\n * extremely large data values.\n */\n LargeList: 21,\n /**\n * Contains two child arrays, run_ends and values. The run_ends child array\n * must be a 16/32/64-bit integer array which encodes the indices at which\n * the run with the value in each corresponding index in the values child\n * array ends. Like list/struct types, the value array can be of any type.\n */\n RunEndEncoded: 22,\n /**\n * Logically the same as Binary, but the internal representation uses a view\n * struct that contains the string length and either the string's entire data\n * inline (for small strings) or an inlined prefix, an index of another buffer,\n * and an offset pointing to a slice in that buffer (for non-small strings).\n *\n * Since it uses a variable number of data buffers, each Field with this type\n * must have a corresponding entry in `variadicBufferCounts`.\n */\n BinaryView: 23,\n /**\n * Logically the same as Utf8, but the internal representation uses a view\n * struct that contains the string length and either the string's entire data\n * inline (for small strings) or an inlined prefix, an index of another buffer,\n * and an offset pointing to a slice in that buffer (for non-small strings).\n *\n * Since it uses a variable number of data buffers, each Field with this type\n * must have a corresponding entry in `variadicBufferCounts`.\n */\n Utf8View: 24,\n /**\n * Represents the same logical types that List can, but contains offsets and\n * sizes allowing for writes in any order and sharing of child values among\n * list values.\n */\n ListView: 25,\n /**\n * Same as ListView, but with 64-bit offsets and sizes, allowing to represent\n * extremely large data values.\n */\n LargeListView: 26\n }\n);\nvar Precision = (\n /** @type {const} */\n {\n /** 16-bit floating point number. */\n HALF: 0,\n /** 32-bit floating point number. */\n SINGLE: 1,\n /** 64-bit floating point number. */\n DOUBLE: 2\n }\n);\nvar DateUnit = (\n /** @type {const} */\n {\n /* Days (as 32 bit int) since the UNIX epoch. */\n DAY: 0,\n /**\n * Milliseconds (as 64 bit int) indicating UNIX time elapsed since the epoch\n * (no leap seconds), with values evenly divisible by 86400000.\n */\n MILLISECOND: 1\n }\n);\nvar TimeUnit = (\n /** @type {const} */\n {\n /** Seconds. */\n SECOND: 0,\n /** Milliseconds. */\n MILLISECOND: 1,\n /** Microseconds. */\n MICROSECOND: 2,\n /** Nanoseconds. */\n NANOSECOND: 3\n }\n);\nvar IntervalUnit = (\n /** @type {const} */\n {\n /**\n * Indicates the number of elapsed whole months, stored as 4-byte signed\n * integers.\n */\n YEAR_MONTH: 0,\n /**\n * Indicates the number of elapsed days and milliseconds (no leap seconds),\n * stored as 2 contiguous 32-bit signed integers (8-bytes in total). Support\n * of this IntervalUnit is not required for full arrow compatibility.\n */\n DAY_TIME: 1,\n /**\n * A triple of the number of elapsed months, days, and nanoseconds.\n * The values are stored contiguously in 16-byte blocks. Months and days are\n * encoded as 32-bit signed integers and nanoseconds is encoded as a 64-bit\n * signed integer. Nanoseconds does not allow for leap seconds. Each field is\n * independent (e.g. there is no constraint that nanoseconds have the same\n * sign as days or that the quantity of nanoseconds represents less than a\n * day's worth of time).\n */\n MONTH_DAY_NANO: 2\n }\n);\nvar UnionMode = (\n /** @type {const} */\n {\n /** Sparse union layout with full arrays for each sub-type. */\n Sparse: 0,\n /** Dense union layout with offsets into value arrays. */\n Dense: 1\n }\n);\n\n// ../../node_modules/@uwdata/flechette/src/util/arrays.js\nvar uint8Array = Uint8Array;\nvar uint16Array = Uint16Array;\nvar uint32Array = Uint32Array;\nvar uint64Array = BigUint64Array;\nvar int8Array = Int8Array;\nvar int16Array = Int16Array;\nvar int32Array = Int32Array;\nvar int64Array = BigInt64Array;\nvar float32Array = Float32Array;\nvar float64Array = Float64Array;\nfunction intArrayType(bitWidth, signed) {\n const i = Math.log2(bitWidth) - 3;\n return (signed ? [int8Array, int16Array, int32Array, int64Array] : [uint8Array, uint16Array, uint32Array, uint64Array])[i];\n}\nvar TypedArray = Object.getPrototypeOf(Int8Array);\nfunction bisect(offsets, index2) {\n let a2 = 0;\n let b = offsets.length;\n if (b <= 2147483648) {\n do {\n const mid2 = a2 + b >>> 1;\n if (offsets[mid2] <= index2) a2 = mid2 + 1;\n else b = mid2;\n } while (a2 < b);\n } else {\n do {\n const mid2 = Math.trunc((a2 + b) / 2);\n if (offsets[mid2] <= index2) a2 = mid2 + 1;\n else b = mid2;\n } while (a2 < b);\n }\n return a2;\n}\n\n// ../../node_modules/@uwdata/flechette/src/util/objects.js\nfunction check(value, test, message) {\n if (test(value)) return value;\n throw new Error(message(value));\n}\nfunction checkOneOf(value, set3, message) {\n set3 = Array.isArray(set3) ? set3 : Object.values(set3);\n return check(\n value,\n (value2) => set3.includes(value2),\n message ?? (() => `${value} must be one of ${set3}`)\n );\n}\nfunction keyFor(object, value) {\n for (const [key, val] of Object.entries(object)) {\n if (val === value) return key;\n }\n return \"\";\n}\n\n// ../../node_modules/@uwdata/flechette/src/data-types.js\nvar invalidDataType = (typeId) => `Unsupported data type: \"${keyFor(Type, typeId)}\" (id ${typeId})`;\nvar field = (name2, type2, nullable = true, metadata = null) => ({\n name: name2,\n type: type2,\n nullable,\n metadata\n});\nfunction isField(value) {\n return Object.hasOwn(value, \"name\") && isDataType(value.type);\n}\nfunction isDataType(value) {\n return typeof value?.typeId === \"number\";\n}\nfunction asField(value, defaultName = \"\", defaultNullable = true) {\n return isField(value) ? value : field(\n defaultName,\n check(value, isDataType, () => `Data type expected.`),\n defaultNullable\n );\n}\nvar dictionary = (type2, indexType, ordered = false, id2 = -1) => ({\n typeId: Type.Dictionary,\n id: id2,\n dictionary: type2,\n indices: indexType || int32(),\n ordered\n});\nvar int = (bitWidth = 32, signed = true) => ({\n typeId: Type.Int,\n bitWidth: checkOneOf(bitWidth, [8, 16, 32, 64]),\n signed,\n values: intArrayType(bitWidth, signed)\n});\nvar int32 = () => int(32);\nvar float = (precision = 2) => ({\n typeId: Type.Float,\n precision: checkOneOf(precision, Precision),\n values: [uint16Array, float32Array, float64Array][precision]\n});\nvar binary = () => ({\n typeId: Type.Binary,\n offsets: int32Array\n});\nvar utf8 = () => ({\n typeId: Type.Utf8,\n offsets: int32Array\n});\nvar decimal = (precision, scale3, bitWidth = 128) => ({\n typeId: Type.Decimal,\n precision,\n scale: scale3,\n bitWidth: checkOneOf(bitWidth, [128, 256]),\n values: uint64Array\n});\nvar date = (unit3) => ({\n typeId: Type.Date,\n unit: checkOneOf(unit3, DateUnit),\n values: unit3 === DateUnit.DAY ? int32Array : int64Array\n});\nvar time = (unit3 = TimeUnit.MILLISECOND, bitWidth = 32) => ({\n typeId: Type.Time,\n unit: checkOneOf(unit3, TimeUnit),\n bitWidth: checkOneOf(bitWidth, [32, 64]),\n values: bitWidth === 32 ? int32Array : int64Array\n});\nvar timestamp = (unit3 = TimeUnit.MILLISECOND, timezone = null) => ({\n typeId: Type.Timestamp,\n unit: checkOneOf(unit3, TimeUnit),\n timezone,\n values: int64Array\n});\nvar interval = (unit3 = IntervalUnit.MONTH_DAY_NANO) => ({\n typeId: Type.Interval,\n unit: checkOneOf(unit3, IntervalUnit),\n values: unit3 === IntervalUnit.MONTH_DAY_NANO ? void 0 : int32Array\n});\nvar list = (child) => ({\n typeId: Type.List,\n children: [asField(child)],\n offsets: int32Array\n});\nvar struct = (children2) => ({\n typeId: Type.Struct,\n children: Array.isArray(children2) && isField(children2[0]) ? (\n /** @type {import('./types.js').Field[]} */\n children2\n ) : Object.entries(children2).map(([name2, type2]) => field(name2, type2))\n});\nvar union = (mode3, children2, typeIds, typeIdForValue) => {\n typeIds ??= children2.map((v2, i) => i);\n return {\n typeId: Type.Union,\n mode: checkOneOf(mode3, UnionMode),\n typeIds,\n typeMap: typeIds.reduce((m, id2, i) => (m[id2] = i, m), {}),\n children: children2.map((v2, i) => asField(v2, `_${i}`)),\n typeIdForValue,\n offsets: int32Array\n };\n};\nvar fixedSizeBinary = (stride) => ({\n typeId: Type.FixedSizeBinary,\n stride\n});\nvar fixedSizeList = (child, stride) => ({\n typeId: Type.FixedSizeList,\n stride,\n children: [asField(child)]\n});\nvar mapType = (keysSorted, child) => ({\n typeId: Type.Map,\n keysSorted,\n children: [child],\n offsets: int32Array\n});\nvar duration = (unit3 = TimeUnit.MILLISECOND) => ({\n typeId: Type.Duration,\n unit: checkOneOf(unit3, TimeUnit),\n values: int64Array\n});\nvar largeBinary = () => ({\n typeId: Type.LargeBinary,\n offsets: int64Array\n});\nvar largeUtf8 = () => ({\n typeId: Type.LargeUtf8,\n offsets: int64Array\n});\nvar largeList = (child) => ({\n typeId: Type.LargeList,\n children: [asField(child)],\n offsets: int64Array\n});\nvar runEndEncoded = (runsField, valuesField) => ({\n typeId: Type.RunEndEncoded,\n children: [\n check(\n asField(runsField, \"run_ends\"),\n (field3) => field3.type.typeId === Type.Int,\n () => \"Run-ends must have an integer type.\"\n ),\n asField(valuesField, \"values\")\n ]\n});\nvar listView = (child) => ({\n typeId: Type.ListView,\n children: [asField(child, \"value\")],\n offsets: int32Array\n});\nvar largeListView = (child) => ({\n typeId: Type.LargeListView,\n children: [asField(child, \"value\")],\n offsets: int64Array\n});\n\n// ../../node_modules/@uwdata/flechette/src/util/numbers.js\nvar f64 = new float64Array(2);\nvar buf = f64.buffer;\nvar i64 = new int64Array(buf);\nvar u32 = new uint32Array(buf);\nvar i32 = new int32Array(buf);\nvar u8 = new uint8Array(buf);\nfunction toNumber(value) {\n if (value > Number.MAX_SAFE_INTEGER || value < Number.MIN_SAFE_INTEGER) {\n throw Error(`BigInt exceeds integer number representation: ${value}`);\n }\n return Number(value);\n}\nfunction divide(num, div) {\n return Number(num / div) + Number(num % div) / Number(div);\n}\nvar asUint64 = (v2) => BigInt.asUintN(64, v2);\nfunction fromDecimal128(buf2, offset2) {\n const i = offset2 << 1;\n let x3;\n if (BigInt.asIntN(64, buf2[i + 1]) < 0) {\n x3 = asUint64(~buf2[i]) | asUint64(~buf2[i + 1]) << 64n;\n x3 = -(x3 + 1n);\n } else {\n x3 = buf2[i] | buf2[i + 1] << 64n;\n }\n return x3;\n}\nfunction fromDecimal256(buf2, offset2) {\n const i = offset2 << 2;\n let x3;\n if (BigInt.asIntN(64, buf2[i + 3]) < 0) {\n x3 = asUint64(~buf2[i]) | asUint64(~buf2[i + 1]) << 64n | asUint64(~buf2[i + 2]) << 128n | asUint64(~buf2[i + 3]) << 192n;\n x3 = -(x3 + 1n);\n } else {\n x3 = buf2[i] | buf2[i + 1] << 64n | buf2[i + 2] << 128n | buf2[i + 3] << 192n;\n }\n return x3;\n}\n\n// ../../node_modules/@uwdata/flechette/src/util/strings.js\nvar textDecoder = new TextDecoder(\"utf-8\");\nvar textEncoder = new TextEncoder();\nfunction decodeUtf8(buf2) {\n return textDecoder.decode(buf2);\n}\n\n// ../../node_modules/@uwdata/flechette/src/util/read.js\nvar SIZEOF_INT = 4;\nfunction decodeBit(bitmap2, index2) {\n return (bitmap2[index2 >> 3] & 1 << index2 % 8) !== 0;\n}\nfunction readObject(buf2, index2) {\n const pos = index2 + readInt32(buf2, index2);\n const vtable = pos - readInt32(buf2, pos);\n const size = readInt16(buf2, vtable);\n return (index3, read, fallback = null) => {\n if (index3 < size) {\n const off = readInt16(buf2, vtable + index3);\n if (off) return read(buf2, pos + off);\n }\n return fallback;\n };\n}\nfunction readOffset(buf2, offset2) {\n return offset2;\n}\nfunction readBoolean(buf2, offset2) {\n return !!readInt8(buf2, offset2);\n}\nfunction readInt8(buf2, offset2) {\n return readUint8(buf2, offset2) << 24 >> 24;\n}\nfunction readUint8(buf2, offset2) {\n return buf2[offset2];\n}\nfunction readInt16(buf2, offset2) {\n return readUint16(buf2, offset2) << 16 >> 16;\n}\nfunction readUint16(buf2, offset2) {\n return buf2[offset2] | buf2[offset2 + 1] << 8;\n}\nfunction readInt32(buf2, offset2) {\n return buf2[offset2] | buf2[offset2 + 1] << 8 | buf2[offset2 + 2] << 16 | buf2[offset2 + 3] << 24;\n}\nfunction readUint32(buf2, offset2) {\n return readInt32(buf2, offset2) >>> 0;\n}\nfunction readInt64(buf2, offset2) {\n return toNumber(BigInt.asIntN(\n 64,\n BigInt(readUint32(buf2, offset2)) + (BigInt(readUint32(buf2, offset2 + SIZEOF_INT)) << 32n)\n ));\n}\nfunction readString(buf2, index2) {\n let offset2 = index2 + readInt32(buf2, index2);\n const length4 = readInt32(buf2, offset2);\n offset2 += SIZEOF_INT;\n return decodeUtf8(buf2.subarray(offset2, offset2 + length4));\n}\nfunction readVector(buf2, offset2, stride, extract) {\n if (!offset2) return [];\n const base = offset2 + readInt32(buf2, offset2);\n return Array.from(\n { length: readInt32(buf2, base) },\n (_, i) => extract(buf2, base + SIZEOF_INT + i * stride)\n );\n}\n\n// ../../node_modules/@uwdata/flechette/src/util/struct.js\nvar RowIndex = Symbol(\"rowIndex\");\nfunction proxyFactory(names, batches) {\n class RowObject {\n /**\n * Create a new proxy row object representing a struct or table row.\n * @param {number} index The record batch row index.\n */\n constructor(index2) {\n this[RowIndex] = index2;\n }\n /**\n * Return a JSON-compatible object representation.\n */\n toJSON() {\n return structObject(names, batches, this[RowIndex]);\n }\n }\n ;\n const proto = RowObject.prototype;\n for (let i = 0; i < names.length; ++i) {\n if (Object.hasOwn(proto, names[i])) continue;\n const batch = batches[i];\n Object.defineProperty(proto, names[i], {\n get() {\n return batch.at(this[RowIndex]);\n },\n enumerable: true\n });\n }\n return (index2) => new RowObject(index2);\n}\nfunction objectFactory(names, batches) {\n return (index2) => structObject(names, batches, index2);\n}\nfunction structObject(names, batches, index2) {\n const obj = {};\n for (let i = 0; i < names.length; ++i) {\n obj[names[i]] = batches[i].at(index2);\n }\n return obj;\n}\n\n// ../../node_modules/@uwdata/flechette/src/batch.js\nfunction isDirectBatch(batch) {\n return batch instanceof DirectBatch;\n}\nvar Batch = class {\n /**\n * The array type to use when extracting data from the batch.\n * A null value indicates that the array type should match\n * the type of the batch's values array.\n * @type {ArrayConstructor | import('./types.js').TypedArrayConstructor | null}\n */\n static ArrayType = null;\n /**\n * Create a new column batch.\n * @param {object} options\n * @param {number} options.length The length of the batch\n * @param {number} options.nullCount The null value count\n * @param {import('./types.js').DataType} options.type The data type.\n * @param {Uint8Array} [options.validity] Validity bitmap buffer\n * @param {import('./types.js').TypedArray} [options.values] Values buffer\n * @param {import('./types.js').OffsetArray} [options.offsets] Offsets buffer\n * @param {import('./types.js').OffsetArray} [options.sizes] Sizes buffer\n * @param {Batch[]} [options.children] Children batches\n */\n constructor({\n length: length4,\n nullCount,\n type: type2,\n validity,\n values: values2,\n offsets,\n sizes,\n children: children2\n }) {\n this.length = length4;\n this.nullCount = nullCount;\n this.type = type2;\n this.validity = validity;\n this.values = values2;\n this.offsets = offsets;\n this.sizes = sizes;\n this.children = children2;\n if (!nullCount || !this.validity) {\n this.at = (index2) => this.value(index2);\n }\n }\n /**\n * Provide an informative object string tag.\n */\n get [Symbol.toStringTag]() {\n return \"Batch\";\n }\n /**\n * Return the value at the given index.\n * @param {number} index The value index.\n * @returns {T | null} The value.\n */\n at(index2) {\n return this.isValid(index2) ? this.value(index2) : null;\n }\n /**\n * Check if a value at the given index is valid (non-null).\n * @param {number} index The value index.\n * @returns {boolean} True if valid, false otherwise.\n */\n isValid(index2) {\n return decodeBit(this.validity, index2);\n }\n /**\n * Return the value at the given index. This method does not check the\n * validity bitmap and is intended primarily for internal use. In most\n * cases, callers should use the `at()` method instead.\n * @param {number} index The value index\n * @returns {T} The value, ignoring the validity bitmap.\n */\n value(index2) {\n return (\n /** @type {T} */\n this.values[index2]\n );\n }\n /**\n * Extract an array of values within the given index range. Unlike\n * Array.slice, all arguments are required and may not be negative indices.\n * @param {number} start The starting index, inclusive\n * @param {number} end The ending index, exclusive\n * @returns {import('./types.js').ValueArray} The slice of values\n */\n slice(start2, end) {\n const n = end - start2;\n const values2 = Array(n);\n for (let i = 0; i < n; ++i) {\n values2[i] = this.at(start2 + i);\n }\n return values2;\n }\n /**\n * Return an iterator over the values in this batch.\n * @returns {Iterator}\n */\n *[Symbol.iterator]() {\n for (let i = 0; i < this.length; ++i) {\n yield this.at(i);\n }\n }\n};\nvar DirectBatch = class extends Batch {\n /**\n * Create a new column batch with direct value array access.\n * @param {object} options\n * @param {number} options.length The length of the batch\n * @param {number} options.nullCount The null value count\n * @param {import('./types.js').DataType} options.type The data type.\n * @param {Uint8Array} [options.validity] Validity bitmap buffer\n * @param {import('./types.js').TypedArray} options.values Values buffer\n */\n constructor(options) {\n super(options);\n const { length: length4, values: values2 } = this;\n this.values = values2.subarray(0, length4);\n }\n /**\n * Extract an array of values within the given index range. Unlike\n * Array.slice, all arguments are required and may not be negative indices.\n * When feasible, a zero-copy subarray of a typed array is returned.\n * @param {number} start The starting index, inclusive\n * @param {number} end The ending index, exclusive\n * @returns {import('./types.js').ValueArray} The slice of values\n */\n slice(start2, end) {\n return this.nullCount ? super.slice(start2, end) : this.values.subarray(start2, end);\n }\n /**\n * Return an iterator over the values in this batch.\n * @returns {Iterator}\n */\n [Symbol.iterator]() {\n return this.nullCount ? super[Symbol.iterator]() : (\n /** @type {Iterator} */\n this.values[Symbol.iterator]()\n );\n }\n};\nvar NumberBatch = class extends Batch {\n static ArrayType = float64Array;\n};\nvar ArrayBatch = class extends Batch {\n static ArrayType = Array;\n};\nvar NullBatch = class extends ArrayBatch {\n /**\n * @param {number} index The value index\n * @returns {null}\n */\n value(index2) {\n return null;\n }\n};\nvar Int64Batch = class extends NumberBatch {\n /**\n * @param {number} index The value index\n */\n value(index2) {\n return toNumber(\n /** @type {bigint} */\n this.values[index2]\n );\n }\n};\nvar Float16Batch = class extends NumberBatch {\n /**\n * @param {number} index The value index\n */\n value(index2) {\n const v2 = (\n /** @type {number} */\n this.values[index2]\n );\n const expo = (v2 & 31744) >> 10;\n const sigf = (v2 & 1023) / 1024;\n const sign3 = (-1) ** ((v2 & 32768) >> 15);\n switch (expo) {\n case 31:\n return sign3 * (sigf ? Number.NaN : 1 / 0);\n case 0:\n return sign3 * (sigf ? 6103515625e-14 * sigf : 0);\n }\n return sign3 * 2 ** (expo - 15) * (1 + sigf);\n }\n};\nvar BoolBatch = class extends ArrayBatch {\n /**\n * @param {number} index The value index\n */\n value(index2) {\n return decodeBit(\n /** @type {Uint8Array} */\n this.values,\n index2\n );\n }\n};\nvar DecimalBatch = class extends Batch {\n constructor(options) {\n super(options);\n const { bitWidth, scale: scale3 } = (\n /** @type {import('./types.js').DecimalType} */\n this.type\n );\n this.decimal = bitWidth === 128 ? fromDecimal128 : fromDecimal256;\n this.scale = 10n ** BigInt(scale3);\n }\n};\nvar DecimalNumberBatch = class extends DecimalBatch {\n static ArrayType = float64Array;\n /**\n * @param {number} index The value index\n */\n value(index2) {\n return divide(\n this.decimal(\n /** @type {BigUint64Array} */\n this.values,\n index2\n ),\n this.scale\n );\n }\n};\nvar DecimalBigIntBatch = class extends DecimalBatch {\n static ArrayType = Array;\n /**\n * @param {number} index The value index\n */\n value(index2) {\n return this.decimal(\n /** @type {BigUint64Array} */\n this.values,\n index2\n );\n }\n};\nvar DateBatch = class extends ArrayBatch {\n /**\n * Create a new date batch.\n * @param {Batch} batch A batch of timestamp values.\n */\n constructor(batch) {\n super(batch);\n this.source = batch;\n }\n /**\n * @param {number} index The value index\n */\n value(index2) {\n return new Date(this.source.value(index2));\n }\n};\nvar DateDayBatch = class extends NumberBatch {\n /**\n * @param {number} index The value index\n * @returns {number}\n */\n value(index2) {\n return 864e5 * /** @type {number} */\n this.values[index2];\n }\n};\nvar DateDayMillisecondBatch = Int64Batch;\nvar TimestampSecondBatch = class extends Int64Batch {\n /**\n * @param {number} index The value index\n */\n value(index2) {\n return super.value(index2) * 1e3;\n }\n};\nvar TimestampMillisecondBatch = Int64Batch;\nvar TimestampMicrosecondBatch = class extends Int64Batch {\n /**\n * @param {number} index The value index\n */\n value(index2) {\n return divide(\n /** @type {bigint} */\n this.values[index2],\n 1000n\n );\n }\n};\nvar TimestampNanosecondBatch = class extends Int64Batch {\n /**\n * @param {number} index The value index\n */\n value(index2) {\n return divide(\n /** @type {bigint} */\n this.values[index2],\n 1000000n\n );\n }\n};\nvar IntervalDayTimeBatch = class extends ArrayBatch {\n /**\n * @param {number} index The value index\n * @returns {Int32Array}\n */\n value(index2) {\n const values2 = (\n /** @type {Int32Array} */\n this.values\n );\n return values2.subarray(index2 << 1, index2 + 1 << 1);\n }\n};\nvar IntervalMonthDayNanoBatch = class extends ArrayBatch {\n /**\n * @param {number} index The value index\n */\n value(index2) {\n const values2 = (\n /** @type {Uint8Array} */\n this.values\n );\n const base = index2 << 4;\n return Float64Array.of(\n readInt32(values2, base),\n readInt32(values2, base + 4),\n readInt64(values2, base + 8)\n );\n }\n};\nvar offset32 = ({ values: values2, offsets }, index2) => values2.subarray(offsets[index2], offsets[index2 + 1]);\nvar offset64 = ({ values: values2, offsets }, index2) => values2.subarray(toNumber(offsets[index2]), toNumber(offsets[index2 + 1]));\nvar BinaryBatch = class extends ArrayBatch {\n /**\n * @param {number} index\n * @returns {Uint8Array}\n */\n value(index2) {\n return offset32(this, index2);\n }\n};\nvar LargeBinaryBatch = class extends ArrayBatch {\n /**\n * @param {number} index\n * @returns {Uint8Array}\n */\n value(index2) {\n return offset64(this, index2);\n }\n};\nvar Utf8Batch = class extends ArrayBatch {\n /**\n * @param {number} index\n */\n value(index2) {\n return decodeUtf8(offset32(this, index2));\n }\n};\nvar LargeUtf8Batch = class extends ArrayBatch {\n /**\n * @param {number} index\n */\n value(index2) {\n return decodeUtf8(offset64(this, index2));\n }\n};\nvar ListBatch = class extends ArrayBatch {\n /**\n * @param {number} index\n * @returns {import('./types.js').ValueArray}\n */\n value(index2) {\n const offsets = (\n /** @type {Int32Array} */\n this.offsets\n );\n return this.children[0].slice(offsets[index2], offsets[index2 + 1]);\n }\n};\nvar LargeListBatch = class extends ArrayBatch {\n /**\n * @param {number} index\n * @returns {import('./types.js').ValueArray}\n */\n value(index2) {\n const offsets = (\n /** @type {BigInt64Array} */\n this.offsets\n );\n return this.children[0].slice(toNumber(offsets[index2]), toNumber(offsets[index2 + 1]));\n }\n};\nvar ListViewBatch = class extends ArrayBatch {\n /**\n * @param {number} index\n * @returns {import('./types.js').ValueArray}\n */\n value(index2) {\n const a2 = (\n /** @type {number} */\n this.offsets[index2]\n );\n const b = a2 + /** @type {number} */\n this.sizes[index2];\n return this.children[0].slice(a2, b);\n }\n};\nvar LargeListViewBatch = class extends ArrayBatch {\n /**\n * @param {number} index\n * @returns {import('./types.js').ValueArray}\n */\n value(index2) {\n const a2 = (\n /** @type {bigint} */\n this.offsets[index2]\n );\n const b = a2 + /** @type {bigint} */\n this.sizes[index2];\n return this.children[0].slice(toNumber(a2), toNumber(b));\n }\n};\nvar FixedBatch = class extends ArrayBatch {\n constructor(options) {\n super(options);\n this.stride = this.type.stride;\n }\n};\nvar FixedBinaryBatch = class extends FixedBatch {\n /**\n * @param {number} index\n * @returns {Uint8Array}\n */\n value(index2) {\n const { stride, values: values2 } = this;\n return (\n /** @type {Uint8Array} */\n values2.subarray(index2 * stride, (index2 + 1) * stride)\n );\n }\n};\nvar FixedListBatch = class extends FixedBatch {\n /**\n * @param {number} index\n * @returns {import('./types.js').ValueArray}\n */\n value(index2) {\n const { children: children2, stride } = this;\n return children2[0].slice(index2 * stride, (index2 + 1) * stride);\n }\n};\nfunction pairs({ children: children2, offsets }, index2) {\n const [keys, vals] = children2[0].children;\n const start2 = offsets[index2];\n const end = offsets[index2 + 1];\n const entries = [];\n for (let i = start2; i < end; ++i) {\n entries.push([keys.at(i), vals.at(i)]);\n }\n return entries;\n}\nvar MapEntryBatch = class extends ArrayBatch {\n /**\n * Return the value at the given index.\n * @param {number} index The value index.\n * @returns {[K, V][]} The map entries as an array of [key, value] arrays.\n */\n value(index2) {\n return (\n /** @type {[K, V][]} */\n pairs(this, index2)\n );\n }\n};\nvar MapBatch = class extends ArrayBatch {\n /**\n * Return the value at the given index.\n * @param {number} index The value index.\n * @returns {Map} The map value.\n */\n value(index2) {\n return new Map(\n /** @type {[K, V][]} */\n pairs(this, index2)\n );\n }\n};\nvar SparseUnionBatch = class extends ArrayBatch {\n /**\n * Create a new column batch.\n * @param {object} options\n * @param {number} options.length The length of the batch\n * @param {number} options.nullCount The null value count\n * @param {import('./types.js').DataType} options.type The data type.\n * @param {Uint8Array} [options.validity] Validity bitmap buffer\n * @param {Int32Array} [options.offsets] Offsets buffer\n * @param {Batch[]} options.children Children batches\n * @param {Int8Array} options.typeIds Union type ids buffer\n * @param {Record} options.map A typeId to children index map\n */\n constructor({ typeIds, ...options }) {\n super(options);\n this.typeIds = typeIds;\n this.typeMap = this.type.typeMap;\n }\n /**\n * @param {number} index The value index.\n */\n value(index2, offset2 = index2) {\n const { typeIds, children: children2, typeMap } = this;\n return children2[typeMap[typeIds[index2]]].at(offset2);\n }\n};\nvar DenseUnionBatch = class extends SparseUnionBatch {\n /**\n * @param {number} index The value index.\n */\n value(index2) {\n return super.value(\n index2,\n /** @type {number} */\n this.offsets[index2]\n );\n }\n};\nvar StructBatch = class extends ArrayBatch {\n constructor(options, factory = objectFactory) {\n super(options);\n this.names = this.type.children.map((child) => child.name);\n this.factory = factory(this.names, this.children);\n }\n /**\n * @param {number} index The value index.\n * @returns {Record}\n */\n value(index2) {\n return this.factory(index2);\n }\n};\nvar StructProxyBatch = class extends StructBatch {\n constructor(options) {\n super(options, proxyFactory);\n }\n};\nvar RunEndEncodedBatch = class extends ArrayBatch {\n /**\n * @param {number} index The value index.\n */\n value(index2) {\n const [{ values: runs }, vals] = this.children;\n return vals.at(\n bisect(\n /** @type {import('./types.js').IntegerArray} */\n runs,\n index2\n )\n );\n }\n};\nvar DictionaryBatch = class extends ArrayBatch {\n /**\n * Register the backing dictionary. Dictionaries are added\n * after batch creation as the complete dictionary may not\n * be finished across multiple record batches.\n * @param {import('./column.js').Column} dictionary\n * The dictionary of column values.\n */\n setDictionary(dictionary2) {\n this.dictionary = dictionary2;\n this.cache = dictionary2.cache();\n return this;\n }\n /**\n * @param {number} index The value index.\n */\n value(index2) {\n return this.cache[this.key(index2)];\n }\n /**\n * @param {number} index The value index.\n * @returns {number} The dictionary key\n */\n key(index2) {\n return (\n /** @type {number} */\n this.values[index2]\n );\n }\n};\nvar ViewBatch = class extends ArrayBatch {\n /**\n * Create a new view batch.\n * @param {object} options Batch options.\n * @param {number} options.length The length of the batch\n * @param {number} options.nullCount The null value count\n * @param {import('./types.js').DataType} options.type The data type.\n * @param {Uint8Array} [options.validity] Validity bitmap buffer\n * @param {Uint8Array} options.values Values buffer\n * @param {Uint8Array[]} options.data View data buffers\n */\n constructor({ data, ...options }) {\n super(options);\n this.data = data;\n }\n /**\n * Get the binary data at the provided index.\n * @param {number} index The value index.\n * @returns {Uint8Array}\n */\n view(index2) {\n const { values: values2, data } = this;\n const offset2 = index2 << 4;\n let start2 = offset2 + 4;\n let buf2 = (\n /** @type {Uint8Array} */\n values2\n );\n const length4 = readInt32(buf2, offset2);\n if (length4 > 12) {\n start2 = readInt32(buf2, offset2 + 12);\n buf2 = data[readInt32(buf2, offset2 + 8)];\n }\n return buf2.subarray(start2, start2 + length4);\n }\n};\nvar BinaryViewBatch = class extends ViewBatch {\n /**\n * @param {number} index The value index.\n */\n value(index2) {\n return this.view(index2);\n }\n};\nvar Utf8ViewBatch = class extends ViewBatch {\n /**\n * @param {number} index The value index.\n */\n value(index2) {\n return decodeUtf8(this.view(index2));\n }\n};\n\n// ../../node_modules/@uwdata/flechette/src/column.js\nfunction columnBuilder(type2) {\n let data = [];\n return {\n add(batch) {\n data.push(batch);\n return this;\n },\n clear: () => data = [],\n done: () => new Column(data, type2)\n };\n}\nvar Column = class {\n /**\n * Create a new column instance.\n * @param {import('./batch.js').Batch[]} data The value batches.\n * @param {import('./types.js').DataType} [type] The column data type.\n * If not specified, the type is extracted from the batches.\n */\n constructor(data, type2 = data[0]?.type) {\n this.type = type2;\n this.length = data.reduce((m, c4) => m + c4.length, 0);\n this.nullCount = data.reduce((m, c4) => m + c4.nullCount, 0);\n this.data = data;\n const n = data.length;\n const offsets = new Int32Array(n + 1);\n if (n === 1) {\n const [batch] = data;\n offsets[1] = batch.length;\n this.at = (index2) => batch.at(index2);\n } else {\n for (let i = 0, s2 = 0; i < n; ++i) {\n offsets[i + 1] = s2 += data[i].length;\n }\n }\n this.offsets = offsets;\n }\n /**\n * Provide an informative object string tag.\n */\n get [Symbol.toStringTag]() {\n return \"Column\";\n }\n /**\n * Return an iterator over the values in this column.\n * @returns {Iterator}\n */\n [Symbol.iterator]() {\n const data = this.data;\n return data.length === 1 ? data[0][Symbol.iterator]() : batchedIterator(data);\n }\n /**\n * Return the column value at the given index. If a column has multiple\n * batches, this method performs binary search over the batch lengths to\n * determine the batch from which to retrieve the value. The search makes\n * lookup less efficient than a standard array access. If making a full\n * scan of a column, consider extracting arrays via `toArray()` or using an\n * iterator (`for (const value of column) {...}`).\n * @param {number} index The row index.\n * @returns {T | null} The value.\n */\n at(index2) {\n const { data, offsets } = this;\n const i = bisect(offsets, index2) - 1;\n return data[i]?.at(index2 - offsets[i]);\n }\n /**\n * Return the column value at the given index. This method is the same as\n * `at()` and is provided for better compatibility with Apache Arrow JS.\n * @param {number} index The row index.\n * @returns {T | null} The value.\n */\n get(index2) {\n return this.at(index2);\n }\n /**\n * Extract column values into a single array instance. When possible,\n * a zero-copy subarray of the input Arrow data is returned.\n * @returns {import('./types.js').ValueArray}\n */\n toArray() {\n const { length: length4, nullCount, data } = this;\n const copy4 = !nullCount && isDirectBatch(data[0]);\n const n = data.length;\n if (copy4 && n === 1) {\n return data[0].values;\n }\n const ArrayType = !n || nullCount > 0 ? Array : data[0].constructor.ArrayType ?? data[0].values.constructor;\n const array4 = new ArrayType(length4);\n return copy4 ? copyArray(array4, data) : extractArray(array4, data);\n }\n /**\n * Return an array of cached column values.\n * Used internally to accelerate dictionary types.\n */\n cache() {\n return this._cache ?? (this._cache = this.toArray());\n }\n};\nfunction* batchedIterator(data) {\n for (let i = 0; i < data.length; ++i) {\n const iter = data[i][Symbol.iterator]();\n for (let next = iter.next(); !next.done; next = iter.next()) {\n yield next.value;\n }\n }\n}\nfunction copyArray(array4, data) {\n for (let i = 0, offset2 = 0; i < data.length; ++i) {\n const { values: values2 } = data[i];\n array4.set(values2, offset2);\n offset2 += values2.length;\n }\n return array4;\n}\nfunction extractArray(array4, data) {\n let index2 = -1;\n for (let i = 0; i < data.length; ++i) {\n const batch = data[i];\n for (let j = 0; j < batch.length; ++j) {\n array4[++index2] = batch.at(j);\n }\n }\n return array4;\n}\n\n// ../../node_modules/@uwdata/flechette/src/table.js\nvar Table = class _Table {\n /**\n * Create a new table with the given schema and columns (children).\n * @param {import('./types.js').Schema} schema The table schema.\n * @param {import('./column.js').Column[]} children The table columns.\n * @param {boolean} [useProxy=false] Flag indicating if row proxy\n * objects should be used to represent table rows (default `false`).\n */\n constructor(schema, children2, useProxy = false) {\n const names = schema.fields.map((f) => f.name);\n this.schema = schema;\n this.names = names;\n this.children = children2;\n this.factory = useProxy ? proxyFactory : objectFactory;\n const gen = [];\n this.getFactory = (b) => gen[b] ?? (gen[b] = this.factory(names, children2.map((c4) => c4.data[b])));\n }\n /**\n * Provide an informative object string tag.\n */\n get [Symbol.toStringTag]() {\n return \"Table\";\n }\n /**\n * The number of columns in this table.\n * @return {number} The number of columns.\n */\n get numCols() {\n return this.names.length;\n }\n /**\n * The number of rows in this table.\n * @return {number} The number of rows.\n */\n get numRows() {\n return this.children[0]?.length ?? 0;\n }\n /**\n * Return the child column at the given index position.\n * @param {number} index The column index.\n * @returns {import('./column.js').Column}\n */\n getChildAt(index2) {\n return this.children[index2];\n }\n /**\n * Return the first child column with the given name.\n * @param {string} name The column name.\n * @returns {import('./column.js').Column}\n */\n getChild(name2) {\n const i = this.names.findIndex((x3) => x3 === name2);\n return i > -1 ? this.children[i] : void 0;\n }\n /**\n * Construct a new table containing only columns at the specified indices.\n * The order of columns in the new table matches the order of input indices.\n * @param {number[]} indices The indices of columns to keep.\n * @param {string[]} [as] Optional new names for selected columns.\n * @returns {Table} A new table with columns at the specified indices.\n */\n selectAt(indices2, as = []) {\n const { children: children2, factory, schema } = this;\n const { fields } = schema;\n return new _Table(\n {\n ...schema,\n fields: indices2.map((i, j) => renameField(fields[i], as[j]))\n },\n indices2.map((i) => children2[i]),\n factory === proxyFactory\n );\n }\n /**\n * Construct a new table containing only columns with the specified names.\n * If columns have duplicate names, the first (with lowest index) is used.\n * The order of columns in the new table matches the order of input names.\n * @param {string[]} names Names of columns to keep.\n * @param {string[]} [as] Optional new names for selected columns.\n * @returns {Table} A new table with columns matching the specified names.\n */\n select(names, as) {\n const all2 = this.names;\n const indices2 = names.map((name2) => all2.indexOf(name2));\n return this.selectAt(indices2, as);\n }\n /**\n * Return an object mapping column names to extracted value arrays.\n * @returns {Record>}\n */\n toColumns() {\n const { children: children2, names } = this;\n const cols = {};\n names.forEach((name2, i) => cols[name2] = children2[i]?.toArray() ?? []);\n return cols;\n }\n /**\n * Return an array of objects representing the rows of this table.\n * @returns {Record[]}\n */\n toArray() {\n const { children: children2, getFactory, numRows } = this;\n const data = children2[0]?.data ?? [];\n const output = Array(numRows);\n for (let b = 0, row = -1; b < data.length; ++b) {\n const f = getFactory(b);\n for (let i = 0; i < data[b].length; ++i) {\n output[++row] = f(i);\n }\n }\n return output;\n }\n /**\n * Return an iterator over objects representing the rows of this table.\n * @returns {Generator, any, null>}\n */\n *[Symbol.iterator]() {\n const { children: children2, getFactory } = this;\n const data = children2[0]?.data ?? [];\n for (let b = 0; b < data.length; ++b) {\n const f = getFactory(b);\n for (let i = 0; i < data[b].length; ++i) {\n yield f(i);\n }\n }\n }\n /**\n * Return a row object for the given index.\n * @param {number} index The row index.\n * @returns {Record} The row object.\n */\n at(index2) {\n const { children: children2, getFactory, numRows } = this;\n if (index2 < 0 || index2 >= numRows) return null;\n const [{ offsets }] = children2;\n const b = bisect(offsets, index2) - 1;\n return getFactory(b)(index2 - offsets[b]);\n }\n /**\n * Return a row object for the given index. This method is the same as\n * `at()` and is provided for better compatibility with Apache Arrow JS.\n * @param {number} index The row index.\n * @returns {Record} The row object.\n */\n get(index2) {\n return this.at(index2);\n }\n};\nfunction renameField(field3, name2) {\n return name2 != null && name2 !== field3.name ? { ...field3, name: name2 } : field3;\n}\n\n// ../../node_modules/@uwdata/flechette/src/batch-type.js\nfunction batchType(type2, options = {}) {\n const { typeId, bitWidth, precision, unit: unit3 } = type2;\n const { useBigInt, useDate, useDecimalBigInt, useMap, useProxy } = options;\n switch (typeId) {\n case Type.Null:\n return NullBatch;\n case Type.Bool:\n return BoolBatch;\n case Type.Int:\n case Type.Time:\n case Type.Duration:\n return useBigInt || bitWidth < 64 ? DirectBatch : Int64Batch;\n case Type.Float:\n return precision ? DirectBatch : Float16Batch;\n case Type.Date:\n return wrap(\n unit3 === DateUnit.DAY ? DateDayBatch : DateDayMillisecondBatch,\n useDate && DateBatch\n );\n case Type.Timestamp:\n return wrap(\n unit3 === TimeUnit.SECOND ? TimestampSecondBatch : unit3 === TimeUnit.MILLISECOND ? TimestampMillisecondBatch : unit3 === TimeUnit.MICROSECOND ? TimestampMicrosecondBatch : TimestampNanosecondBatch,\n useDate && DateBatch\n );\n case Type.Decimal:\n return useDecimalBigInt ? DecimalBigIntBatch : DecimalNumberBatch;\n case Type.Interval:\n return unit3 === IntervalUnit.DAY_TIME ? IntervalDayTimeBatch : unit3 === IntervalUnit.YEAR_MONTH ? DirectBatch : IntervalMonthDayNanoBatch;\n case Type.FixedSizeBinary:\n return FixedBinaryBatch;\n case Type.Utf8:\n return Utf8Batch;\n case Type.LargeUtf8:\n return LargeUtf8Batch;\n case Type.Binary:\n return BinaryBatch;\n case Type.LargeBinary:\n return LargeBinaryBatch;\n case Type.BinaryView:\n return BinaryViewBatch;\n case Type.Utf8View:\n return Utf8ViewBatch;\n case Type.List:\n return ListBatch;\n case Type.LargeList:\n return LargeListBatch;\n case Type.Map:\n return useMap ? MapBatch : MapEntryBatch;\n case Type.ListView:\n return ListViewBatch;\n case Type.LargeListView:\n return LargeListViewBatch;\n case Type.FixedSizeList:\n return FixedListBatch;\n case Type.Struct:\n return useProxy ? StructProxyBatch : StructBatch;\n case Type.RunEndEncoded:\n return RunEndEncodedBatch;\n case Type.Dictionary:\n return DictionaryBatch;\n case Type.Union:\n return type2.mode ? DenseUnionBatch : SparseUnionBatch;\n }\n throw new Error(invalidDataType(typeId));\n}\nfunction wrap(BaseClass, WrapperClass) {\n return WrapperClass ? class WrapBatch extends WrapperClass {\n constructor(options) {\n super(new BaseClass(options));\n }\n } : BaseClass;\n}\n\n// ../../node_modules/@uwdata/flechette/src/decode/block.js\nfunction decodeBlock(buf2, index2) {\n return {\n offset: readInt64(buf2, index2),\n metadataLength: readInt32(buf2, index2 + 8),\n bodyLength: readInt64(buf2, index2 + 16)\n };\n}\nfunction decodeBlocks(buf2, index2) {\n return readVector(buf2, index2, 24, decodeBlock);\n}\n\n// ../../node_modules/@uwdata/flechette/src/decode/record-batch.js\nfunction decodeRecordBatch(buf2, index2, version) {\n const get3 = readObject(buf2, index2);\n if (get3(10, readOffset, 0)) {\n throw new Error(\"Record batch compression not implemented\");\n }\n const offset2 = version < Version.V4 ? 8 : 0;\n return {\n length: get3(4, readInt64, 0),\n nodes: readVector(buf2, get3(6, readOffset), 16, (buf3, pos) => ({\n length: readInt64(buf3, pos),\n nullCount: readInt64(buf3, pos + 8)\n })),\n regions: readVector(buf2, get3(8, readOffset), 16 + offset2, (buf3, pos) => ({\n offset: readInt64(buf3, pos + offset2),\n length: readInt64(buf3, pos + offset2 + 8)\n })),\n variadic: readVector(buf2, get3(12, readOffset), 8, readInt64)\n };\n}\n\n// ../../node_modules/@uwdata/flechette/src/decode/dictionary-batch.js\nfunction decodeDictionaryBatch(buf2, index2, version) {\n const get3 = readObject(buf2, index2);\n return {\n id: get3(4, readInt64, 0),\n data: get3(6, (buf3, off) => decodeRecordBatch(buf3, off, version)),\n /**\n * If isDelta is true the values in the dictionary are to be appended to a\n * dictionary with the indicated id. If isDelta is false this dictionary\n * should replace the existing dictionary.\n */\n isDelta: get3(8, readBoolean, false)\n };\n}\n\n// ../../node_modules/@uwdata/flechette/src/decode/data-type.js\nfunction decodeDataType(buf2, index2, typeId, children2) {\n checkOneOf(typeId, Type, invalidDataType);\n const get3 = readObject(buf2, index2);\n switch (typeId) {\n // types without flatbuffer objects\n case Type.Binary:\n return binary();\n case Type.Utf8:\n return utf8();\n case Type.LargeBinary:\n return largeBinary();\n case Type.LargeUtf8:\n return largeUtf8();\n case Type.List:\n return list(children2[0]);\n case Type.ListView:\n return listView(children2[0]);\n case Type.LargeList:\n return largeList(children2[0]);\n case Type.LargeListView:\n return largeListView(children2[0]);\n case Type.Struct:\n return struct(children2);\n case Type.RunEndEncoded:\n return runEndEncoded(children2[0], children2[1]);\n // types with flatbuffer objects\n case Type.Int:\n return int(\n // @ts-ignore\n get3(4, readInt32, 0),\n // bitwidth\n get3(6, readBoolean, false)\n // signed\n );\n case Type.Float:\n return float(\n // @ts-ignore\n get3(4, readInt16, Precision.HALF)\n // precision\n );\n case Type.Decimal:\n return decimal(\n get3(4, readInt32, 0),\n // precision\n get3(6, readInt32, 0),\n // scale\n // @ts-ignore\n get3(8, readInt32, 128)\n // bitwidth\n );\n case Type.Date:\n return date(\n // @ts-ignore\n get3(4, readInt16, DateUnit.MILLISECOND)\n // unit\n );\n case Type.Time:\n return time(\n // @ts-ignore\n get3(4, readInt16, TimeUnit.MILLISECOND),\n // unit\n get3(6, readInt32, 32)\n // bitWidth\n );\n case Type.Timestamp:\n return timestamp(\n // @ts-ignore\n get3(4, readInt16, TimeUnit.SECOND),\n // unit\n get3(6, readString)\n // timezone\n );\n case Type.Interval:\n return interval(\n // @ts-ignore\n get3(4, readInt16, IntervalUnit.YEAR_MONTH)\n // unit\n );\n case Type.Duration:\n return duration(\n // @ts-ignore\n get3(4, readInt16, TimeUnit.MILLISECOND)\n // unit\n );\n case Type.FixedSizeBinary:\n return fixedSizeBinary(\n get3(4, readInt32, 0)\n // stride\n );\n case Type.FixedSizeList:\n return fixedSizeList(\n children2[0],\n get3(4, readInt32, 0)\n // stride\n );\n case Type.Map:\n return mapType(\n get3(4, readBoolean, false),\n // keysSorted\n children2[0]\n );\n case Type.Union:\n return union(\n // @ts-ignore\n get3(4, readInt16, UnionMode.Sparse),\n // mode\n children2,\n readVector(buf2, get3(6, readOffset), 4, readInt32)\n // type ids\n );\n }\n return { typeId };\n}\n\n// ../../node_modules/@uwdata/flechette/src/decode/metadata.js\nfunction decodeMetadata(buf2, index2) {\n const entries = readVector(buf2, index2, 4, (buf3, pos) => {\n const get3 = readObject(buf3, pos);\n return (\n /** @type {[string, string]} */\n [\n get3(4, readString),\n // 4: key (string)\n get3(6, readString)\n // 6: key (string)\n ]\n );\n });\n return entries.length ? new Map(entries) : null;\n}\n\n// ../../node_modules/@uwdata/flechette/src/decode/schema.js\nfunction decodeSchema(buf2, index2, version) {\n const get3 = readObject(buf2, index2);\n return {\n version,\n endianness: (\n /** @type {import('../types.js').Endianness_} */\n get3(4, readInt16, 0)\n ),\n fields: get3(6, decodeSchemaFields, []),\n metadata: get3(8, decodeMetadata)\n };\n}\nfunction decodeSchemaFields(buf2, fieldsOffset) {\n return readVector(buf2, fieldsOffset, 4, decodeField);\n}\nfunction decodeField(buf2, index2) {\n const get3 = readObject(buf2, index2);\n const typeId = get3(8, readUint8, Type.NONE);\n const typeOffset = get3(10, readOffset, 0);\n const dict = get3(12, decodeDictionary);\n const children2 = get3(14, (buf3, off) => decodeFieldChildren(buf3, off));\n let type2 = decodeDataType(buf2, typeOffset, typeId, children2);\n if (dict) {\n dict.dictionary = type2;\n type2 = dict;\n }\n return {\n name: get3(4, readString),\n type: type2,\n nullable: get3(6, readBoolean, false),\n metadata: get3(16, decodeMetadata)\n };\n}\nfunction decodeFieldChildren(buf2, fieldOffset) {\n const children2 = readVector(buf2, fieldOffset, 4, decodeField);\n return children2.length ? children2 : null;\n}\nfunction decodeDictionary(buf2, index2) {\n if (!index2) return null;\n const get3 = readObject(buf2, index2);\n return dictionary(\n null,\n // data type will be populated by caller\n get3(6, decodeInt, int32()),\n // index type\n get3(8, readBoolean, false),\n // ordered\n get3(4, readInt64, 0)\n // id\n );\n}\nfunction decodeInt(buf2, index2) {\n return (\n /** @type {import('../types.js').IntType} */\n decodeDataType(buf2, index2, Type.Int)\n );\n}\n\n// ../../node_modules/@uwdata/flechette/src/decode/message.js\nvar invalidMessageMetadata = (expected, actual) => `Expected to read ${expected} metadata bytes, but only read ${actual}.`;\nvar invalidMessageBodyLength = (expected, actual) => `Expected to read ${expected} bytes for message body, but only read ${actual}.`;\nvar invalidMessageType = (type2) => `Unsupported message type: ${type2} (${keyFor(MessageHeader, type2)})`;\nfunction decodeMessage(buf2, index2) {\n let metadataLength = readInt32(buf2, index2) || 0;\n index2 += SIZEOF_INT;\n if (metadataLength === -1) {\n metadataLength = readInt32(buf2, index2) || 0;\n index2 += SIZEOF_INT;\n }\n if (metadataLength === 0) return null;\n const head = buf2.subarray(index2, index2 += metadataLength);\n if (head.byteLength < metadataLength) {\n throw new Error(invalidMessageMetadata(metadataLength, head.byteLength));\n }\n const get3 = readObject(head, 0);\n const version = (\n /** @type {import('../types.js').Version_} */\n get3(4, readInt16, Version.V1)\n );\n const type2 = (\n /** @type {import('../types.js').MessageHeader_} */\n get3(6, readUint8, MessageHeader.NONE)\n );\n const offset2 = get3(8, readOffset, 0);\n const bodyLength = get3(10, readInt64, 0);\n let content;\n if (offset2) {\n const decoder = type2 === MessageHeader.Schema ? decodeSchema : type2 === MessageHeader.DictionaryBatch ? decodeDictionaryBatch : type2 === MessageHeader.RecordBatch ? decodeRecordBatch : null;\n if (!decoder) throw new Error(invalidMessageType(type2));\n content = decoder(head, offset2, version);\n if (bodyLength > 0) {\n const body = buf2.subarray(index2, index2 += bodyLength);\n if (body.byteLength < bodyLength) {\n throw new Error(invalidMessageBodyLength(bodyLength, body.byteLength));\n }\n content.body = body;\n }\n }\n return { version, type: type2, index: index2, content };\n}\n\n// ../../node_modules/@uwdata/flechette/src/decode/decode-ipc.js\nfunction decodeIPC(data) {\n const source = data instanceof ArrayBuffer ? new Uint8Array(data) : data;\n return source instanceof Uint8Array && isArrowFileFormat(source) ? decodeIPCFile(source) : decodeIPCStream(source);\n}\nfunction isArrowFileFormat(buf2) {\n if (!buf2 || buf2.length < 4) return false;\n for (let i = 0; i < 6; ++i) {\n if (MAGIC[i] !== buf2[i]) return false;\n }\n return true;\n}\nfunction decodeIPCStream(data) {\n const stream = [data].flat();\n let schema;\n const records = [];\n const dictionaries = [];\n for (const buf2 of stream) {\n if (!(buf2 instanceof Uint8Array)) {\n throw new Error(`IPC data batch was not a Uint8Array.`);\n }\n let offset2 = 0;\n while (true) {\n const m = decodeMessage(buf2, offset2);\n if (m === null) break;\n offset2 = m.index;\n if (!m.content) continue;\n switch (m.type) {\n case MessageHeader.Schema:\n if (!schema) schema = m.content;\n break;\n case MessageHeader.RecordBatch:\n records.push(m.content);\n break;\n case MessageHeader.DictionaryBatch:\n dictionaries.push(m.content);\n break;\n }\n }\n }\n return (\n /** @type {import('../types.js').ArrowData} */\n { schema, dictionaries, records, metadata: null }\n );\n}\nfunction decodeIPCFile(data) {\n const offset2 = data.byteLength - (MAGIC.length + 4);\n const length4 = readInt32(data, offset2);\n const get3 = readObject(data, offset2 - length4);\n const version = (\n /** @type {import('../types.js').Version_} */\n get3(4, readInt16, Version.V1)\n );\n const dicts = get3(8, decodeBlocks, []);\n const recs = get3(10, decodeBlocks, []);\n return (\n /** @type {import('../types.js').ArrowData} */\n {\n schema: get3(6, (buf2, index2) => decodeSchema(buf2, index2, version)),\n dictionaries: dicts.map(({ offset: offset3 }) => decodeMessage(data, offset3).content),\n records: recs.map(({ offset: offset3 }) => decodeMessage(data, offset3).content),\n metadata: get3(12, decodeMetadata)\n }\n );\n}\n\n// ../../node_modules/@uwdata/flechette/src/decode/table-from-ipc.js\nfunction tableFromIPC(data, options) {\n return createTable(decodeIPC(data), options);\n}\nfunction createTable(data, options = {}) {\n const { schema = { fields: [] }, dictionaries, records } = data;\n const { version, fields } = schema;\n const dictionaryMap = /* @__PURE__ */ new Map();\n const context = contextGenerator(options, version, dictionaryMap);\n const dictionaryTypes = /* @__PURE__ */ new Map();\n visitSchemaFields(schema, (field3) => {\n const type2 = field3.type;\n if (type2.typeId === Type.Dictionary) {\n dictionaryTypes.set(type2.id, type2.dictionary);\n }\n });\n const dicts = /* @__PURE__ */ new Map();\n for (const dict of dictionaries) {\n const { id: id2, data: data2, isDelta, body } = dict;\n const type2 = dictionaryTypes.get(id2);\n const batch = visit(type2, context({ ...data2, body }));\n if (!dicts.has(id2)) {\n if (isDelta) {\n throw new Error(\"Delta update can not be first dictionary batch.\");\n }\n dicts.set(id2, columnBuilder(type2).add(batch));\n } else {\n const dict2 = dicts.get(id2);\n if (!isDelta) dict2.clear();\n dict2.add(batch);\n }\n }\n dicts.forEach((value, key) => dictionaryMap.set(key, value.done()));\n const cols = fields.map((f) => columnBuilder(f.type));\n for (const batch of records) {\n const ctx = context(batch);\n fields.forEach((f, i) => cols[i].add(visit(f.type, ctx)));\n }\n return new Table(schema, cols.map((c4) => c4.done()), options.useProxy);\n}\nfunction visitSchemaFields(schema, visitor) {\n schema.fields.forEach(function visitField(field3) {\n visitor(field3);\n field3.type.dictionary?.children?.forEach(visitField);\n field3.type.children?.forEach(visitField);\n });\n}\nfunction contextGenerator(options, version, dictionaryMap) {\n const base = {\n version,\n options,\n dictionary: (id2) => dictionaryMap.get(id2)\n };\n return (batch) => {\n const { length: length4, nodes, regions, variadic, body } = batch;\n let nodeIndex = -1;\n let bufferIndex = -1;\n let variadicIndex = -1;\n return {\n ...base,\n length: length4,\n node: () => nodes[++nodeIndex],\n buffer: (ArrayType) => {\n const { length: length5, offset: offset2 } = regions[++bufferIndex];\n return ArrayType ? new ArrayType(body.buffer, body.byteOffset + offset2, length5 / ArrayType.BYTES_PER_ELEMENT) : body.subarray(offset2, offset2 + length5);\n },\n variadic: () => variadic[++variadicIndex],\n visit(children2) {\n return children2.map((f) => visit(f.type, this));\n }\n };\n };\n}\nfunction visit(type2, ctx) {\n const { typeId } = type2;\n const { length: length4, options, node, buffer: buffer2, variadic, version } = ctx;\n const BatchType = batchType(type2, options);\n if (typeId === Type.Null) {\n return new BatchType({ length: length4, nullCount: length4, type: type2 });\n }\n const base = { ...node(), type: type2 };\n switch (typeId) {\n // validity and data value buffers\n case Type.Bool:\n case Type.Int:\n case Type.Time:\n case Type.Duration:\n case Type.Float:\n case Type.Decimal:\n case Type.Date:\n case Type.Timestamp:\n case Type.Interval:\n case Type.FixedSizeBinary:\n return new BatchType({\n ...base,\n validity: buffer2(),\n values: buffer2(type2.values)\n });\n // validity, offset, and value buffers\n case Type.Utf8:\n case Type.LargeUtf8:\n case Type.Binary:\n case Type.LargeBinary:\n return new BatchType({\n ...base,\n validity: buffer2(),\n offsets: buffer2(type2.offsets),\n values: buffer2()\n });\n // views with variadic buffers\n case Type.BinaryView:\n case Type.Utf8View:\n return new BatchType({\n ...base,\n validity: buffer2(),\n values: buffer2(),\n // views buffer\n data: Array.from({ length: variadic() }, () => buffer2())\n // data buffers\n });\n // validity, offset, and list child\n case Type.List:\n case Type.LargeList:\n case Type.Map:\n return new BatchType({\n ...base,\n validity: buffer2(),\n offsets: buffer2(type2.offsets),\n children: ctx.visit(type2.children)\n });\n // validity, offset, size, and list child\n case Type.ListView:\n case Type.LargeListView:\n return new BatchType({\n ...base,\n validity: buffer2(),\n offsets: buffer2(type2.offsets),\n sizes: buffer2(type2.offsets),\n children: ctx.visit(type2.children)\n });\n // validity and children\n case Type.FixedSizeList:\n case Type.Struct:\n return new BatchType({\n ...base,\n validity: buffer2(),\n children: ctx.visit(type2.children)\n });\n // children only\n case Type.RunEndEncoded:\n return new BatchType({\n ...base,\n children: ctx.visit(type2.children)\n });\n // dictionary\n case Type.Dictionary: {\n const { id: id2, indices: indices2 } = type2;\n return new BatchType({\n ...base,\n validity: buffer2(),\n values: buffer2(indices2.values)\n }).setDictionary(ctx.dictionary(id2));\n }\n // union\n case Type.Union: {\n if (version < Version.V5) {\n buffer2();\n }\n return new BatchType({\n ...base,\n typeIds: buffer2(int8Array),\n offsets: type2.mode === UnionMode.Sparse ? null : buffer2(type2.offsets),\n children: ctx.visit(type2.children)\n });\n }\n // unsupported type\n default:\n throw new Error(invalidDataType(typeId));\n }\n}\n\n// ../../node_modules/@uwdata/flechette/src/encode/schema.js\nvar isLittleEndian = new Uint16Array(new Uint8Array([1, 0]).buffer)[0] === 1;\n\n// ../core/src/util/decode-ipc.js\nfunction decodeIPC2(data) {\n return tableFromIPC(data, { useDate: true });\n}\n\n// ../core/src/connectors/socket.js\nfunction socketConnector(uri = \"ws://localhost:3000/\") {\n const queue = [];\n let connected = false;\n let request = null;\n let ws;\n const events = {\n open() {\n connected = true;\n next();\n },\n close() {\n connected = false;\n request = null;\n ws = null;\n while (queue.length) {\n queue.shift().reject(\"Socket closed\");\n }\n },\n error(event) {\n if (request) {\n const { reject } = request;\n request = null;\n next();\n reject(event);\n } else {\n console.error(\"WebSocket error: \", event);\n }\n },\n message({ data }) {\n if (request) {\n const { query, resolve, reject } = request;\n request = null;\n next();\n if (typeof data === \"string\") {\n const json = JSON.parse(data);\n json.error ? reject(json.error) : resolve(json);\n } else if (query.type === \"exec\") {\n resolve();\n } else if (query.type === \"arrow\") {\n resolve(decodeIPC2(data));\n } else {\n throw new Error(`Unexpected socket data: ${data}`);\n }\n } else {\n console.log(\"WebSocket message: \", data);\n }\n }\n };\n function init2() {\n ws = new WebSocket(uri);\n ws.binaryType = \"arraybuffer\";\n for (const type2 in events) {\n ws.addEventListener(type2, events[type2]);\n }\n }\n function enqueue(query, resolve, reject) {\n if (ws == null) init2();\n queue.push({ query, resolve, reject });\n if (connected && !request) next();\n }\n function next() {\n if (queue.length) {\n request = queue.shift();\n ws.send(JSON.stringify(request.query));\n }\n }\n return {\n get connected() {\n return connected;\n },\n /**\n * Query the DuckDB server.\n * @param {object} query\n * @param {'exec' | 'arrow' | 'json' | 'create-bundle' | 'load-bundle'} [query.type] The query type.\n * @param {string} query.sql A SQL query string.\n * @returns the query result\n */\n query(query) {\n return new Promise(\n (resolve, reject) => enqueue(query, resolve, reject)\n );\n }\n };\n}\n\n// ../sql/src/ref.js\nvar Ref = class {\n /**\n * Create a new Ref instance.\n * @param {string|Ref|null} table The table name.\n * @param {string|null} [column] The column name.\n */\n constructor(table3, column3) {\n if (table3) this.table = String(table3);\n if (column3) this.column = column3;\n }\n /**\n * Get the list of referenced columns. Either a single element array\n * if column is non-null, otherwise an empty array.\n */\n get columns() {\n return this.column ? [this.column] : [];\n }\n /**\n * Generate a SQL string for this reference.\n * @returns {string} The SQL string.\n */\n toString() {\n const { table: table3, column: column3 } = this;\n if (column3) {\n const col = column3.startsWith(\"*\") ? column3 : `\"${column3}\"`;\n return `${table3 ? `${quoteTableName(table3)}.` : \"\"}${col}`;\n } else {\n return table3 ? quoteTableName(table3) : \"NULL\";\n }\n }\n};\nfunction quoteTableName(table3) {\n const pieces = table3.split(\".\");\n return pieces.map((p) => `\"${p}\"`).join(\".\");\n}\nfunction isColumnRefFor(ref, name2) {\n return ref instanceof Ref && ref.column === name2;\n}\nfunction asColumn(value) {\n return typeof value === \"string\" ? column(value) : value;\n}\nfunction asRelation(value) {\n return typeof value === \"string\" ? relation(value) : value;\n}\nfunction relation(name2) {\n return new Ref(name2);\n}\nfunction column(table3, column3 = null) {\n if (arguments.length === 1) {\n column3 = table3;\n table3 = null;\n }\n return new Ref(table3, column3);\n}\n\n// ../sql/src/to-sql.js\nfunction literalToSQL(value) {\n switch (typeof value) {\n case \"boolean\":\n return value ? \"TRUE\" : \"FALSE\";\n case \"string\":\n return `'${value.replace(`'`, `''`)}'`;\n case \"number\":\n return Number.isFinite(value) ? String(value) : \"NULL\";\n default:\n if (value == null) {\n return \"NULL\";\n } else if (value instanceof Date) {\n const ts = +value;\n if (Number.isNaN(ts)) return \"NULL\";\n const y3 = value.getUTCFullYear();\n const m = value.getUTCMonth();\n const d = value.getUTCDate();\n return ts === Date.UTC(y3, m, d) ? `MAKE_DATE(${y3}, ${m + 1}, ${d})` : `EPOCH_MS(${ts})`;\n } else if (value instanceof RegExp) {\n return `'${value.source}'`;\n } else {\n return String(value);\n }\n }\n}\n\n// ../sql/src/expression.js\nvar isParamLike = (value) => typeof value?.addEventListener === \"function\";\nfunction isSQLExpression(value) {\n return value instanceof SQLExpression;\n}\nvar SQLExpression = class {\n /**\n * Create a new SQL expression instance.\n * @param {(string | ParamLike | SQLExpression | import('./ref.js').Ref)[]} parts The parts of the expression.\n * @param {string[]} [columns=[]] The column dependencies\n * @param {object} [props] Additional properties for this expression.\n */\n constructor(parts, columns, props) {\n this._expr = Array.isArray(parts) ? parts : [parts];\n this._deps = columns || [];\n this.annotate(props);\n const params = this._expr.filter((part) => isParamLike(part));\n if (params.length > 0) {\n this._params = Array.from(new Set(params));\n this._params.forEach((param) => {\n param.addEventListener(\"value\", () => update(this, this.map?.get(\"value\")));\n });\n } else {\n this.addEventListener = void 0;\n }\n }\n /**\n * A reference to this expression.\n * Provides compatibility with param-like objects.\n */\n get value() {\n return this;\n }\n /**\n * The column dependencies of this expression.\n * @returns {string[]} The columns dependencies.\n */\n get columns() {\n const { _params, _deps } = this;\n if (_params) {\n const pset = new Set(_params.flatMap((p) => {\n const cols = p.value?.columns;\n return Array.isArray(cols) ? cols : [];\n }));\n if (pset.size) {\n const set3 = new Set(_deps);\n pset.forEach((col) => set3.add(col));\n return Array.from(set3);\n }\n }\n return _deps;\n }\n /**\n * The first column dependency in this expression, or undefined if none.\n * @returns {string} The first column dependency.\n */\n get column() {\n return this._deps.length ? this._deps[0] : this.columns[0];\n }\n /**\n * Annotate this expression instance with additional properties.\n * @param {object[]} [props] One or more objects with properties to add.\n * @returns This SQL expression.\n */\n annotate(...props) {\n return Object.assign(this, ...props);\n }\n /**\n * Generate a SQL code string corresponding to this expression.\n * @returns {string} A SQL code string.\n */\n toString() {\n return this._expr.map((p) => isParamLike(p) && !isSQLExpression(p) ? literalToSQL(p.value) : p).join(\"\");\n }\n /**\n * Add an event listener callback for the provided event type.\n * @param {string} type The event type to listen for (for example, \"value\").\n * @param {(a: SQLExpression) => Promise?} callback The callback function to\n * invoke upon updates. A callback may optionally return a Promise that\n * upstream listeners may await before proceeding.\n */\n addEventListener(type2, callback) {\n const map5 = this.map || (this.map = /* @__PURE__ */ new Map());\n const set3 = map5.get(type2) || (map5.set(type2, /* @__PURE__ */ new Set()), map5.get(type2));\n set3.add(callback);\n }\n};\nfunction update(expr, callbacks) {\n if (callbacks?.size) {\n return Promise.allSettled(Array.from(callbacks, (fn) => fn(expr)));\n }\n}\nfunction parseSQL(strings, exprs) {\n const spans = [strings[0]];\n const cols = /* @__PURE__ */ new Set();\n const n = exprs.length;\n for (let i = 0, k2 = 0; i < n; ) {\n const e = exprs[i];\n if (isParamLike(e)) {\n spans[++k2] = e;\n } else {\n if (Array.isArray(e?.columns)) {\n e.columns.forEach((col) => cols.add(col));\n }\n spans[k2] += typeof e === \"string\" ? e : literalToSQL(e);\n }\n const s2 = strings[++i];\n if (isParamLike(spans[k2])) {\n spans[++k2] = s2;\n } else {\n spans[k2] += s2;\n }\n }\n return { spans, cols: Array.from(cols) };\n}\nfunction sql(strings, ...exprs) {\n const { spans, cols } = parseSQL(strings, exprs);\n return new SQLExpression(spans, cols);\n}\n\n// ../sql/src/desc.js\nfunction desc(expr) {\n const e = asColumn(expr);\n return sql`${e} DESC NULLS LAST`.annotate({ label: e?.label, desc: true });\n}\n\n// ../sql/src/literal.js\nvar literal = (value) => ({\n value,\n toString: () => literalToSQL(value)\n});\n\n// ../sql/src/operators.js\nfunction visit2(callback) {\n callback(this.op, this);\n this.children?.forEach((v2) => v2.visit(callback));\n}\nfunction logical(op, clauses) {\n const children2 = clauses.filter((x3) => x3 != null).map(asColumn);\n const strings = children2.map((c4, i) => i ? ` ${op} ` : \"\");\n if (children2.length === 1) {\n strings.push(\"\");\n } else if (children2.length > 1) {\n strings[0] = \"(\";\n strings.push(\")\");\n }\n return sql(strings, ...children2).annotate({ op, children: children2, visit: visit2 });\n}\nvar and = (...clauses) => logical(\"AND\", clauses.flat());\nvar or = (...clauses) => logical(\"OR\", clauses.flat());\nvar unaryOp = (op) => (a2) => sql`(${op} ${asColumn(a2)})`.annotate({ op, a: a2, visit: visit2 });\nvar not = unaryOp(\"NOT\");\nvar unaryPostOp = (op) => (a2) => sql`(${asColumn(a2)} ${op})`.annotate({ op, a: a2, visit: visit2 });\nvar isNull = unaryPostOp(\"IS NULL\");\nvar isNotNull = unaryPostOp(\"IS NOT NULL\");\nvar binaryOp = (op) => (a2, b) => sql`(${asColumn(a2)} ${op} ${asColumn(b)})`.annotate({ op, a: a2, b, visit: visit2 });\nvar eq = binaryOp(\"=\");\nvar neq = binaryOp(\"<>\");\nvar lt = binaryOp(\"<\");\nvar gt = binaryOp(\">\");\nvar lte = binaryOp(\"<=\");\nvar gte = binaryOp(\">=\");\nvar isDistinct = binaryOp(\"IS DISTINCT FROM\");\nvar isNotDistinct = binaryOp(\"IS NOT DISTINCT FROM\");\nfunction rangeOp(op, a2, range3, exclusive) {\n a2 = asColumn(a2);\n const prefix2 = op.startsWith(\"NOT \") ? \"NOT \" : \"\";\n const expr = !range3 ? sql`` : exclusive ? sql`${prefix2}(${range3[0]} <= ${a2} AND ${a2} < ${range3[1]})` : sql`(${a2} ${op} ${range3[0]} AND ${range3[1]})`;\n return expr.annotate({ op, visit: visit2, field: a2, range: range3 });\n}\nvar isBetween = (a2, range3, exclusive) => rangeOp(\"BETWEEN\", a2, range3, exclusive);\nvar isNotBetween = (a2, range3, exclusive) => rangeOp(\"NOT BETWEEN\", a2, range3, exclusive);\n\n// ../sql/src/repeat.js\nfunction repeat(length4, str) {\n return Array.from({ length: length4 }, () => str);\n}\n\n// ../sql/src/functions.js\nfunction functionCall(op, type2) {\n return (...values2) => {\n const args = values2.map(asColumn);\n const cast2 = type2 ? `::${type2}` : \"\";\n const expr = args.length ? sql([`${op}(`, ...repeat(args.length - 1, \", \"), `)${cast2}`], ...args) : sql`${op}()${cast2}`;\n return expr.annotate({ func: op, args });\n };\n}\nvar regexp_matches = functionCall(\"REGEXP_MATCHES\");\nvar contains = functionCall(\"CONTAINS\");\nvar prefix = functionCall(\"PREFIX\");\nvar suffix = functionCall(\"SUFFIX\");\nvar lower = functionCall(\"LOWER\");\nvar upper = functionCall(\"UPPER\");\nvar length = functionCall(\"LENGTH\");\nvar isNaN2 = functionCall(\"ISNAN\");\nvar isFinite2 = functionCall(\"ISFINITE\");\nvar isInfinite = functionCall(\"ISINF\");\n\n// ../sql/src/windows.js\nvar WindowFunction = class _WindowFunction extends SQLExpression {\n /**\n * Create a new WindowFunction instance.\n * @param {string} op The window operation indicator.\n * @param {*} func The window function expression.\n * @param {*} [type] The SQL data type to cast to.\n * @param {string} [name] The window definition name.\n * @param {*} [group] Grouping (partition by) expressions.\n * @param {*} [order] Sorting (order by) expressions.\n * @param {*} [frame] The window frame definition.\n */\n constructor(op, func, type2, name2, group3 = \"\", order = \"\", frame4 = \"\") {\n let expr;\n const noWindowParams = !(group3 || order || frame4);\n if (name2 && noWindowParams) {\n expr = name2 ? sql`${func} OVER \"${name2}\"` : sql`${func} OVER ()`;\n } else {\n const s1 = group3 && order ? \" \" : \"\";\n const s2 = (group3 || order) && frame4 ? \" \" : \"\";\n expr = sql`${func} OVER (${name2 ? `\"${name2}\" ` : \"\"}${group3}${s1}${order}${s2}${frame4})`;\n }\n if (type2) {\n expr = sql`(${expr})::${type2}`;\n }\n const { _expr, _deps } = expr;\n super(_expr, _deps);\n this.window = op;\n this.func = func;\n this.type = type2;\n this.name = name2;\n this.group = group3;\n this.order = order;\n this.frame = frame4;\n }\n get basis() {\n return this.column;\n }\n get label() {\n const { func } = this;\n return func.label ?? func.toString();\n }\n /**\n * Return an updated window function over a named window definition.\n * @param {string} name The window definition name.\n * @returns {WindowFunction} A new window function.\n */\n over(name2) {\n const { window: op, func, type: type2, group: group3, order, frame: frame4 } = this;\n return new _WindowFunction(op, func, type2, name2, group3, order, frame4);\n }\n /**\n * Return an updated window function with the given partitioning.\n * @param {*} expr The grouping (partition by) criteria for the window function.\n * @returns {WindowFunction} A new window function.\n */\n partitionby(...expr) {\n const exprs = expr.flat().filter((x3) => x3).map(asColumn);\n const group3 = sql(\n [\"PARTITION BY \", repeat(exprs.length - 1, \", \"), \"\"],\n ...exprs\n );\n const { window: op, func, type: type2, name: name2, order, frame: frame4 } = this;\n return new _WindowFunction(op, func, type2, name2, group3, order, frame4);\n }\n /**\n * Return an updated window function with the given ordering.\n * @param {*} expr The sorting (order by) criteria for the window function.\n * @returns {WindowFunction} A new window function.\n */\n orderby(...expr) {\n const exprs = expr.flat().filter((x3) => x3).map(asColumn);\n const order = sql(\n [\"ORDER BY \", repeat(exprs.length - 1, \", \"), \"\"],\n ...exprs\n );\n const { window: op, func, type: type2, name: name2, group: group3, frame: frame4 } = this;\n return new _WindowFunction(op, func, type2, name2, group3, order, frame4);\n }\n /**\n * Return an updated window function with the given rows frame.\n * @param {(number|null)[] | import('./expression.js').ParamLike} expr The row-based window frame.\n * @returns {WindowFunction} A new window function.\n */\n rows(expr) {\n const frame4 = windowFrame(\"ROWS\", expr);\n const { window: op, func, type: type2, name: name2, group: group3, order } = this;\n return new _WindowFunction(op, func, type2, name2, group3, order, frame4);\n }\n /**\n * Return an updated window function with the given range frame.\n * @param {(number|null)[] | import('./expression.js').ParamLike} expr The range-based window frame.\n * @returns {WindowFunction} A new window function.\n */\n range(expr) {\n const frame4 = windowFrame(\"RANGE\", expr);\n const { window: op, func, type: type2, name: name2, group: group3, order } = this;\n return new _WindowFunction(op, func, type2, name2, group3, order, frame4);\n }\n};\nfunction windowFrame(type2, frame4) {\n if (isParamLike(frame4)) {\n const expr = sql`${frame4}`;\n expr.toString = () => `${type2} ${frameToSQL(frame4.value)}`;\n return expr;\n }\n return `${type2} ${frameToSQL(frame4)}`;\n}\nfunction frameToSQL(frame4) {\n const [prev, next] = frame4;\n const a2 = prev === 0 ? \"CURRENT ROW\" : Number.isFinite(prev) ? `${Math.abs(prev)} PRECEDING` : \"UNBOUNDED PRECEDING\";\n const b = next === 0 ? \"CURRENT ROW\" : Number.isFinite(next) ? `${Math.abs(next)} FOLLOWING` : \"UNBOUNDED FOLLOWING\";\n return `BETWEEN ${a2} AND ${b}`;\n}\nfunction winf(op, type2) {\n return (...values2) => {\n const func = functionCall(op)(...values2);\n return new WindowFunction(op, func, type2);\n };\n}\nvar row_number = winf(\"ROW_NUMBER\", \"INTEGER\");\nvar rank = winf(\"RANK\", \"INTEGER\");\nvar dense_rank = winf(\"DENSE_RANK\", \"INTEGER\");\nvar percent_rank = winf(\"PERCENT_RANK\");\nvar cume_dist = winf(\"CUME_DIST\");\nvar ntile = winf(\"NTILE\");\nvar lag = winf(\"LAG\");\nvar lead = winf(\"LEAD\");\nvar first_value = winf(\"FIRST_VALUE\");\nvar last_value = winf(\"LAST_VALUE\");\nvar nth_value = winf(\"NTH_VALUE\");\n\n// ../sql/src/aggregates.js\nfunction agg(strings, ...exprs) {\n return sql(strings, ...exprs).annotate({ aggregate: true });\n}\nvar AggregateFunction = class _AggregateFunction extends SQLExpression {\n /**\n * Create a new AggregateFunction instance.\n * @param {*} op The aggregate operation.\n * @param {*} [args] The aggregate function arguments.\n * @param {*} [type] The SQL data type to cast to.\n * @param {boolean} [isDistinct] Flag indicating if this is a distinct value aggregate.\n * @param {*} [filter] Filtering expression to apply prior to aggregation.\n */\n constructor(op, args, type2, isDistinct2, filter3) {\n args = (args || []).map(asColumn);\n const { strings, exprs } = aggExpr(op, args, type2, isDistinct2, filter3);\n const { spans, cols } = parseSQL(strings, exprs);\n super(spans, cols);\n this.aggregate = op;\n this.args = args;\n this.type = type2;\n this.isDistinct = isDistinct2;\n this.filter = filter3;\n }\n get basis() {\n return this.column;\n }\n get label() {\n const { aggregate: op, args, isDistinct: isDistinct2 } = this;\n const dist2 = isDistinct2 ? \"DISTINCT\" + (args.length ? \" \" : \"\") : \"\";\n const tail = args.length ? `(${dist2}${args.map(unquoted).join(\", \")})` : \"\";\n return `${op.toLowerCase()}${tail}`;\n }\n /**\n * Return a new derived aggregate function over distinct values.\n * @returns {AggregateFunction} A new aggregate function.\n */\n distinct() {\n const { aggregate: op, args, type: type2, filter: filter3 } = this;\n return new _AggregateFunction(op, args, type2, true, filter3);\n }\n /**\n * Return a new derived aggregate function that filters values.\n * @param {*} filter The filter expresion.\n * @returns {AggregateFunction} A new aggregate function.\n */\n where(filter3) {\n const { aggregate: op, args, type: type2, isDistinct: isDistinct2 } = this;\n return new _AggregateFunction(op, args, type2, isDistinct2, filter3);\n }\n /**\n * Return a new window function over this aggregate.\n * @returns {WindowFunction} A new aggregate function.\n */\n window() {\n const { aggregate: op, args, type: type2, isDistinct: isDistinct2 } = this;\n const func = new _AggregateFunction(op, args, null, isDistinct2);\n return new WindowFunction(op, func, type2);\n }\n /**\n * Return a window function over this aggregate with the given partitioning.\n * @param {*} expr The grouping (partition by) criteria for the window function.\n * @returns {WindowFunction} A new window function.\n */\n partitionby(...expr) {\n return this.window().partitionby(...expr);\n }\n /**\n * Return a window function over this aggregate with the given ordering.\n * @param {*} expr The sorting (order by) criteria for the window function.\n * @returns {WindowFunction} A new window function.\n */\n orderby(...expr) {\n return this.window().orderby(...expr);\n }\n /**\n * Return a window function over this aggregate with the given row frame.\n * @param {(number|null)[] | import('./expression.js').ParamLike} frame The row-based window frame.\n * @returns {WindowFunction} A new window function.\n */\n rows(frame4) {\n return this.window().rows(frame4);\n }\n /**\n * Return a window function over this aggregate with the given range frame.\n * @param {(number|null)[] | import('./expression.js').ParamLike} frame The range-based window frame.\n * @returns {WindowFunction} A new window function.\n */\n range(frame4) {\n return this.window().range(frame4);\n }\n};\nfunction aggExpr(op, args, type2, isDistinct2, filter3) {\n const close = `)${type2 ? `::${type2}` : \"\"}`;\n let strings = [`${op}(${isDistinct2 ? \"DISTINCT \" : \"\"}`];\n let exprs = [];\n if (args.length) {\n strings = strings.concat([\n ...repeat(args.length - 1, \", \"),\n `${close}${filter3 ? \" FILTER (WHERE \" : \"\"}`,\n ...filter3 ? [\")\"] : []\n ]);\n exprs = [...args, ...filter3 ? [filter3] : []];\n } else {\n strings[0] += \"*\" + close;\n }\n return { exprs, strings };\n}\nfunction unquoted(value) {\n const s2 = literalToSQL(value);\n return s2 && s2.startsWith('\"') && s2.endsWith('\"') ? s2.slice(1, -1) : s2;\n}\nfunction aggf(op, type2) {\n return (...args) => new AggregateFunction(op, args, type2);\n}\nvar count = aggf(\"COUNT\", \"INTEGER\");\nvar avg = aggf(\"AVG\");\nvar mean = aggf(\"AVG\");\nvar mad = aggf(\"MAD\");\nvar max = aggf(\"MAX\");\nvar min = aggf(\"MIN\");\nvar sum = aggf(\"SUM\", \"DOUBLE\");\nvar product = aggf(\"PRODUCT\");\nvar median = aggf(\"MEDIAN\");\nvar quantile = aggf(\"QUANTILE\");\nvar mode = aggf(\"MODE\");\nvar variance = aggf(\"VARIANCE\");\nvar stddev = aggf(\"STDDEV\");\nvar skewness = aggf(\"SKEWNESS\");\nvar kurtosis = aggf(\"KURTOSIS\");\nvar entropy = aggf(\"ENTROPY\");\nvar varPop = aggf(\"VAR_POP\");\nvar stddevPop = aggf(\"STDDEV_POP\");\nvar corr = aggf(\"CORR\");\nvar covariance = aggf(\"COVAR_SAMP\");\nvar covarPop = aggf(\"COVAR_POP\");\nvar regrIntercept = aggf(\"REGR_INTERCEPT\");\nvar regrSlope = aggf(\"REGR_SLOPE\");\nvar regrCount = aggf(\"REGR_COUNT\");\nvar regrR2 = aggf(\"REGR_R2\");\nvar regrSYY = aggf(\"REGR_SYY\");\nvar regrSXX = aggf(\"REGR_SXX\");\nvar regrSXY = aggf(\"REGR_SXY\");\nvar regrAvgX = aggf(\"REGR_AVGX\");\nvar regrAvgY = aggf(\"REGR_AVGY\");\nvar first = aggf(\"FIRST\");\nvar last = aggf(\"LAST\");\nvar argmin = aggf(\"ARG_MIN\");\nvar argmax = aggf(\"ARG_MAX\");\nvar stringAgg = aggf(\"STRING_AGG\");\nvar arrayAgg = aggf(\"ARRAY_AGG\");\n\n// ../sql/src/cast.js\nfunction cast(expr, type2) {\n const arg = asColumn(expr);\n const e = sql`CAST(${arg} AS ${type2})`;\n Object.defineProperty(e, \"label\", {\n enumerable: true,\n get() {\n return expr.label;\n }\n });\n Object.defineProperty(e, \"aggregate\", {\n enumerable: true,\n get() {\n return expr.aggregate || false;\n }\n });\n return e;\n}\nvar castDouble = (expr) => cast(expr, \"DOUBLE\");\nvar castInteger = (expr) => cast(expr, \"INTEGER\");\n\n// ../sql/src/datetime.js\nvar epoch_ms = (expr) => {\n return sql`epoch_ms(${asColumn(expr)})`;\n};\nfunction dateBin(expr, interval3, steps = 1) {\n const i = `INTERVAL ${steps} ${interval3}`;\n const d = asColumn(expr);\n return sql`TIME_BUCKET(${i}, ${d})`.annotate({ label: interval3 });\n}\nvar dateMonth = (expr) => {\n const d = asColumn(expr);\n return sql`MAKE_DATE(2012, MONTH(${d}), 1)`.annotate({ label: \"month\" });\n};\nvar dateMonthDay = (expr) => {\n const d = asColumn(expr);\n return sql`MAKE_DATE(2012, MONTH(${d}), DAY(${d}))`.annotate({ label: \"date\" });\n};\nvar dateDay2 = (expr) => {\n const d = asColumn(expr);\n return sql`MAKE_DATE(2012, 1, DAY(${d}))`.annotate({ label: \"date\" });\n};\n\n// ../sql/src/spatial.js\nvar geojson = functionCall(\"ST_AsGeoJSON\");\nvar x = functionCall(\"ST_X\");\nvar y = functionCall(\"ST_Y\");\nvar centroid = functionCall(\"ST_CENTROID\");\nvar centroidX = (geom) => x(centroid(geom));\nvar centroidY = (geom) => y(centroid(geom));\n\n// ../sql/src/Query.js\nvar Query = class _Query {\n static select(...expr) {\n return new _Query().select(...expr);\n }\n static from(...expr) {\n return new _Query().from(...expr);\n }\n static with(...expr) {\n return new _Query().with(...expr);\n }\n static union(...queries) {\n return new SetOperation(\"UNION\", queries.flat());\n }\n static unionAll(...queries) {\n return new SetOperation(\"UNION ALL\", queries.flat());\n }\n static intersect(...queries) {\n return new SetOperation(\"INTERSECT\", queries.flat());\n }\n static except(...queries) {\n return new SetOperation(\"EXCEPT\", queries.flat());\n }\n static describe(query) {\n const q = query.clone();\n const { clone, toString } = q;\n return Object.assign(q, {\n describe: true,\n clone: () => _Query.describe(clone.call(q)),\n toString: () => `DESCRIBE ${toString.call(q)}`\n });\n }\n constructor() {\n this.query = {\n with: [],\n select: [],\n from: [],\n where: [],\n groupby: [],\n having: [],\n window: [],\n qualify: [],\n orderby: []\n };\n this.cteFor = null;\n }\n clone() {\n const q = new _Query();\n q.query = { ...this.query };\n return q;\n }\n /**\n * Retrieve current WITH common table expressions (CTEs).\n * @returns {any[]}\n */\n /**\n * Add WITH common table expressions (CTEs).\n * @param {...any} expr Expressions to add.\n * @returns {this}\n */\n with(...expr) {\n const { query } = this;\n if (expr.length === 0) {\n return query.with;\n } else {\n const list2 = [];\n const add2 = (as, q) => {\n const query2 = q.clone();\n query2.cteFor = this;\n list2.push({ as, query: query2 });\n };\n expr.flat().forEach((e) => {\n if (e == null) {\n } else if (e.as && e.query) {\n add2(e.as, e.query);\n } else {\n for (const as in e) {\n add2(as, e[as]);\n }\n }\n });\n query.with = query.with.concat(list2);\n return this;\n }\n }\n /**\n * Retrieve current SELECT expressions.\n * @returns {any[]}\n */\n /**\n * Add SELECT expressions.\n * @param {...any} expr Expressions to add.\n * @returns {this}\n */\n select(...expr) {\n const { query } = this;\n if (expr.length === 0) {\n return query.select;\n } else {\n const list2 = [];\n for (const e of expr.flat()) {\n if (e == null) {\n } else if (typeof e === \"string\") {\n list2.push({ as: e, expr: asColumn(e) });\n } else if (e instanceof Ref) {\n list2.push({ as: e.column, expr: e });\n } else if (Array.isArray(e)) {\n list2.push({ as: e[0], expr: e[1] });\n } else {\n for (const as in e) {\n list2.push({ as: unquote(as), expr: asColumn(e[as]) });\n }\n }\n }\n const keys = new Set(list2.map((x3) => x3.as));\n query.select = query.select.filter((x3) => !keys.has(x3.as)).concat(list2.filter((x3) => x3.expr));\n return this;\n }\n }\n $select(...expr) {\n this.query.select = [];\n return this.select(...expr);\n }\n distinct(value = true) {\n this.query.distinct = !!value;\n return this;\n }\n /**\n * Retrieve current from expressions.\n * @returns {any[]}\n */\n /**\n * Provide table from expressions.\n * @param {...any} expr\n * @returns {this}\n */\n from(...expr) {\n const { query } = this;\n if (expr.length === 0) {\n return query.from;\n } else {\n const list2 = [];\n expr.flat().forEach((e) => {\n if (e == null) {\n } else if (typeof e === \"string\") {\n list2.push({ as: e, from: asRelation(e) });\n } else if (e instanceof Ref) {\n list2.push({ as: e.table, from: e });\n } else if (isQuery(e) || isSQLExpression(e)) {\n list2.push({ from: e });\n } else if (Array.isArray(e)) {\n list2.push({ as: unquote(e[0]), from: asRelation(e[1]) });\n } else {\n for (const as in e) {\n list2.push({ as: unquote(as), from: asRelation(e[as]) });\n }\n }\n });\n query.from = query.from.concat(list2);\n return this;\n }\n }\n $from(...expr) {\n this.query.from = [];\n return this.from(...expr);\n }\n /**\n * Retrieve current SAMPLE settings.\n * @returns {any[]}\n */\n /**\n * Set SAMPLE settings.\n * @param {number|object} value The percentage or number of rows to sample.\n * @param {string} [method] The sampling method to use.\n * @returns {this}\n */\n sample(value, method) {\n const { query } = this;\n if (arguments.length === 0) {\n return query.sample;\n } else {\n let spec = value;\n if (typeof value === \"number\") {\n spec = value > 0 && value < 1 ? { perc: 100 * value, method } : { rows: Math.round(value), method };\n }\n query.sample = spec;\n return this;\n }\n }\n /**\n * Retrieve current WHERE expressions.\n * @returns {any[]}\n */\n /**\n * Add WHERE expressions.\n * @param {...any} expr Expressions to add.\n * @returns {this}\n */\n where(...expr) {\n const { query } = this;\n if (expr.length === 0) {\n return query.where;\n } else {\n query.where = query.where.concat(\n expr.flat().filter((x3) => x3)\n );\n return this;\n }\n }\n $where(...expr) {\n this.query.where = [];\n return this.where(...expr);\n }\n /**\n * Retrieve current GROUP BY expressions.\n * @returns {any[]}\n */\n /**\n * Add GROUP BY expressions.\n * @param {...any} expr Expressions to add.\n * @returns {this}\n */\n groupby(...expr) {\n const { query } = this;\n if (expr.length === 0) {\n return query.groupby;\n } else {\n query.groupby = query.groupby.concat(\n expr.flat().filter((x3) => x3).map(asColumn)\n );\n return this;\n }\n }\n $groupby(...expr) {\n this.query.groupby = [];\n return this.groupby(...expr);\n }\n /**\n * Retrieve current HAVING expressions.\n * @returns {any[]}\n */\n /**\n * Add HAVING expressions.\n * @param {...any} expr Expressions to add.\n * @returns {this}\n */\n having(...expr) {\n const { query } = this;\n if (expr.length === 0) {\n return query.having;\n } else {\n query.having = query.having.concat(\n expr.flat().filter((x3) => x3)\n );\n return this;\n }\n }\n /**\n * Retrieve current WINDOW definitions.\n * @returns {any[]}\n */\n /**\n * Add WINDOW definitions.\n * @param {...any} expr Expressions to add.\n * @returns {this}\n */\n window(...expr) {\n const { query } = this;\n if (expr.length === 0) {\n return query.window;\n } else {\n const list2 = [];\n expr.flat().forEach((e) => {\n if (e == null) {\n } else {\n for (const as in e) {\n list2.push({ as: unquote(as), expr: e[as] });\n }\n }\n });\n query.window = query.window.concat(list2);\n return this;\n }\n }\n /**\n * Retrieve current QUALIFY expressions.\n * @returns {any[]}\n */\n /**\n * Add QUALIFY expressions.\n * @param {...any} expr Expressions to add.\n * @returns {this}\n */\n qualify(...expr) {\n const { query } = this;\n if (expr.length === 0) {\n return query.qualify;\n } else {\n query.qualify = query.qualify.concat(\n expr.flat().filter((x3) => x3)\n );\n return this;\n }\n }\n /**\n * Retrieve current ORDER BY expressions.\n * @returns {any[]}\n */\n /**\n * Add ORDER BY expressions.\n * @param {...any} expr Expressions to add.\n * @returns {this}\n */\n orderby(...expr) {\n const { query } = this;\n if (expr.length === 0) {\n return query.orderby;\n } else {\n query.orderby = query.orderby.concat(\n expr.flat().filter((x3) => x3).map(asColumn)\n );\n return this;\n }\n }\n /**\n * Retrieve current LIMIT value.\n * @returns {number|null}\n */\n /**\n * Set the query result LIMIT.\n * @param {number} value The limit value.\n * @returns {this}\n */\n limit(value) {\n const { query } = this;\n if (arguments.length === 0) {\n return query.limit;\n } else {\n query.limit = Number.isFinite(value) ? value : void 0;\n return this;\n }\n }\n /**\n * Retrieve current OFFSET value.\n * @returns {number|null}\n */\n /**\n * Set the query result OFFSET.\n * @param {number} value The offset value.\n * @returns {this}\n */\n offset(value) {\n const { query } = this;\n if (arguments.length === 0) {\n return query.offset;\n } else {\n query.offset = Number.isFinite(value) ? value : void 0;\n return this;\n }\n }\n get subqueries() {\n const { query, cteFor } = this;\n const ctes = (cteFor?.query || query).with;\n const cte = ctes?.reduce((o, { as, query: query2 }) => (o[as] = query2, o), {});\n const q = [];\n query.from.forEach(({ from: from2 }) => {\n if (isQuery(from2)) {\n q.push(from2);\n } else if (cte[from2.table]) {\n const sub = cte[from2.table];\n q.push(sub);\n }\n });\n return q;\n }\n toString() {\n const {\n with: cte,\n select: select2,\n distinct: distinct2,\n from: from2,\n sample,\n where,\n groupby,\n having,\n window: window3,\n qualify,\n orderby,\n limit,\n offset: offset2\n } = this.query;\n const sql2 = [];\n if (cte.length) {\n const list2 = cte.map(({ as, query }) => `\"${as}\" AS (${query})`);\n sql2.push(`WITH ${list2.join(\", \")}`);\n }\n const sels = select2.map(\n ({ as, expr }) => isColumnRefFor(expr, as) && !expr.table ? `${expr}` : `${expr} AS \"${as}\"`\n );\n sql2.push(`SELECT${distinct2 ? \" DISTINCT\" : \"\"} ${sels.join(\", \")}`);\n if (from2.length) {\n const rels = from2.map(({ as, from: from3 }) => {\n const rel = isQuery(from3) ? `(${from3})` : `${from3}`;\n return !as || as === from3.table ? rel : `${rel} AS \"${as}\"`;\n });\n sql2.push(`FROM ${rels.join(\", \")}`);\n }\n if (where.length) {\n const clauses = where.map(String).filter((x3) => x3).join(\" AND \");\n if (clauses) sql2.push(`WHERE ${clauses}`);\n }\n if (sample) {\n const { rows, perc, method, seed } = sample;\n const size = rows ? `${rows} ROWS` : `${perc} PERCENT`;\n const how = method ? ` (${method}${seed != null ? `, ${seed}` : \"\"})` : \"\";\n sql2.push(`USING SAMPLE ${size}${how}`);\n }\n if (groupby.length) {\n sql2.push(`GROUP BY ${groupby.join(\", \")}`);\n }\n if (having.length) {\n const clauses = having.map(String).filter((x3) => x3).join(\" AND \");\n if (clauses) sql2.push(`HAVING ${clauses}`);\n }\n if (window3.length) {\n const windows = window3.map(({ as, expr }) => `\"${as}\" AS (${expr})`);\n sql2.push(`WINDOW ${windows.join(\", \")}`);\n }\n if (qualify.length) {\n const clauses = qualify.map(String).filter((x3) => x3).join(\" AND \");\n if (clauses) sql2.push(`QUALIFY ${clauses}`);\n }\n if (orderby.length) {\n sql2.push(`ORDER BY ${orderby.join(\", \")}`);\n }\n if (Number.isFinite(limit)) {\n sql2.push(`LIMIT ${limit}`);\n }\n if (Number.isFinite(offset2)) {\n sql2.push(`OFFSET ${offset2}`);\n }\n return sql2.join(\" \");\n }\n};\nvar SetOperation = class _SetOperation {\n constructor(op, queries) {\n this.op = op;\n this.queries = queries.map((q) => q.clone());\n this.query = { orderby: [] };\n this.cteFor = null;\n }\n clone() {\n const q = new _SetOperation(this.op, this.queries);\n q.query = { ...this.query };\n return q;\n }\n orderby(...expr) {\n const { query } = this;\n if (expr.length === 0) {\n return query.orderby;\n } else {\n query.orderby = query.orderby.concat(\n expr.flat().filter((x3) => x3).map(asColumn)\n );\n return this;\n }\n }\n limit(value) {\n const { query } = this;\n if (arguments.length === 0) {\n return query.limit;\n } else {\n query.limit = Number.isFinite(value) ? value : void 0;\n return this;\n }\n }\n offset(value) {\n const { query } = this;\n if (arguments.length === 0) {\n return query.offset;\n } else {\n query.offset = Number.isFinite(value) ? value : void 0;\n return this;\n }\n }\n get subqueries() {\n const { queries, cteFor } = this;\n if (cteFor) queries.forEach((q) => q.cteFor = cteFor);\n return queries;\n }\n toString() {\n const { op, queries, query: { orderby, limit, offset: offset2 } } = this;\n const sql2 = [queries.join(` ${op} `)];\n if (orderby.length) {\n sql2.push(`ORDER BY ${orderby.join(\", \")}`);\n }\n if (Number.isFinite(limit)) {\n sql2.push(`LIMIT ${limit}`);\n }\n if (Number.isFinite(offset2)) {\n sql2.push(`OFFSET ${offset2}`);\n }\n return sql2.join(\" \");\n }\n};\nfunction isQuery(value) {\n return value instanceof Query || value instanceof SetOperation;\n}\nfunction isDescribeQuery(value) {\n return isQuery(value) && value.describe;\n}\nfunction unquote(s2) {\n return isDoubleQuoted(s2) ? s2.slice(1, -1) : s2;\n}\nfunction isDoubleQuoted(s2) {\n return s2[0] === '\"' && s2[s2.length - 1] === '\"';\n}\n\n// ../sql/src/scales.js\nvar identity = (x3) => x3;\nfunction scaleLinear() {\n return {\n apply: identity,\n invert: identity,\n sqlApply: asColumn,\n sqlInvert: identity\n };\n}\nfunction scaleLog({ base = null } = {}) {\n if (base == null || base === Math.E) {\n return {\n apply: Math.log,\n invert: Math.exp,\n sqlApply: (c4) => sql`LN(${asColumn(c4)})`,\n sqlInvert: (c4) => sql`EXP(${c4})`\n };\n } else if (base === 10) {\n return {\n apply: Math.log10,\n invert: (x3) => Math.pow(10, x3),\n sqlApply: (c4) => sql`LOG(${asColumn(c4)})`,\n sqlInvert: (c4) => sql`POW(10, ${c4})`\n };\n } else {\n const b = +base;\n return {\n apply: (x3) => Math.log(x3) / Math.log(b),\n invert: (x3) => Math.pow(b, x3),\n sqlApply: (c4) => sql`LN(${asColumn(c4)}) / LN(${b})`,\n sqlInvert: (c4) => sql`POW(${b}, ${c4})`\n };\n }\n}\nfunction scaleSymlog({ constant: constant2 = 1 } = {}) {\n const _ = +constant2;\n return {\n apply: (x3) => Math.sign(x3) * Math.log1p(Math.abs(x3)),\n invert: (x3) => Math.sign(x3) * Math.exp(Math.abs(x3) - _),\n sqlApply: (c4) => (c4 = asColumn(c4), sql`SIGN(${c4}) * LN(${_} + ABS(${c4}))`),\n sqlInvert: (c4) => sql`SIGN(${c4}) * (EXP(ABS(${c4})) - ${_})`\n };\n}\nfunction scaleSqrt() {\n return {\n apply: (x3) => Math.sign(x3) * Math.sqrt(Math.abs(x3)),\n invert: (x3) => Math.sign(x3) * x3 * x3,\n sqlApply: (c4) => (c4 = asColumn(c4), sql`SIGN(${c4}) * SQRT(ABS(${c4}))`),\n sqlInvert: (c4) => sql`SIGN(${c4}) * (${c4}) ** 2`\n };\n}\nfunction scalePow({ exponent = 1 } = {}) {\n const e = +exponent;\n return {\n apply: (x3) => Math.sign(x3) * Math.pow(Math.abs(x3), e),\n invert: (x3) => Math.sign(x3) * Math.pow(Math.abs(x3), 1 / e),\n sqlApply: (c4) => (c4 = asColumn(c4), sql`SIGN(${c4}) * POW(ABS(${c4}), ${e})`),\n sqlInvert: (c4) => sql`SIGN(${c4}) * POW(ABS(${c4}), 1/${e})`\n };\n}\nfunction scaleTime() {\n return {\n apply: (x3) => +x3,\n invert: (x3) => new Date(x3),\n sqlApply: (c4) => c4 instanceof Date ? +c4 : epoch_ms(asColumn(c4)),\n sqlInvert: identity\n };\n}\nvar scales = {\n identity: scaleLinear,\n linear: scaleLinear,\n log: scaleLog,\n symlog: scaleSymlog,\n sqrt: scaleSqrt,\n pow: scalePow,\n time: scaleTime,\n utc: scaleTime\n};\nfunction scaleTransform(options) {\n const scale3 = scales[options.type];\n return scale3 ? { ...options, ...scale3(options) } : null;\n}\n\n// ../sql/src/load/create.js\nfunction create(name2, query, {\n replace = false,\n temp = true,\n view = false\n} = {}) {\n return \"CREATE\" + (replace ? \" OR REPLACE \" : \" \") + (temp ? \"TEMP \" : \"\") + (view ? \"VIEW\" : \"TABLE\") + (replace ? \" \" : \" IF NOT EXISTS \") + name2 + \" AS \" + query;\n}\n\n// ../sql/src/load/extension.js\nfunction loadExtension(name2) {\n return `INSTALL ${name2}; LOAD ${name2}`;\n}\n\n// ../sql/src/load/sql-from.js\nfunction sqlFrom(data, {\n columns = Object.keys(data?.[0] || {})\n} = {}) {\n let keys = [];\n if (Array.isArray(columns)) {\n keys = columns;\n columns = keys.reduce((m, k2) => (m[k2] = k2, m), {});\n } else if (columns) {\n keys = Object.keys(columns);\n }\n if (!keys.length) {\n throw new Error(\"Can not create table from empty column set.\");\n }\n const subq = [];\n for (const datum2 of data) {\n const sel = keys.map((k2) => `${literalToSQL(datum2[k2])} AS \"${columns[k2]}\"`);\n subq.push(`(SELECT ${sel.join(\", \")})`);\n }\n return subq.join(\" UNION ALL \");\n}\n\n// ../sql/src/load/load.js\nfunction load(method, tableName, fileName, options = {}, defaults22 = {}) {\n const { select: select2 = [\"*\"], where, view, temp, replace, ...file } = options;\n const params = parameters({ ...defaults22, ...file });\n const read = `${method}('${fileName}'${params ? \", \" + params : \"\"})`;\n const filter3 = where ? ` WHERE ${where}` : \"\";\n const query = `SELECT ${select2.join(\", \")} FROM ${read}${filter3}`;\n return create(tableName, query, { view, temp, replace });\n}\nfunction loadCSV(tableName, fileName, options) {\n return load(\"read_csv\", tableName, fileName, options, { auto_detect: true, sample_size: -1 });\n}\nfunction loadJSON(tableName, fileName, options) {\n return load(\"read_json\", tableName, fileName, options, { auto_detect: true, json_format: \"auto\" });\n}\nfunction loadParquet(tableName, fileName, options) {\n return load(\"read_parquet\", tableName, fileName, options);\n}\nfunction loadSpatial(tableName, fileName, options = {}) {\n const { options: opt, ...rest } = options;\n if (opt) {\n const open = Array.isArray(opt) ? opt.join(\", \") : typeof opt === \"string\" ? opt : Object.entries(opt).map(([key, value]) => `${key}=${value}`).join(\", \");\n Object.assign(rest, { open_options: open.toUpperCase() });\n }\n return load(\"st_read\", tableName, fileName, rest);\n}\nfunction loadObjects(tableName, data, options = {}) {\n const { select: select2 = [\"*\"], ...opt } = options;\n const values2 = sqlFrom(data);\n const query = select2.length === 1 && select2[0] === \"*\" ? values2 : `SELECT ${select2} FROM ${values2}`;\n return create(tableName, query, opt);\n}\nfunction parameters(options) {\n return Object.entries(options).map(([key, value]) => `${key}=${toDuckDBValue(value)}`).join(\", \");\n}\nfunction toDuckDBValue(value) {\n switch (typeof value) {\n case \"boolean\":\n return String(value);\n case \"string\":\n return `'${value}'`;\n case \"undefined\":\n case \"object\":\n if (value == null) {\n return \"NULL\";\n } else if (Array.isArray(value)) {\n return \"[\" + value.map((v2) => toDuckDBValue(v2)).join(\", \") + \"]\";\n } else {\n return \"{\" + Object.entries(value).map(([k2, v2]) => `'${k2}': ${toDuckDBValue(v2)}`).join(\", \") + \"}\";\n }\n default:\n return value;\n }\n}\n\n// ../core/src/util/index-columns.js\nfunction indexColumns(client) {\n if (!client.filterIndexable) return null;\n const q = client.query();\n const from2 = getBase(q, (q2) => q2.from()?.[0].from.table);\n if (typeof from2 !== \"string\" || !q.select) return null;\n const aggr = [];\n const dims = [];\n const aux = {};\n const avg2 = (ref) => {\n const name2 = ref.column;\n const expr = getBase(q, (q2) => q2.select().find((c4) => c4.as === name2)?.expr);\n return `(SELECT AVG(${expr ?? ref}) FROM \"${from2}\")`;\n };\n for (const entry of q.select()) {\n const { as, expr: { aggregate, args } } = entry;\n const op = aggregate?.toUpperCase?.();\n switch (op) {\n case \"COUNT\":\n case \"SUM\":\n aggr.push({ [as]: agg`SUM(\"${as}\")::DOUBLE` });\n break;\n case \"AVG\":\n aggr.push({ [as]: avgExpr(aux, as, args[0]) });\n break;\n case \"ARG_MAX\":\n aggr.push({ [as]: argmaxExpr(aux, as, args) });\n break;\n case \"ARG_MIN\":\n aggr.push({ [as]: argminExpr(aux, as, args) });\n break;\n // variance statistics drop the original aggregate operation\n // in favor of tracking auxiliary sufficient statistics\n case \"VARIANCE\":\n case \"VAR_SAMP\":\n aux[as] = null;\n aggr.push({ [as]: varianceExpr(aux, args[0], avg2) });\n break;\n case \"VAR_POP\":\n aux[as] = null;\n aggr.push({ [as]: varianceExpr(aux, args[0], avg2, false) });\n break;\n case \"STDDEV\":\n case \"STDDEV_SAMP\":\n aux[as] = null;\n aggr.push({ [as]: agg`SQRT(${varianceExpr(aux, args[0], avg2)})` });\n break;\n case \"STDDEV_POP\":\n aux[as] = null;\n aggr.push({ [as]: agg`SQRT(${varianceExpr(aux, args[0], avg2, false)})` });\n break;\n case \"COVAR_SAMP\":\n aux[as] = null;\n aggr.push({ [as]: covarianceExpr(aux, args, avg2) });\n break;\n case \"COVAR_POP\":\n aux[as] = null;\n aggr.push({ [as]: covarianceExpr(aux, args, avg2, false) });\n break;\n case \"CORR\":\n aux[as] = null;\n aggr.push({ [as]: corrExpr(aux, args, avg2) });\n break;\n // regression statistics\n case \"REGR_COUNT\":\n aux[as] = null;\n aggr.push({ [as]: agg`${regrCountExpr(aux, args)}::DOUBLE` });\n break;\n case \"REGR_AVGX\":\n aux[as] = null;\n aggr.push({ [as]: regrAvgXExpr(aux, args) });\n break;\n case \"REGR_AVGY\":\n aux[as] = null;\n aggr.push({ [as]: regrAvgYExpr(aux, args) });\n break;\n case \"REGR_SYY\":\n aux[as] = null;\n aggr.push({ [as]: regrVarExpr(aux, 0, args, avg2) });\n break;\n case \"REGR_SXX\":\n aux[as] = null;\n aggr.push({ [as]: regrVarExpr(aux, 1, args, avg2) });\n break;\n case \"REGR_SXY\":\n aux[as] = null;\n aggr.push({ [as]: covarianceExpr(aux, args, avg2, null) });\n break;\n case \"REGR_SLOPE\":\n aux[as] = null;\n aggr.push({ [as]: regrSlopeExpr(aux, args, avg2) });\n break;\n case \"REGR_INTERCEPT\":\n aux[as] = null;\n aggr.push({ [as]: regrInterceptExpr(aux, args, avg2) });\n break;\n case \"REGR_R2\":\n aux[as] = null;\n aggr.push({ [as]: agg`(${corrExpr(aux, args, avg2)}) ** 2` });\n break;\n // aggregates that commute directly\n case \"MAX\":\n case \"MIN\":\n case \"BIT_AND\":\n case \"BIT_OR\":\n case \"BIT_XOR\":\n case \"BOOL_AND\":\n case \"BOOL_OR\":\n case \"PRODUCT\":\n aggr.push({ [as]: agg`${op}(\"${as}\")` });\n break;\n // otherwise, check if dimension\n default:\n if (!aggregate) dims.push(as);\n else return null;\n }\n }\n if (!aggr.length) return null;\n return { from: from2, dims, aggr, aux };\n}\nfunction auxName(type2, ...args) {\n const cols = args.length ? \"_\" + args.map(sanitize).join(\"_\") : \"\";\n return `__${type2}${cols}__`;\n}\nfunction sanitize(col) {\n return `${col}`.replaceAll('\"', \"\").replaceAll(\" \", \"_\");\n}\nfunction getBase(query, get3) {\n const subq = query.subqueries;\n if (query.select && subq.length === 0) {\n return get3(query);\n }\n const base = getBase(subq[0], get3);\n for (let i = 1; i < subq.length; ++i) {\n const value = getBase(subq[i], get3);\n if (value === void 0) continue;\n if (value !== base) return NaN;\n }\n return base;\n}\nfunction countExpr(aux, arg) {\n const n = auxName(\"count\", arg);\n aux[n] = agg`COUNT(${arg})`;\n return agg`SUM(${n})`.annotate({ name: n });\n}\nfunction avgExpr(aux, as, arg) {\n const n = countExpr(aux, arg);\n return agg`(SUM(\"${as}\" * ${n.name}) / ${n})`;\n}\nfunction argmaxExpr(aux, as, [, y3]) {\n const max4 = auxName(\"max\", y3);\n aux[max4] = agg`MAX(${y3})`;\n return agg`ARG_MAX(\"${as}\", ${max4})`;\n}\nfunction argminExpr(aux, as, [, y3]) {\n const min5 = auxName(\"min\", y3);\n aux[min5] = agg`MIN(${y3})`;\n return agg`ARG_MIN(\"${as}\", ${min5})`;\n}\nfunction varianceExpr(aux, x3, avg2, correction = true) {\n const n = countExpr(aux, x3);\n const ssq = auxName(\"rssq\", x3);\n const sum4 = auxName(\"rsum\", x3);\n const delta = sql`${x3} - ${avg2(x3)}`;\n aux[ssq] = agg`SUM((${delta}) ** 2)`;\n aux[sum4] = agg`SUM(${delta})`;\n const adj = correction ? ` - 1` : \"\";\n return agg`(SUM(${ssq}) - (SUM(${sum4}) ** 2 / ${n})) / (${n}${adj})`;\n}\nfunction covarianceExpr(aux, args, avg2, correction = true) {\n const n = regrCountExpr(aux, args);\n const sxy = regrSumXYExpr(aux, args, avg2);\n const sx = regrSumExpr(aux, 1, args, avg2);\n const sy = regrSumExpr(aux, 0, args, avg2);\n const adj = correction === null ? \"\" : correction ? ` / (${n} - 1)` : ` / ${n}`;\n return agg`(${sxy} - ${sx} * ${sy} / ${n})${adj}`;\n}\nfunction corrExpr(aux, args, avg2) {\n const n = regrCountExpr(aux, args);\n const sxy = regrSumXYExpr(aux, args, avg2);\n const sxx = regrSumSqExpr(aux, 1, args, avg2);\n const syy = regrSumSqExpr(aux, 0, args, avg2);\n const sx = regrSumExpr(aux, 1, args, avg2);\n const sy = regrSumExpr(aux, 0, args, avg2);\n const vx = agg`(${sxx} - (${sx} ** 2) / ${n})`;\n const vy = agg`(${syy} - (${sy} ** 2) / ${n})`;\n return agg`(${sxy} - ${sx} * ${sy} / ${n}) / SQRT(${vx} * ${vy})`;\n}\nfunction regrCountExpr(aux, [y3, x3]) {\n const n = auxName(\"count\", y3, x3);\n aux[n] = agg`REGR_COUNT(${y3}, ${x3})`;\n return agg`SUM(${n})`.annotate({ name: n });\n}\nfunction regrSumExpr(aux, i, args, avg2) {\n const v2 = args[i];\n const o = args[1 - i];\n const sum4 = auxName(\"rs\", v2);\n aux[sum4] = agg`SUM(${v2} - ${avg2(v2)}) FILTER (${o} IS NOT NULL)`;\n return agg`SUM(${sum4})`;\n}\nfunction regrSumSqExpr(aux, i, args, avg2) {\n const v2 = args[i];\n const u4 = args[1 - i];\n const ssq = auxName(\"rss\", v2);\n aux[ssq] = agg`SUM((${v2} - ${avg2(v2)}) ** 2) FILTER (${u4} IS NOT NULL)`;\n return agg`SUM(${ssq})`;\n}\nfunction regrSumXYExpr(aux, args, avg2) {\n const [y3, x3] = args;\n const sxy = auxName(\"sxy\", y3, x3);\n aux[sxy] = agg`SUM((${x3} - ${avg2(x3)}) * (${y3} - ${avg2(y3)}))`;\n return agg`SUM(${sxy})`;\n}\nfunction regrAvgXExpr(aux, args) {\n const [y3, x3] = args;\n const n = regrCountExpr(aux, args);\n const a2 = auxName(\"avg\", x3, y3);\n aux[a2] = agg`REGR_AVGX(${y3}, ${x3})`;\n return agg`(SUM(${a2} * ${n.name}) / ${n})`;\n}\nfunction regrAvgYExpr(aux, args) {\n const [y3, x3] = args;\n const n = regrCountExpr(aux, args);\n const a2 = auxName(\"avg\", y3, x3);\n aux[a2] = agg`REGR_AVGY(${y3}, ${x3})`;\n return agg`(SUM(${a2} * ${n.name}) / ${n})`;\n}\nfunction regrVarExpr(aux, i, args, avg2) {\n const n = regrCountExpr(aux, args);\n const sum4 = regrSumExpr(aux, i, args, avg2);\n const ssq = regrSumSqExpr(aux, i, args, avg2);\n return agg`(${ssq} - (${sum4} ** 2 / ${n}))`;\n}\nfunction regrSlopeExpr(aux, args, avg2) {\n const cov = covarianceExpr(aux, args, avg2, null);\n const varx = regrVarExpr(aux, 1, args, avg2);\n return agg`(${cov}) / ${varx}`;\n}\nfunction regrInterceptExpr(aux, args, avg2) {\n const ax = regrAvgXExpr(aux, args);\n const ay = regrAvgYExpr(aux, args);\n const m = regrSlopeExpr(aux, args, avg2);\n return agg`${ay} - (${m}) * ${ax}`;\n}\n\n// ../core/src/util/hash.js\nfunction fnv_hash(v2) {\n let a2 = 2166136261;\n for (let i = 0, n = v2.length; i < n; ++i) {\n const c4 = v2.charCodeAt(i);\n const d = c4 & 65280;\n if (d) a2 = fnv_multiply(a2 ^ d >> 8);\n a2 = fnv_multiply(a2 ^ c4 & 255);\n }\n return fnv_mix(a2);\n}\nfunction fnv_multiply(a2) {\n return a2 + (a2 << 1) + (a2 << 4) + (a2 << 7) + (a2 << 8) + (a2 << 24);\n}\nfunction fnv_mix(a2) {\n a2 += a2 << 13;\n a2 ^= a2 >>> 7;\n a2 += a2 << 3;\n a2 ^= a2 >>> 17;\n a2 += a2 << 5;\n return a2 & 4294967295;\n}\n\n// ../core/src/DataCubeIndexer.js\nvar Skip = { skip: true, result: null };\nvar DataCubeIndexer = class {\n /**\n * Create a new data cube index table manager.\n * @param {import('./Coordinator.js').Coordinator} coordinator A Mosaic coordinator.\n * @param {DataCubeIndexerOptions} [options] Data cube indexer options.\n */\n constructor(coordinator2, {\n schema = \"mosaic\",\n enabled = true\n } = {}) {\n this.indexes = /* @__PURE__ */ new Map();\n this.active = null;\n this.mc = coordinator2;\n this._schema = schema;\n this._enabled = enabled;\n }\n /**\n * Set the enabled state of this indexer. If false, any local state is\n * cleared and subsequent index calls will return null until re-enabled.\n * This method has no effect on any index tables already in the database.\n * @param {boolean} [state] The enabled state to set.\n */\n set enabled(state) {\n if (this._enabled !== state) {\n if (!state) this.clear();\n this._enabled = state;\n }\n }\n /**\n * Get the enabled state of this indexer.\n * @returns {boolean} The current enabled state.\n */\n get enabled() {\n return this._enabled;\n }\n /**\n * Set the database schema used by this indexer. Upon changes, any local\n * state is cleared. This method does _not_ drop any existing data cube\n * tables, use `dropIndexTables` before changing the schema to also remove\n * existing index tables in the database.\n * @param {string} [schema] The schema name to set.\n */\n set schema(schema) {\n if (this._schema !== schema) {\n this.clear();\n this._schema = schema;\n }\n }\n /**\n * Get the database schema used by this indexer.\n * @returns {string} The current schema name.\n */\n get schema() {\n return this._schema;\n }\n /**\n * Issues a query through the coordinator to drop the current index table\n * schema. *All* tables in the schema will be removed and local state is\n * cleared. Call this method if the underlying base tables have been updated,\n * causing derived index tables to become stale and inaccurate. Use this\n * method with care! Once dropped, the schema will be repopulated by future\n * data cube indexer requests.\n * @returns A query result promise.\n */\n dropIndexTables() {\n this.clear();\n return this.mc.exec(`DROP SCHEMA IF EXISTS \"${this.schema}\" CASCADE`);\n }\n /**\n * Clear the cache of data cube index table entries for the current active\n * selection clause. This method does _not_ drop any existing data cube\n * tables. Use `dropIndexTables` to remove existing index tables from the\n * database.\n */\n clear() {\n this.indexes.clear();\n this.active = null;\n }\n /**\n * Return data cube index table information for the active state of a\n * client-selection pair, or null if the client is not indexable. This\n * method has multiple possible side effects, including data cube table\n * generation and updating internal caches.\n * @param {import('./MosaicClient.js').MosaicClient} client A Mosaic client.\n * @param {import('./Selection.js').Selection} selection A Mosaic selection\n * to filter the client by.\n * @param {import('./util/selection-types.js').SelectionClause} activeClause\n * A representative active selection clause for which to (possibly) generate\n * data cube index tables.\n * @returns {DataCubeInfo | Skip | null} Data cube index table\n * information and query generator, or null if the client is not indexable.\n */\n index(client, selection2, activeClause) {\n if (!this.enabled) return null;\n const { indexes: indexes2, mc, schema } = this;\n const { source } = activeClause;\n if (!source) return null;\n if (this.active) {\n if (this.active.source !== source) this.clear();\n if (this.active?.source === null) return null;\n }\n let { active } = this;\n if (!active) {\n this.active = active = activeColumns(activeClause);\n if (active.source === null) return null;\n }\n if (indexes2.has(client)) {\n return indexes2.get(client);\n }\n const indexCols = indexColumns(client);\n let info;\n if (!indexCols) {\n info = null;\n } else if (selection2.skip(client, activeClause)) {\n info = Skip;\n } else {\n const filter3 = selection2.remove(source).predicate(client);\n info = dataCubeInfo(client.query(filter3), active, indexCols, schema);\n info.result = mc.exec([\n `CREATE SCHEMA IF NOT EXISTS ${schema}`,\n create(info.table, info.create, { temp: false })\n ]);\n info.result.catch((e) => mc.logger().error(e));\n }\n indexes2.set(client, info);\n return info;\n }\n};\nfunction activeColumns(clause) {\n const { source, meta } = clause;\n const clausePred = clause.predicate;\n const clauseCols = clausePred?.columns;\n let predicate;\n let columns;\n if (!meta || !clauseCols) {\n return { source: null, columns, predicate };\n }\n const { type: type2, scales: scales2, bin: bin3, pixelSize = 1 } = meta;\n if (type2 === \"point\") {\n predicate = (x3) => x3;\n columns = Object.fromEntries(\n clauseCols.map((col) => [`${col}`, asColumn(col)])\n );\n } else if (type2 === \"interval\" && scales2) {\n const bins2 = scales2.map((s2) => binInterval(s2, pixelSize, bin3));\n if (bins2.some((b) => !b)) {\n } else if (bins2.length === 1) {\n predicate = (p) => p ? isBetween(\"active0\", p.range.map(bins2[0])) : [];\n columns = { active0: bins2[0](clausePred.field) };\n } else {\n predicate = (p) => p ? and(p.children.map(\n ({ range: range3 }, i) => isBetween(`active${i}`, range3.map(bins2[i]))\n )) : [];\n columns = Object.fromEntries(\n // @ts-ignore\n clausePred.children.map((p, i) => [`active${i}`, bins2[i](p.field)])\n );\n }\n }\n return { source: columns ? source : null, columns, predicate };\n}\nvar BIN = { ceil: \"CEIL\", round: \"ROUND\" };\nfunction binInterval(scale3, pixelSize, bin3) {\n const { type: type2, domain, range: range3, apply: apply2, sqlApply } = scaleTransform(scale3);\n if (!apply2) return;\n const fn = BIN[`${bin3}`.toLowerCase()] || \"FLOOR\";\n const lo = apply2(Math.min(...domain));\n const hi = apply2(Math.max(...domain));\n const a2 = type2 === \"identity\" ? 1 : Math.abs(range3[1] - range3[0]) / (hi - lo);\n const s2 = a2 / pixelSize === 1 ? \"\" : `${a2 / pixelSize}::DOUBLE * `;\n const d = lo === 0 ? \"\" : ` - ${lo}::DOUBLE`;\n return (value) => sql`${fn}(${s2}(${sqlApply(value)}${d}))::INTEGER`;\n}\nfunction dataCubeInfo(clientQuery, active, indexCols, schema) {\n const { dims, aggr, aux } = indexCols;\n const { columns } = active;\n const query = clientQuery.select({ ...columns, ...aux }).groupby(Object.keys(columns));\n const [subq] = query.subqueries;\n if (subq) {\n const cols = Object.values(columns).flatMap((c4) => c4.columns);\n subqueryPushdown(subq, cols);\n }\n const order = query.orderby();\n query.query.orderby = [];\n const create5 = query.toString();\n const id2 = (fnv_hash(create5) >>> 0).toString(16);\n const table3 = `${schema}.cube_${id2}`;\n const select2 = Query.select(dims, aggr).from(table3).groupby(dims).orderby(order);\n return new DataCubeInfo({ id: id2, table: table3, create: create5, active, select: select2 });\n}\nfunction subqueryPushdown(query, cols) {\n const memo2 = /* @__PURE__ */ new Set();\n const pushdown = (q) => {\n if (memo2.has(q)) return;\n memo2.add(q);\n if (q.select && q.from().length) {\n q.select(cols);\n }\n q.subqueries.forEach(pushdown);\n };\n pushdown(query);\n}\nvar DataCubeInfo = class {\n /**\n * Create a new DataCubeInfo instance.\n * @param {object} options\n */\n constructor({ table: table3, create: create5, active, select: select2 } = {}) {\n this.table = table3;\n this.create = create5;\n this.result = null;\n this.active = active;\n this.select = select2;\n this.skip = false;\n }\n /**\n * Generate a data cube index table query for the given predicate.\n * @param {import('@uwdata/mosaic-sql').SQLExpression} predicate The current\n * active clause predicate.\n * @returns {Query} A data cube index table query.\n */\n query(predicate) {\n return this.select.clone().where(this.active.predicate(predicate));\n }\n};\n\n// ../core/src/util/query-result.js\nvar QueryResult = class extends Promise {\n /**\n * Create a new query result Promise.\n */\n constructor() {\n let resolve;\n let reject;\n super((r, e) => {\n resolve = r;\n reject = e;\n });\n this._resolve = resolve;\n this._reject = reject;\n }\n /**\n * Resolve the result Promise with the provided value.\n * @param {*} value The result value.\n * @returns {this}\n */\n fulfill(value) {\n this._resolve(value);\n return this;\n }\n /**\n * Rejects the result Promise with the provided error.\n * @param {*} error The error value.\n * @returns {this}\n */\n reject(error2) {\n this._reject(error2);\n return this;\n }\n};\nQueryResult.prototype.constructor = Promise;\n\n// ../core/src/QueryConsolidator.js\nfunction wait(callback) {\n const method = typeof requestAnimationFrame !== \"undefined\" ? requestAnimationFrame : typeof setImmediate !== \"undefined\" ? setImmediate : setTimeout;\n return method(callback);\n}\nfunction consolidator(enqueue, cache, record) {\n let pending = [];\n let id2 = 0;\n function run() {\n const groups2 = entryGroups(pending, cache);\n pending = [];\n id2 = 0;\n for (const group3 of groups2) {\n consolidate(group3, enqueue, record);\n processResults(group3, cache);\n }\n }\n return {\n add(entry, priority) {\n if (entry.request.type === \"arrow\") {\n id2 = id2 || wait(() => run());\n pending.push({ entry, priority, index: pending.length });\n } else {\n enqueue(entry, priority);\n }\n }\n };\n}\nfunction entryGroups(entries, cache) {\n const groups2 = [];\n const groupMap = /* @__PURE__ */ new Map();\n for (const query of entries) {\n const { entry: { request } } = query;\n const key = consolidationKey(request.query, cache);\n if (!groupMap.has(key)) {\n const list2 = [];\n groups2.push(list2);\n groupMap.set(key, list2);\n }\n groupMap.get(key).push(query);\n }\n return groups2;\n}\nfunction consolidationKey(query, cache) {\n const sql2 = `${query}`;\n if (query instanceof Query && !cache.get(sql2)) {\n if (\n // @ts-ignore\n query.orderby().length || query.where().length || // @ts-ignore\n query.qualify().length || query.having().length\n ) {\n return sql2;\n }\n const q = query.clone().$select(\"*\");\n const groupby = query.groupby();\n if (groupby.length) {\n const map5 = {};\n query.select().forEach(({ as, expr }) => map5[as] = expr);\n q.$groupby(groupby.map((e) => e instanceof Ref && map5[e.column] || e));\n } else if (query.select().some(({ expr }) => expr.aggregate)) {\n q.$groupby(\"ALL\");\n }\n return `${q}`;\n } else {\n return sql2;\n }\n}\nfunction consolidate(group3, enqueue, record) {\n if (shouldConsolidate(group3)) {\n enqueue({\n request: {\n type: \"arrow\",\n cache: false,\n record: false,\n query: group3.query = consolidatedQuery(group3, record)\n },\n result: group3.result = new QueryResult()\n });\n } else {\n for (const { entry, priority } of group3) {\n enqueue(entry, priority);\n }\n }\n}\nfunction shouldConsolidate(group3) {\n if (group3.length > 1) {\n const sql2 = `${group3[0].entry.request.query}`;\n for (let i = 1; i < group3.length; ++i) {\n if (sql2 !== `${group3[i].entry.request.query}`) {\n return true;\n }\n }\n }\n return false;\n}\nfunction consolidatedQuery(group3, record) {\n const maps = group3.maps = [];\n const fields = /* @__PURE__ */ new Map();\n for (const item of group3) {\n const { query: query2 } = item.entry.request;\n const fieldMap = [];\n maps.push(fieldMap);\n for (const { as, expr } of query2.select()) {\n const e = `${expr}`;\n if (!fields.has(e)) {\n fields.set(e, [`col${fields.size}`, expr]);\n }\n const [name2] = fields.get(e);\n fieldMap.push([name2, as]);\n }\n record(`${query2}`);\n }\n const query = group3[0].entry.request.query.clone();\n const groupby = query.groupby();\n if (groupby.length) {\n const map5 = {};\n group3.maps[0].forEach(([name2, as]) => map5[as] = name2);\n query.$groupby(groupby.map((e) => e instanceof Ref && map5[e.column] || e));\n }\n return query.$select(Array.from(fields.values()));\n}\nasync function processResults(group3, cache) {\n const { maps, query, result } = group3;\n if (!maps) return;\n let data;\n try {\n data = await result;\n } catch (err) {\n for (const { entry } of group3) {\n entry.result.reject(err);\n }\n return;\n }\n const describe = isDescribeQuery(query);\n group3.forEach(({ entry }, index2) => {\n const { request, result: result2 } = entry;\n const map5 = maps[index2];\n const extract = describe && map5 ? filterResult(data, map5) : map5 ? projectResult(data, map5) : data;\n if (request.cache) {\n cache.set(String(request.query), extract);\n }\n result2.fulfill(extract);\n });\n}\nfunction projectResult(data, map5) {\n return data.select(map5.map((x3) => x3[0]), map5.map((x3) => x3[1]));\n}\nfunction filterResult(data, map5) {\n const lookup = new Map(map5);\n const result = [];\n for (const d of data) {\n if (lookup.has(d.column_name)) {\n result.push({ ...d, column_name: lookup.get(d.column_name) });\n }\n }\n return result;\n}\n\n// ../core/src/util/cache.js\nvar requestIdle = typeof requestIdleCallback !== \"undefined\" ? requestIdleCallback : setTimeout;\nvar voidCache = () => ({\n get: () => void 0,\n set: (key, value) => value,\n clear: () => {\n }\n});\nfunction lruCache({\n max: max4 = 1e3,\n // max entries\n ttl = 3 * 60 * 60 * 1e3\n // time-to-live, default 3 hours\n} = {}) {\n let cache = /* @__PURE__ */ new Map();\n function evict() {\n const expire = performance.now() - ttl;\n let lruKey = null;\n let lruLast = Infinity;\n for (const [key, value] of cache) {\n const { last: last2 } = value;\n if (last2 < lruLast) {\n lruKey = key;\n lruLast = last2;\n }\n if (expire > last2) {\n cache.delete(key);\n }\n }\n if (lruKey) {\n cache.delete(lruKey);\n }\n }\n return {\n get(key) {\n const entry = cache.get(key);\n if (entry) {\n entry.last = performance.now();\n return entry.value;\n }\n },\n set(key, value) {\n cache.set(key, { last: performance.now(), value });\n if (cache.size > max4) requestIdle(evict);\n return value;\n },\n clear() {\n cache = /* @__PURE__ */ new Map();\n }\n };\n}\n\n// ../core/src/util/priority-queue.js\nvar PriorityQueue = class {\n /**\n * Create a new priority queue instance.\n * @param {number} ranks An integer number of rank-order priority levels.\n */\n constructor(ranks) {\n this.queue = Array.from(\n { length: ranks },\n () => ({ head: null, tail: null })\n );\n }\n /**\n * Indicate if the queue is empty.\n * @returns {boolean} true if empty, false otherwise.\n */\n isEmpty() {\n return this.queue.every((list2) => !list2.head);\n }\n /**\n * Insert an item into the queue with a given priority rank.\n * @param {*} item The item to add.\n * @param {number} rank The integer priority rank.\n * Priority ranks are integers starting at zero.\n * Lower ranks indicate higher priority.\n */\n insert(item, rank3) {\n const list2 = this.queue[rank3];\n if (!list2) {\n throw new Error(`Invalid queue priority rank: ${rank3}`);\n }\n const node = { item, next: null };\n if (list2.head === null) {\n list2.head = list2.tail = node;\n } else {\n list2.tail = list2.tail.next = node;\n }\n }\n /**\n * Remove a set of items from the queue, regardless of priority rank.\n * If a provided item is not in the queue it will be ignored.\n * @param {(item: *) => boolean} test A predicate function to test\n * if an item should be removed (true to drop, false to keep).\n */\n remove(test) {\n for (const list2 of this.queue) {\n let { head, tail } = list2;\n for (let prev = null, curr = head; curr; prev = curr, curr = curr.next) {\n if (test(curr.item)) {\n if (curr === head) {\n head = curr.next;\n } else {\n prev.next = curr.next;\n }\n if (curr === tail) tail = prev || head;\n }\n }\n list2.head = head;\n list2.tail = tail;\n }\n }\n /**\n * Remove and return the next highest priority item.\n * @returns {*} The next item in the queue,\n * or undefined if this queue is empty.\n */\n next() {\n for (const list2 of this.queue) {\n const { head } = list2;\n if (head !== null) {\n list2.head = head.next;\n if (list2.tail === head) {\n list2.tail = null;\n }\n return head.item;\n }\n }\n }\n};\n\n// ../core/src/QueryManager.js\nvar Priority = { High: 0, Normal: 1, Low: 2 };\nvar QueryManager = class {\n constructor() {\n this.queue = new PriorityQueue(3);\n this.db = null;\n this.clientCache = null;\n this._logger = null;\n this._logQueries = false;\n this.recorders = [];\n this.pending = null;\n this._consolidate = null;\n }\n next() {\n if (this.pending || this.queue.isEmpty()) return;\n const { request, result } = this.queue.next();\n this.pending = this.submit(request, result);\n this.pending.finally(() => {\n this.pending = null;\n this.next();\n });\n }\n enqueue(entry, priority = Priority.Normal) {\n this.queue.insert(entry, priority);\n this.next();\n }\n recordQuery(sql2) {\n if (this.recorders.length && sql2) {\n this.recorders.forEach((rec) => rec.add(sql2));\n }\n }\n async submit(request, result) {\n try {\n const { query, type: type2, cache = false, record = true, options } = request;\n const sql2 = query ? `${query}` : null;\n if (record) {\n this.recordQuery(sql2);\n }\n if (cache) {\n const cached = this.clientCache.get(sql2);\n if (cached) {\n this._logger.debug(\"Cache\");\n result.fulfill(cached);\n return;\n }\n }\n const t03 = performance.now();\n if (this._logQueries) {\n this._logger.debug(\"Query\", { type: type2, sql: sql2, ...options });\n }\n const data = await this.db.query({ type: type2, sql: sql2, ...options });\n if (cache) this.clientCache.set(sql2, data);\n this._logger.debug(`Request: ${(performance.now() - t03).toFixed(1)}`);\n result.fulfill(data);\n } catch (err) {\n result.reject(err);\n }\n }\n cache(value) {\n return value !== void 0 ? this.clientCache = value === true ? lruCache() : value || voidCache() : this.clientCache;\n }\n logger(value) {\n return value ? this._logger = value : this._logger;\n }\n logQueries(value) {\n return value !== void 0 ? this._logQueries = !!value : this._logQueries;\n }\n connector(connector) {\n return connector ? this.db = connector : this.db;\n }\n consolidate(flag) {\n if (flag && !this._consolidate) {\n this._consolidate = consolidator(this.enqueue.bind(this), this.clientCache, this.recordQuery.bind(this));\n } else if (!flag && this._consolidate) {\n this._consolidate = null;\n }\n }\n request(request, priority = Priority.Normal) {\n const result = new QueryResult();\n const entry = { request, result };\n if (this._consolidate) {\n this._consolidate.add(entry, priority);\n } else {\n this.enqueue(entry, priority);\n }\n return result;\n }\n cancel(requests) {\n const set3 = new Set(requests);\n if (set3.size) {\n this.queue.remove(({ result }) => {\n if (set3.has(result)) {\n result.reject(\"Canceled\");\n return true;\n }\n return false;\n });\n }\n }\n clear() {\n this.queue.remove(({ result }) => {\n result.reject(\"Cleared\");\n return true;\n });\n }\n record() {\n let state = [];\n const recorder = {\n add(query) {\n state.push(query);\n },\n reset() {\n state = [];\n },\n snapshot() {\n return state.slice();\n },\n stop() {\n this.recorders = this.recorders.filter((x3) => x3 !== recorder);\n return state;\n }\n };\n this.recorders.push(recorder);\n return recorder;\n }\n};\n\n// ../core/src/util/js-type.js\nfunction jsType(type2) {\n switch (type2) {\n case \"BIGINT\":\n case \"HUGEINT\":\n case \"INTEGER\":\n case \"SMALLINT\":\n case \"TINYINT\":\n case \"UBIGINT\":\n case \"UINTEGER\":\n case \"USMALLINT\":\n case \"UTINYINT\":\n // integers\n case \"DOUBLE\":\n case \"FLOAT\":\n case \"REAL\":\n return \"number\";\n case \"DATE\":\n case \"TIMESTAMP\":\n case \"TIMESTAMPTZ\":\n case \"TIMESTAMP WITH TIME ZONE\":\n case \"TIME\":\n case \"TIMESTAMP_NS\":\n return \"date\";\n case \"BOOLEAN\":\n return \"boolean\";\n case \"VARCHAR\":\n case \"UUID\":\n case \"JSON\":\n return \"string\";\n case \"ARRAY\":\n case \"LIST\":\n return \"array\";\n case \"BLOB\":\n case \"STRUCT\":\n case \"MAP\":\n case \"GEOMETRY\":\n return \"object\";\n default:\n if (type2.startsWith(\"DECIMAL\")) {\n return \"number\";\n } else if (type2.startsWith(\"STRUCT\") || type2.startsWith(\"MAP\")) {\n return \"object\";\n } else if (type2.endsWith(\"]\")) {\n return \"array\";\n }\n throw new Error(`Unsupported type: ${type2}`);\n }\n}\n\n// ../core/src/util/field-info.js\nvar Count = \"count\";\nvar Nulls = \"nulls\";\nvar Max = \"max\";\nvar Min = \"min\";\nvar Distinct = \"distinct\";\nvar statMap = {\n [Count]: count,\n [Distinct]: (column3) => count(column3).distinct(),\n [Max]: max,\n [Min]: min,\n [Nulls]: (column3) => count().where(isNull(column3))\n};\nfunction summarize(table3, column3, stats) {\n return Query.from(table3).select(Array.from(stats, (s2) => [s2, statMap[s2](column3)]));\n}\nasync function queryFieldInfo(mc, fields) {\n if (fields.length === 1 && `${fields[0].column}` === \"*\") {\n return getTableInfo(mc, fields[0].table);\n } else {\n return (await Promise.all(fields.map((f) => getFieldInfo(mc, f)))).filter((x3) => x3);\n }\n}\nasync function getFieldInfo(mc, { table: table3, column: column3, stats }) {\n const q = Query.from({ source: table3 }).select({ column: column3 }).groupby(column3.aggregate ? sql`ALL` : []);\n const [desc2] = Array.from(await mc.query(Query.describe(q)));\n const info = {\n table: table3,\n column: `${column3}`,\n sqlType: desc2.column_type,\n type: jsType(desc2.column_type),\n nullable: desc2.null === \"YES\"\n };\n if (!(stats?.length || stats?.size)) return info;\n const [result] = await mc.query(\n summarize(table3, column3, stats),\n { persist: true }\n );\n return Object.assign(info, result);\n}\nasync function getTableInfo(mc, table3) {\n const result = await mc.query(`DESCRIBE ${asRelation(table3)}`);\n return Array.from(result).map((desc2) => ({\n table: table3,\n column: desc2.column_name,\n sqlType: desc2.column_type,\n type: jsType(desc2.column_type),\n nullable: desc2.null === \"YES\"\n }));\n}\n\n// ../core/src/util/void-logger.js\nfunction voidLogger() {\n return {\n debug() {\n },\n info() {\n },\n log() {\n },\n warn() {\n },\n error() {\n }\n };\n}\n\n// ../core/src/Coordinator.js\nvar _instance;\nfunction coordinator(instance) {\n if (instance) {\n _instance = instance;\n } else if (_instance == null) {\n _instance = new Coordinator();\n }\n return _instance;\n}\nvar Coordinator = class {\n constructor(db = socketConnector(), {\n logger = console,\n manager = new QueryManager(),\n cache = true,\n consolidate: consolidate2 = true,\n indexes: indexes2 = {}\n } = {}) {\n this.manager = manager;\n this.manager.cache(cache);\n this.manager.consolidate(consolidate2);\n this.databaseConnector(db);\n this.logger(logger);\n this.clear();\n this.dataCubeIndexer = new DataCubeIndexer(this, indexes2);\n }\n /**\n * Clear the coordinator state.\n * @param {object} [options] Options object.\n * @param {boolean} [options.clients=true] If true, disconnect all clients.\n * @param {boolean} [options.cache=true] If true, clear the query cache.\n */\n clear({ clients = true, cache = true } = {}) {\n this.manager.clear();\n if (clients) {\n this.filterGroups?.forEach((group3) => group3.disconnect());\n this.filterGroups = /* @__PURE__ */ new Map();\n this.clients?.forEach((client) => this.disconnect(client));\n this.clients = /* @__PURE__ */ new Set();\n }\n if (cache) this.manager.cache().clear();\n }\n /**\n * Get or set the database connector.\n * @param {*} [db] The database connector to use.\n * @returns The current database connector.\n */\n databaseConnector(db) {\n return this.manager.connector(db);\n }\n /**\n * Get or set the logger.\n * @param {*} logger The logger to use.\n * @returns The current logger\n */\n logger(logger) {\n if (arguments.length) {\n this._logger = logger || voidLogger();\n this.manager.logger(this._logger);\n }\n return this._logger;\n }\n // -- Query Management ----\n /**\n * Cancel previosuly submitted query requests. These queries will be\n * canceled if they are queued but have not yet been submitted.\n * @param {QueryResult[]} requests An array\n * of query result objects, such as those returned by the `query` method.\n */\n cancel(requests) {\n this.manager.cancel(requests);\n }\n /**\n * Issue a query for which no result (return value) is needed.\n * @param {QueryType | QueryType[]} query The query or an array of queries.\n * Each query should be either a Query builder object or a SQL string.\n * @param {object} [options] An options object.\n * @param {number} [options.priority] The query priority, defaults to\n * `Priority.Normal`.\n * @returns {QueryResult} A query result\n * promise.\n */\n exec(query, { priority = Priority.Normal } = {}) {\n query = Array.isArray(query) ? query.filter((x3) => x3).join(\";\\n\") : query;\n return this.manager.request({ type: \"exec\", query }, priority);\n }\n /**\n * Issue a query to the backing database. The submitted query may be\n * consolidate with other queries and its results may be cached.\n * @param {QueryType} query The query as either a Query builder object\n * or a SQL string.\n * @param {object} [options] An options object.\n * @param {'arrow' | 'json'} [options.type] The query result format type.\n * @param {boolean} [options.cache=true] If true, cache the query result.\n * @param {number} [options.priority] The query priority, defaults to\n * `Priority.Normal`.\n * @returns {QueryResult} A query result promise.\n */\n query(query, {\n type: type2 = \"arrow\",\n cache = true,\n priority = Priority.Normal,\n ...options\n } = {}) {\n return this.manager.request({ type: type2, query, cache, options }, priority);\n }\n /**\n * Issue a query to prefetch data for later use. The query result is cached\n * for efficient future access.\n * @param {QueryType} query The query as either a Query builder object\n * or a SQL string.\n * @param {object} [options] An options object.\n * @param {'arrow' | 'json'} [options.type] The query result format type.\n * @returns {QueryResult} A query result promise.\n */\n prefetch(query, options = {}) {\n return this.query(query, { ...options, cache: true, priority: Priority.Low });\n }\n /**\n * Create a bundle of queries that can be loaded into the cache.\n *\n * @param {string} name The name of the bundle.\n * @param {[string | {sql: string}, {alias: string}]} queries The queries to save into the bundle.\n * @param {number} priority Request priority.\n * @returns {QueryResult} A query result promise.\n */\n createBundle(name2, queries, priority = Priority.Low) {\n const options = { name: name2, queries: queries.map((q) => typeof q == \"string\" ? { sql: q } : q) };\n return this.manager.request({ type: \"create-bundle\", options }, priority);\n }\n /**\n * Load a bundle into the cache.\n * @param {string} name The name of the bundle.\n * @param {number} priority Request priority.\n * @returns {QueryResult} A query result promise.\n */\n loadBundle(name2, priority = Priority.High) {\n const options = { name: name2 };\n return this.manager.request({ type: \"load-bundle\", options }, priority);\n }\n // -- Client Management ----\n /**\n * Update client data by submitting the given query and returning the\n * data (or error) to the client.\n * @param {MosaicClient} client A Mosaic client.\n * @param {QueryType} query The data query.\n * @param {number} [priority] The query priority.\n * @returns {Promise} A Promise that resolves upon completion of the update.\n */\n updateClient(client, query, priority = Priority.Normal) {\n client.queryPending();\n return this.query(query, { priority }).then(\n (data) => client.queryResult(data).update(),\n (err) => {\n this._logger.error(err);\n client.queryError(err);\n }\n ).catch((err) => this._logger.error(err));\n }\n /**\n * Issue a query request for a client. If the query is null or undefined,\n * the client is simply updated. Otherwise `updateClient` is called. As a\n * side effect, this method clears the current data cube indexer state.\n * @param {MosaicClient} client The client to update.\n * @param {QueryType | null} [query] The query to issue.\n */\n requestQuery(client, query) {\n this.dataCubeIndexer.clear();\n return query ? this.updateClient(client, query) : Promise.resolve(client.update());\n }\n /**\n * Connect a client to the coordinator.\n * @param {MosaicClient} client The Mosaic client to connect.\n */\n async connect(client) {\n const { clients } = this;\n if (clients.has(client)) {\n throw new Error(\"Client already connected.\");\n }\n clients.add(client);\n client.coordinator = this;\n this.initializeClient(client);\n connectSelection(this, client.filterBy, client);\n }\n async initializeClient(client) {\n const fields = client.fields();\n if (fields?.length) {\n client.fieldInfo(await queryFieldInfo(this, fields));\n }\n return client.requestQuery();\n }\n /**\n * Disconnect a client from the coordinator.\n * @param {MosaicClient} client The Mosaic client to disconnect.\n */\n disconnect(client) {\n const { clients, filterGroups } = this;\n if (!clients.has(client)) return;\n clients.delete(client);\n client.coordinator = null;\n const group3 = filterGroups.get(client.filterBy);\n if (group3) {\n group3.clients.delete(client);\n }\n }\n};\nfunction connectSelection(mc, selection2, client) {\n if (!selection2) return;\n let entry = mc.filterGroups.get(selection2);\n if (!entry) {\n const activate = (clause) => activateSelection(mc, selection2, clause);\n const value = () => updateSelection(mc, selection2);\n selection2.addEventListener(\"activate\", activate);\n selection2.addEventListener(\"value\", value);\n entry = {\n selection: selection2,\n clients: /* @__PURE__ */ new Set(),\n disconnect() {\n selection2.removeEventListener(\"activate\", activate);\n selection2.removeEventListener(\"value\", value);\n }\n };\n mc.filterGroups.set(selection2, entry);\n }\n entry.clients.add(client);\n}\nfunction activateSelection(mc, selection2, clause) {\n const { dataCubeIndexer, filterGroups } = mc;\n const { clients } = filterGroups.get(selection2);\n for (const client of clients) {\n dataCubeIndexer.index(client, selection2, clause);\n }\n}\nfunction updateSelection(mc, selection2) {\n const { dataCubeIndexer, filterGroups } = mc;\n const { clients } = filterGroups.get(selection2);\n const { active } = selection2;\n return Promise.allSettled(Array.from(clients, (client) => {\n const info = dataCubeIndexer.index(client, selection2, active);\n const filter3 = info ? null : selection2.predicate(client);\n if (info?.skip || !info && !filter3) return;\n const query = info?.query(active.predicate) ?? client.query(filter3);\n return mc.updateClient(client, query);\n }));\n}\n\n// ../core/src/util/AsyncDispatch.js\nvar AsyncDispatch = class {\n /**\n * Create a new asynchronous dispatcher instance.\n */\n constructor() {\n this._callbacks = /* @__PURE__ */ new Map();\n }\n /**\n * Add an event listener callback for the provided event type.\n * @param {string} type The event type.\n * @param {(value: *) => void | Promise} callback The event handler\n * callback function to add. If the callback has already been\n * added for the event type, this method has no effect.\n */\n addEventListener(type2, callback) {\n if (!this._callbacks.has(type2)) {\n this._callbacks.set(type2, {\n callbacks: /* @__PURE__ */ new Set(),\n pending: null,\n queue: new DispatchQueue()\n });\n }\n const entry = this._callbacks.get(type2);\n entry.callbacks.add(callback);\n }\n /**\n * Remove an event listener callback for the provided event type.\n * @param {string} type The event type.\n * @param {(value: *) => void | Promise} callback The event handler\n * callback function to remove.\n */\n removeEventListener(type2, callback) {\n const entry = this._callbacks.get(type2);\n if (entry) {\n entry.callbacks.delete(callback);\n }\n }\n /**\n * Lifecycle method that returns the event value to emit.\n * This default implementation simply returns the input value as-is.\n * Subclasses may override this method to implement custom transformations\n * prior to emitting an event value to all listeners.\n * @param {string} type The event type.\n * @param {*} value The event value.\n * @returns The (possibly transformed) event value to emit.\n */\n willEmit(type2, value) {\n return value;\n }\n /**\n * Lifecycle method that returns a filter function for updating the\n * queue of unemitted event values prior to enqueueing a new value.\n * This default implementation simply returns null, indicating that\n * any other unemitted event values should be dropped (that is, all\n * queued events are filtered).\n * @param {string} type The event type.\n * @param {*} value The new event value that will be enqueued.\n * @returns {(value: *) => boolean|null} A dispatch queue filter\n * function, or null if all unemitted event values should be filtered.\n */\n emitQueueFilter(type2, value) {\n return null;\n }\n /**\n * Cancel all unemitted event values for the given event type.\n * @param {string} type The event type.\n */\n cancel(type2) {\n const entry = this._callbacks.get(type2);\n entry?.queue.clear();\n }\n /**\n * Returns a promise that resolves when any pending updates complete for\n * the event of the given type currently being processed. The Promise will\n * resolve immediately if the queue for the given event type is empty.\n * @param {string} type The event type to wait for.\n * @returns {Promise} A pending event promise.\n */\n async pending(type2) {\n await this._callbacks.get(type2)?.pending;\n }\n /**\n * Emit an event value to listeners for the given event type.\n * If a previous emit has not yet resolved, the event value\n * will be queued to be emitted later.\n * The actual event value given to listeners will be the result\n * of passing the input value through the emitValue() method.\n * @param {string} type The event type.\n * @param {*} value The event value.\n */\n emit(type2, value) {\n const entry = this._callbacks.get(type2) || {};\n if (entry.pending) {\n entry.queue.enqueue(value, this.emitQueueFilter(type2, value));\n } else {\n const event = this.willEmit(type2, value);\n const { callbacks, queue } = entry;\n if (callbacks?.size) {\n const callbackValues = Array.from(callbacks, (cb) => cb(event));\n entry.pending = Promise.allSettled(callbackValues).then(() => {\n entry.pending = null;\n if (!queue.isEmpty()) {\n this.emit(type2, queue.dequeue());\n }\n });\n }\n }\n }\n};\nvar DispatchQueue = class {\n /**\n * Create a new dispatch queue instance.\n */\n constructor() {\n this.clear();\n }\n /**\n * Clear the queue state of all event values.\n */\n clear() {\n this.next = null;\n }\n /**\n * Indicate if the queue is empty.\n * @returns {boolean} True if queue is empty, false otherwise.\n */\n isEmpty() {\n return !this.next;\n }\n /**\n * Add a new value to the queue, and optionally filter the\n * current queue content in response.\n * @param {*} value The value to add.\n * @param {(value: *) => boolean} [filter] An optional filter\n * function to apply to existing queue content. If unspecified\n * or falsy, all previously queued values are removed. Otherwise,\n * the provided function is applied to all queue entries. The\n * entry is retained if the filter function returns a truthy value,\n * otherwise the entry is removed.\n */\n enqueue(value, filter3) {\n const tail = { value };\n if (filter3 && this.next) {\n let curr = this;\n while (curr.next) {\n if (filter3(curr.next.value)) {\n curr = curr.next;\n } else {\n curr.next = curr.next.next;\n }\n }\n curr.next = tail;\n } else {\n this.next = tail;\n }\n }\n /**\n * Remove and return the next queued event value.\n * @returns {*} The next event value in the queue.\n */\n dequeue() {\n const { next } = this;\n this.next = next?.next;\n return next?.value;\n }\n};\n\n// ../core/src/util/distinct.js\nfunction distinct(a2, b) {\n return a2 === b ? false : a2 instanceof Date && b instanceof Date ? +a2 !== +b : Array.isArray(a2) && Array.isArray(b) ? distinctArray(a2, b) : true;\n}\nfunction distinctArray(a2, b) {\n if (a2.length !== b.length) return true;\n for (let i = 0; i < a2.length; ++i) {\n if (a2[i] !== b[i]) return true;\n }\n return false;\n}\n\n// ../core/src/Param.js\nfunction isParam(x3) {\n return x3 instanceof Param;\n}\nvar Param = class _Param extends AsyncDispatch {\n /**\n * Create a new Param instance.\n * @param {*} value The initial value of the Param.\n */\n constructor(value) {\n super();\n this._value = value;\n }\n /**\n * Create a new Param instance with the given initial value.\n * @param {*} value The initial value of the Param.\n * @returns {Param} The new Param instance.\n */\n static value(value) {\n return new _Param(value);\n }\n /**\n * Create a new Param instance over an array of initial values,\n * which may contain nested Params.\n * @param {*} values The initial values of the Param.\n * @returns {Param} The new Param instance.\n */\n static array(values2) {\n if (values2.some((v2) => isParam(v2))) {\n const p = new _Param();\n const update2 = () => {\n p.update(values2.map((v2) => isParam(v2) ? v2.value : v2));\n };\n update2();\n values2.forEach((v2) => isParam(v2) ? v2.addEventListener(\"value\", update2) : 0);\n return p;\n }\n return new _Param(values2);\n }\n /**\n * The current value of the Param.\n */\n get value() {\n return this._value;\n }\n /**\n * Update the Param value\n * @param {*} value The new value of the Param.\n * @param {object} [options] The update options.\n * @param {boolean} [options.force] A boolean flag indicating if the Param\n * should emit a 'value' event even if the internal value is unchanged.\n * @returns {this} This Param instance.\n */\n update(value, { force } = {}) {\n const shouldEmit = distinct(this._value, value) || force;\n if (shouldEmit) {\n this.emit(\"value\", value);\n } else {\n this.cancel(\"value\");\n }\n return this;\n }\n /**\n * Upon value-typed updates, sets the current value to the input value\n * immediately prior to the event value being emitted to listeners.\n * @param {string} type The event type.\n * @param {*} value The input event value.\n * @returns {*} The input event value.\n */\n willEmit(type2, value) {\n if (type2 === \"value\") {\n this._value = value;\n }\n return value;\n }\n};\n\n// ../core/src/Selection.js\nfunction isSelection(x3) {\n return x3 instanceof Selection;\n}\nfunction create2(options, include) {\n return new Selection(\n new SelectionResolver(options),\n include ? [include].flat() : include\n );\n}\nvar Selection = class _Selection extends Param {\n /**\n * Create a new Selection instance with an\n * intersect (conjunction) resolution strategy.\n * @param {object} [options] The selection options.\n * @param {boolean} [options.cross=false] Boolean flag indicating\n * cross-filtered resolution. If true, selection clauses will not\n * be applied to the clients they are associated with.\n * @param {boolean} [options.empty=false] Boolean flag indicating if a lack\n * of clauses should correspond to an empty selection with no records. This\n * setting determines the default selection state.\n * @param {Selection|Selection[]} [options.include] Upstream selections whose\n * clauses should be included as part of the new selection. Any clauses\n * published to upstream selections will be relayed to the new selection.\n * @returns {Selection} The new Selection instance.\n */\n static intersect({ cross: cross3 = false, empty: empty4 = false, include = [] } = {}) {\n return create2({ cross: cross3, empty: empty4 }, include);\n }\n /**\n * Create a new Selection instance with a\n * union (disjunction) resolution strategy.\n * @param {object} [options] The selection options.\n * @param {boolean} [options.cross=false] Boolean flag indicating\n * cross-filtered resolution. If true, selection clauses will not\n * be applied to the clients they are associated with.\n * @param {boolean} [options.empty=false] Boolean flag indicating if a lack\n * of clauses should correspond to an empty selection with no records. This\n * setting determines the default selection state.\n * @param {Selection|Selection[]} [options.include] Upstream selections whose\n * clauses should be included as part of the new selection. Any clauses\n * published to upstream selections will be relayed to the new selection.\n * @returns {Selection} The new Selection instance.\n */\n static union({ cross: cross3 = false, empty: empty4 = false, include = [] } = {}) {\n return create2({ cross: cross3, empty: empty4, union: true }, include);\n }\n /**\n * Create a new Selection instance with a singular resolution strategy\n * that keeps only the most recent selection clause.\n * @param {object} [options] The selection options.\n * @param {boolean} [options.cross=false] Boolean flag indicating\n * cross-filtered resolution. If true, selection clauses will not\n * be applied to the clients they are associated with.\n * @param {boolean} [options.empty=false] Boolean flag indicating if a lack\n * of clauses should correspond to an empty selection with no records. This\n * setting determines the default selection state.\n * @param {Selection|Selection[]} [options.include] Upstream selections whose\n * clauses should be included as part of the new selection. Any clauses\n * published to upstream selections will be relayed to the new selection.\n * @returns {Selection} The new Selection instance.\n */\n static single({ cross: cross3 = false, empty: empty4 = false, include = [] } = {}) {\n return create2({ cross: cross3, empty: empty4, single: true }, include);\n }\n /**\n * Create a new Selection instance with a\n * cross-filtered intersect resolution strategy.\n * @param {object} [options] The selection options.\n * @param {boolean} [options.empty=false] Boolean flag indicating if a lack\n * of clauses should correspond to an empty selection with no records. This\n * setting determines the default selection state.\n * @param {Selection|Selection[]} [options.include] Upstream selections whose\n * clauses should be included as part of the new selection. Any clauses\n * published to upstream selections will be relayed to the new selection.\n * @returns {Selection} The new Selection instance.\n */\n static crossfilter({ empty: empty4 = false, include = [] } = {}) {\n return create2({ cross: true, empty: empty4 }, include);\n }\n /**\n * Create a new Selection instance.\n * @param {SelectionResolver} [resolver] The selection resolution\n * strategy to apply.\n * @param {Selection[]} [include] Upstream selections whose clauses\n * should be included as part of this selection. Any clauses published\n * to these upstream selections will be relayed to this selection.\n */\n constructor(resolver = new SelectionResolver(), include = []) {\n super([]);\n this._resolved = this._value;\n this._resolver = resolver;\n this._relay = /* @__PURE__ */ new Set();\n if (Array.isArray(include)) {\n for (const sel of include) {\n sel._relay.add(this);\n }\n }\n }\n /**\n * Create a cloned copy of this Selection instance.\n * @returns {Selection} A clone of this selection.\n */\n clone() {\n const s2 = new _Selection(this._resolver);\n s2._value = s2._resolved = this._value;\n return s2;\n }\n /**\n * Create a clone of this Selection with clauses corresponding\n * to the provided source removed.\n * @param {*} source The clause source to remove.\n * @returns {Selection} A cloned and updated Selection.\n */\n remove(source) {\n const s2 = this.clone();\n s2._value = s2._resolved = s2._resolver.resolve(this._resolved, { source });\n s2._value.active = { source };\n return s2;\n }\n /**\n * The selection clause resolver.\n */\n get resolver() {\n return this._resolver;\n }\n /**\n * Indicate if this selection has a single resolution strategy.\n */\n get single() {\n return this._resolver.single;\n }\n /**\n * The current array of selection clauses.\n */\n get clauses() {\n return super.value;\n }\n /**\n * The current active (most recently updated) selection clause.\n */\n get active() {\n return this.clauses.active;\n }\n /**\n * The value corresponding to the current active selection clause.\n * This method ensures compatibility where a normal Param is expected.\n */\n get value() {\n return this.active?.value;\n }\n /**\n * The value corresponding to a given source. Returns undefined if\n * this selection does not include a clause from this source.\n * @param {*} source The clause source to look up the value for.\n */\n valueFor(source) {\n return this.clauses.find((c4) => c4.source === source)?.value;\n }\n /**\n * Emit an activate event with the given selection clause.\n * @param {*} clause The clause repesenting the potential activation.\n */\n activate(clause) {\n this.emit(\"activate\", clause);\n this._relay.forEach((sel) => sel.activate(clause));\n }\n /**\n * Update the selection with a new selection clause.\n * @param {*} clause The selection clause to add.\n * @returns {this} This Selection instance.\n */\n update(clause) {\n this._resolved = this._resolver.resolve(this._resolved, clause, true);\n this._resolved.active = clause;\n this._relay.forEach((sel) => sel.update(clause));\n return super.update(this._resolved);\n }\n /**\n * Upon value-typed updates, sets the current clause list to the\n * input value and returns the active clause value.\n * @param {string} type The event type.\n * @param {*} value The input event value.\n * @returns {*} For value-typed events, returns the active clause\n * values. Otherwise returns the input event value as-is.\n */\n willEmit(type2, value) {\n if (type2 === \"value\") {\n this._value = value;\n return this.value;\n }\n return value;\n }\n /**\n * Upon value-typed updates, returns a dispatch queue filter function.\n * The return value depends on the selection resolution strategy.\n * @param {string} type The event type.\n * @param {*} value The new event value that will be enqueued.\n * @returns {(value: *) => boolean|null} For value-typed events,\n * returns a dispatch queue filter function. Otherwise returns null.\n */\n emitQueueFilter(type2, value) {\n return type2 === \"value\" ? this._resolver.queueFilter(value) : null;\n }\n /**\n * Indicates if a selection clause should not be applied to a given client.\n * The return value depends on the selection resolution strategy.\n * @param {*} client The selection clause.\n * @param {*} clause The client to test.\n * @returns True if the client should be skipped, false otherwise.\n */\n skip(client, clause) {\n return this._resolver.skip(client, clause);\n }\n /**\n * Return a selection query predicate for the given client.\n * @param {*} client The client whose data may be filtered.\n * @param {boolean} [noSkip=false] Disable skipping of active\n * cross-filtered sources. If set true, the source of the active\n * clause in a cross-filtered selection will not be skipped.\n * @returns {*} The query predicate for filtering client data,\n * based on the current state of this selection.\n */\n predicate(client, noSkip = false) {\n const { clauses } = this;\n const active = noSkip ? null : clauses.active;\n return this._resolver.predicate(clauses, active, client);\n }\n};\nvar SelectionResolver = class {\n /**\n * Create a new selection resolved instance.\n * @param {object} [options] The resolution strategy options.\n * @param {boolean} [options.union=false] Boolean flag to indicate a union strategy.\n * If false, an intersection strategy is used.\n * @param {boolean} [options.cross=false] Boolean flag to indicate cross-filtering.\n * @param {boolean} [options.single=false] Boolean flag to indicate single clauses only.\n * @param {boolean} [options.empty=false] Boolean flag indicating if a lack\n * of clauses should correspond to an empty selection with no records. This\n * setting determines the default selection state.\n */\n constructor({ union: union2, cross: cross3, single, empty: empty4 } = {}) {\n this.union = !!union2;\n this.cross = !!cross3;\n this.single = !!single;\n this.empty = !!empty4;\n }\n /**\n * Resolve a list of selection clauses according to the resolution strategy.\n * @param {*[]} clauseList An array of selection clauses.\n * @param {*} clause A new selection clause to add.\n * @returns {*[]} An updated array of selection clauses.\n */\n resolve(clauseList, clause, reset = false) {\n const { source, predicate } = clause;\n const filtered = clauseList.filter((c4) => source !== c4.source);\n const clauses = this.single ? [] : filtered;\n if (this.single && reset) filtered.forEach((c4) => c4.source?.reset?.());\n if (predicate) clauses.push(clause);\n return clauses;\n }\n /**\n * Indicates if a selection clause should not be applied to a given client.\n * The return value depends on the resolution strategy.\n * @param {*} client The selection clause.\n * @param {*} clause The client to test.\n * @returns True if the client should be skipped, false otherwise.\n */\n skip(client, clause) {\n return this.cross && clause?.clients?.has(client);\n }\n /**\n * Return a selection query predicate for the given client.\n * @param {*[]} clauseList An array of selection clauses.\n * @param {*} active The current active selection clause.\n * @param {*} client The client whose data may be filtered.\n * @returns {*} The query predicate for filtering client data,\n * based on the current state of this selection.\n */\n predicate(clauseList, active, client) {\n const { empty: empty4, union: union2 } = this;\n if (empty4 && !clauseList.length) {\n return [\"FALSE\"];\n }\n if (this.skip(client, active)) return void 0;\n const predicates = clauseList.filter((clause) => !this.skip(client, clause)).map((clause) => clause.predicate);\n return union2 && predicates.length > 1 ? or(predicates) : predicates;\n }\n /**\n * Returns a filter function for queued selection updates.\n * @param {*} value The new event value that will be enqueued.\n * @returns {(value: *) => boolean|null} A dispatch queue filter\n * function, or null if all unemitted event values should be filtered.\n */\n queueFilter(value) {\n if (this.cross) {\n const source = value.active?.source;\n return (clauses) => clauses.active?.source !== source;\n }\n return null;\n }\n};\n\n// ../core/src/SelectionClause.js\nfunction clausePoint(field3, value, {\n source,\n clients = source ? /* @__PURE__ */ new Set([source]) : void 0\n}) {\n const predicate = value !== void 0 ? isNotDistinct(field3, literal(value)) : null;\n return {\n meta: { type: \"point\" },\n source,\n clients,\n value,\n predicate\n };\n}\nfunction clausePoints(fields, value, {\n source,\n clients = source ? /* @__PURE__ */ new Set([source]) : void 0\n}) {\n let predicate = null;\n if (value) {\n const clauses = value.map((vals) => {\n const list2 = vals.map((v2, i) => isNotDistinct(fields[i], literal(v2)));\n return list2.length > 1 ? and(list2) : list2[0];\n });\n predicate = clauses.length > 1 ? or(clauses) : clauses[0];\n }\n return {\n meta: { type: \"point\" },\n source,\n clients,\n value,\n predicate\n };\n}\nfunction clauseInterval(field3, value, {\n source,\n clients = source ? /* @__PURE__ */ new Set([source]) : void 0,\n bin: bin3,\n scale: scale3,\n pixelSize = 1\n}) {\n const predicate = value != null ? isBetween(field3, value) : null;\n const meta = { type: \"interval\", scales: scale3 && [scale3], bin: bin3, pixelSize };\n return { meta, source, clients, value, predicate };\n}\nfunction clauseIntervals(fields, value, {\n source,\n clients = source ? /* @__PURE__ */ new Set([source]) : void 0,\n bin: bin3,\n scales: scales2 = [],\n pixelSize = 1\n}) {\n const predicate = value != null ? and(fields.map((f, i) => isBetween(f, value[i]))) : null;\n const meta = { type: \"interval\", scales: scales2, bin: bin3, pixelSize };\n return { meta, source, clients, value, predicate };\n}\nvar MATCH_METHODS = { contains, prefix, suffix, regexp: regexp_matches };\nfunction clauseMatch(field3, value, {\n source,\n clients = void 0,\n method = \"contains\"\n}) {\n let fn = MATCH_METHODS[method];\n const predicate = value ? fn(field3, literal(value)) : null;\n const meta = { type: \"match\", method };\n return { meta, source, clients, value, predicate };\n}\n\n// ../core/src/util/is-arrow-table.js\nfunction isArrowTable(values2) {\n return typeof values2?.getChild === \"function\";\n}\n\n// ../core/src/util/synchronizer.js\nfunction synchronizer() {\n const set3 = /* @__PURE__ */ new Set();\n let done;\n let promise = new Promise((resolve) => done = resolve);\n return {\n /**\n * Mark an item as pending.\n * @param {*} item An item to synchronize on.\n */\n pending(item) {\n set3.add(item);\n },\n /**\n * Mark a pending item as ready, indicating it is\n * ready for a synchronized update.\n * @param {*} item An item to synchronize on.\n * @returns {boolean} True if the synchronizer is ready to\n * resolve, false otherwise.\n */\n ready(item) {\n set3.delete(item);\n return set3.size === 0;\n },\n /**\n * Resolve the current synchronization cycle, causing the synchronize\n * promise to resolve and thereby trigger downstream updates.\n */\n resolve() {\n promise = new Promise((resolve) => {\n done();\n done = resolve;\n });\n },\n /**\n * The promise for the current synchronization cycle.\n * @return {Promise} The synchronization promise.\n */\n get promise() {\n return promise;\n }\n };\n}\n\n// ../core/src/util/to-data-columns.js\nfunction toDataColumns(data) {\n return isArrowTable(data) ? arrowToColumns(data) : arrayToColumns(data);\n}\nfunction arrowToColumns(data) {\n const { numRows } = data;\n return { numRows, columns: data.toColumns() };\n}\nfunction arrayToColumns(data) {\n const numRows = data.length;\n if (typeof data[0] === \"object\") {\n const names = numRows ? Object.keys(data[0]) : [];\n const columns = {};\n if (names.length > 0) {\n names.forEach((name2) => {\n columns[name2] = data.map((d) => d[name2]);\n });\n }\n return { numRows, columns };\n } else {\n return { numRows, values: data };\n }\n}\n\n// ../vgplot/src/api.js\nvar api_exports = {};\n__export(api_exports, {\n Fixed: () => Fixed,\n Param: () => Param,\n Query: () => Query,\n Selection: () => Selection,\n agg: () => agg,\n align: () => align2,\n and: () => and,\n area: () => area2,\n areaX: () => areaX2,\n areaY: () => areaY2,\n argmax: () => argmax,\n argmin: () => argmin,\n arrayAgg: () => arrayAgg,\n arrow: () => arrow2,\n aspectRatio: () => aspectRatio,\n avg: () => avg,\n axis: () => axis2,\n axisFx: () => axisFx2,\n axisFy: () => axisFy2,\n axisX: () => axisX2,\n axisY: () => axisY2,\n barX: () => barX2,\n barY: () => barY2,\n bin: () => bin2,\n cast: () => cast,\n castDouble: () => castDouble,\n castInteger: () => castInteger,\n cell: () => cell2,\n cellX: () => cellX2,\n cellY: () => cellY2,\n centroid: () => centroid,\n centroidX: () => centroidX,\n centroidY: () => centroidY,\n circle: () => circle2,\n colorBase: () => colorBase,\n colorClamp: () => colorClamp,\n colorConstant: () => colorConstant2,\n colorDomain: () => colorDomain,\n colorExponent: () => colorExponent,\n colorInterpolate: () => colorInterpolate,\n colorLabel: () => colorLabel,\n colorLegend: () => colorLegend,\n colorN: () => colorN,\n colorNice: () => colorNice,\n colorPercent: () => colorPercent,\n colorPivot: () => colorPivot,\n colorRange: () => colorRange,\n colorReverse: () => colorReverse,\n colorScale: () => colorScale2,\n colorScheme: () => colorScheme2,\n colorSymmetric: () => colorSymmetric,\n colorTickFormat: () => colorTickFormat,\n colorZero: () => colorZero,\n column: () => column,\n contour: () => contour2,\n coordinator: () => coordinator,\n corr: () => corr,\n count: () => count,\n covarPop: () => covarPop,\n covariance: () => covariance,\n create: () => create,\n cume_dist: () => cume_dist,\n dateDay: () => dateDay2,\n dateMonth: () => dateMonth,\n dateMonthDay: () => dateMonthDay,\n delaunayLink: () => delaunayLink2,\n delaunayMesh: () => delaunayMesh2,\n denseLine: () => denseLine,\n dense_rank: () => dense_rank,\n density: () => density2,\n densityX: () => densityX,\n densityY: () => densityY,\n dot: () => dot2,\n dotX: () => dotX2,\n dotY: () => dotY2,\n entropy: () => entropy,\n eq: () => eq,\n errorbarX: () => errorbarX,\n errorbarY: () => errorbarY,\n facetGrid: () => facetGrid,\n facetLabel: () => facetLabel,\n facetMargin: () => facetMargin,\n facetMarginBottom: () => facetMarginBottom,\n facetMarginLeft: () => facetMarginLeft,\n facetMarginRight: () => facetMarginRight,\n facetMarginTop: () => facetMarginTop,\n first: () => first,\n first_value: () => first_value,\n frame: () => frame3,\n from: () => from,\n fxAlign: () => fxAlign,\n fxAriaDescription: () => fxAriaDescription,\n fxAriaLabel: () => fxAriaLabel,\n fxAxis: () => fxAxis,\n fxDomain: () => fxDomain,\n fxFontVariant: () => fxFontVariant,\n fxGrid: () => fxGrid,\n fxInset: () => fxInset,\n fxInsetLeft: () => fxInsetLeft,\n fxInsetRight: () => fxInsetRight,\n fxLabel: () => fxLabel,\n fxLabelAnchor: () => fxLabelAnchor,\n fxLabelOffset: () => fxLabelOffset,\n fxLine: () => fxLine,\n fxPadding: () => fxPadding,\n fxPaddingInner: () => fxPaddingInner,\n fxPaddingOuter: () => fxPaddingOuter,\n fxRange: () => fxRange,\n fxReverse: () => fxReverse,\n fxRound: () => fxRound,\n fxTickFormat: () => fxTickFormat,\n fxTickPadding: () => fxTickPadding,\n fxTickRotate: () => fxTickRotate,\n fxTickSize: () => fxTickSize,\n fxTickSpacing: () => fxTickSpacing,\n fxTicks: () => fxTicks,\n fyAlign: () => fyAlign,\n fyAriaDescription: () => fyAriaDescription,\n fyAriaLabel: () => fyAriaLabel,\n fyAxis: () => fyAxis,\n fyDomain: () => fyDomain,\n fyFontVariant: () => fyFontVariant,\n fyGrid: () => fyGrid,\n fyInset: () => fyInset,\n fyInsetBottom: () => fyInsetBottom,\n fyInsetTop: () => fyInsetTop,\n fyLabel: () => fyLabel,\n fyLabelAnchor: () => fyLabelAnchor,\n fyLabelOffset: () => fyLabelOffset,\n fyLine: () => fyLine,\n fyPadding: () => fyPadding,\n fyPaddingInner: () => fyPaddingInner,\n fyPaddingOuter: () => fyPaddingOuter,\n fyRange: () => fyRange,\n fyReverse: () => fyReverse,\n fyRound: () => fyRound,\n fyTickFormat: () => fyTickFormat,\n fyTickPadding: () => fyTickPadding,\n fyTickRotate: () => fyTickRotate,\n fyTickSize: () => fyTickSize,\n fyTickSpacing: () => fyTickSpacing,\n fyTicks: () => fyTicks,\n geo: () => geo2,\n geojson: () => geojson,\n graticule: () => graticule3,\n grid: () => grid,\n gridFx: () => gridFx2,\n gridFy: () => gridFy2,\n gridX: () => gridX2,\n gridY: () => gridY2,\n gt: () => gt,\n gte: () => gte,\n hconcat: () => hconcat,\n heatmap: () => heatmap,\n height: () => height,\n hexagon: () => hexagon2,\n hexbin: () => hexbin2,\n hexgrid: () => hexgrid2,\n highlight: () => highlight,\n hspace: () => hspace,\n hull: () => hull2,\n image: () => image2,\n inset: () => inset,\n intervalX: () => intervalX,\n intervalXY: () => intervalXY,\n intervalY: () => intervalY,\n isBetween: () => isBetween,\n isDistinct: () => isDistinct,\n isNotBetween: () => isNotBetween,\n isNotDistinct: () => isNotDistinct,\n isNotNull: () => isNotNull,\n isNull: () => isNull,\n kurtosis: () => kurtosis,\n label: () => label,\n lag: () => lag,\n last: () => last,\n last_value: () => last_value,\n lead: () => lead,\n lengthBase: () => lengthBase,\n lengthClamp: () => lengthClamp,\n lengthConstant: () => lengthConstant,\n lengthDomain: () => lengthDomain,\n lengthExponent: () => lengthExponent,\n lengthNice: () => lengthNice,\n lengthPercent: () => lengthPercent,\n lengthRange: () => lengthRange,\n lengthScale: () => lengthScale,\n lengthZero: () => lengthZero,\n line: () => line2,\n lineX: () => lineX2,\n lineY: () => lineY2,\n link: () => link3,\n literal: () => literal,\n loadCSV: () => loadCSV,\n loadExtension: () => loadExtension,\n loadJSON: () => loadJSON,\n loadObjects: () => loadObjects,\n loadParquet: () => loadParquet,\n loadSpatial: () => loadSpatial,\n lt: () => lt,\n lte: () => lte,\n mad: () => mad,\n margin: () => margin,\n marginBottom: () => marginBottom,\n marginLeft: () => marginLeft,\n marginRight: () => marginRight,\n marginTop: () => marginTop,\n margins: () => margins,\n max: () => max,\n median: () => median,\n menu: () => menu2,\n min: () => min,\n mode: () => mode,\n name: () => name,\n nearest: () => nearest,\n nearestX: () => nearestX,\n nearestY: () => nearestY,\n neq: () => neq,\n not: () => not,\n nth_value: () => nth_value,\n ntile: () => ntile,\n opacityBase: () => opacityBase,\n opacityClamp: () => opacityClamp,\n opacityConstant: () => opacityConstant,\n opacityDomain: () => opacityDomain,\n opacityExponent: () => opacityExponent,\n opacityLabel: () => opacityLabel,\n opacityLegend: () => opacityLegend,\n opacityNice: () => opacityNice,\n opacityPercent: () => opacityPercent,\n opacityRange: () => opacityRange,\n opacityReverse: () => opacityReverse,\n opacityScale: () => opacityScale,\n opacityTickFormat: () => opacityTickFormat,\n opacityZero: () => opacityZero,\n or: () => or,\n padding: () => padding,\n pan: () => pan,\n panX: () => panX,\n panY: () => panY,\n panZoom: () => panZoom,\n panZoomX: () => panZoomX,\n panZoomY: () => panZoomY,\n percent_rank: () => percent_rank,\n plot: () => plot2,\n product: () => product,\n projectionClip: () => projectionClip,\n projectionDomain: () => projectionDomain,\n projectionInset: () => projectionInset,\n projectionInsetBottom: () => projectionInsetBottom,\n projectionInsetLeft: () => projectionInsetLeft,\n projectionInsetRight: () => projectionInsetRight,\n projectionInsetTop: () => projectionInsetTop,\n projectionParallels: () => projectionParallels,\n projectionPrecision: () => projectionPrecision,\n projectionRotate: () => projectionRotate,\n projectionType: () => projectionType,\n quantile: () => quantile,\n rBase: () => rBase,\n rClamp: () => rClamp,\n rConstant: () => rConstant,\n rDomain: () => rDomain,\n rExponent: () => rExponent,\n rLabel: () => rLabel,\n rNice: () => rNice,\n rPercent: () => rPercent,\n rRange: () => rRange,\n rScale: () => rScale,\n rZero: () => rZero,\n rank: () => rank,\n raster: () => raster2,\n rasterTile: () => rasterTile,\n rect: () => rect2,\n rectX: () => rectX2,\n rectY: () => rectY2,\n regressionY: () => regressionY,\n row_number: () => row_number,\n ruleX: () => ruleX2,\n ruleY: () => ruleY2,\n search: () => search2,\n skewness: () => skewness,\n slider: () => slider2,\n sphere: () => sphere2,\n spike: () => spike2,\n sql: () => sql,\n stddev: () => stddev,\n stddevPop: () => stddevPop,\n stringAgg: () => stringAgg,\n style: () => style,\n sum: () => sum,\n symbolDomain: () => symbolDomain,\n symbolLegend: () => symbolLegend,\n symbolRange: () => symbolRange,\n symbolScale: () => symbolScale,\n table: () => table2,\n text: () => text2,\n textX: () => textX2,\n textY: () => textY2,\n tickX: () => tickX2,\n tickY: () => tickY2,\n toggle: () => toggle,\n toggleColor: () => toggleColor,\n toggleX: () => toggleX,\n toggleY: () => toggleY,\n toggleZ: () => toggleZ,\n varPop: () => varPop,\n variance: () => variance,\n vconcat: () => vconcat,\n vector: () => vector2,\n vectorX: () => vectorX2,\n vectorY: () => vectorY2,\n voronoi: () => voronoi2,\n voronoiMesh: () => voronoiMesh2,\n vspace: () => vspace,\n width: () => width,\n xAlign: () => xAlign,\n xAriaDescription: () => xAriaDescription,\n xAriaLabel: () => xAriaLabel,\n xAxis: () => xAxis,\n xBase: () => xBase,\n xClamp: () => xClamp,\n xConstant: () => xConstant,\n xDomain: () => xDomain,\n xExponent: () => xExponent,\n xFontVariant: () => xFontVariant,\n xGrid: () => xGrid,\n xInset: () => xInset,\n xInsetLeft: () => xInsetLeft,\n xInsetRight: () => xInsetRight,\n xLabel: () => xLabel,\n xLabelAnchor: () => xLabelAnchor,\n xLabelArrow: () => xLabelArrow,\n xLabelOffset: () => xLabelOffset,\n xLine: () => xLine,\n xNice: () => xNice,\n xPadding: () => xPadding,\n xPaddingInner: () => xPaddingInner,\n xPaddingOuter: () => xPaddingOuter,\n xPercent: () => xPercent,\n xRange: () => xRange,\n xReverse: () => xReverse,\n xRound: () => xRound,\n xScale: () => xScale,\n xTickFormat: () => xTickFormat,\n xTickPadding: () => xTickPadding,\n xTickRotate: () => xTickRotate,\n xTickSize: () => xTickSize,\n xTickSpacing: () => xTickSpacing,\n xTicks: () => xTicks,\n xZero: () => xZero,\n xyDomain: () => xyDomain,\n yAlign: () => yAlign,\n yAriaDescription: () => yAriaDescription,\n yAriaLabel: () => yAriaLabel,\n yAxis: () => yAxis,\n yBase: () => yBase,\n yClamp: () => yClamp,\n yConstant: () => yConstant,\n yDomain: () => yDomain,\n yExponent: () => yExponent,\n yFontVariant: () => yFontVariant,\n yGrid: () => yGrid,\n yInset: () => yInset,\n yInsetBottom: () => yInsetBottom,\n yInsetTop: () => yInsetTop,\n yLabel: () => yLabel,\n yLabelAnchor: () => yLabelAnchor,\n yLabelArrow: () => yLabelArrow,\n yLabelOffset: () => yLabelOffset,\n yLine: () => yLine,\n yNice: () => yNice,\n yPadding: () => yPadding,\n yPaddingInner: () => yPaddingInner,\n yPaddingOuter: () => yPaddingOuter,\n yPercent: () => yPercent,\n yRange: () => yRange,\n yReverse: () => yReverse,\n yRound: () => yRound,\n yScale: () => yScale,\n yTickFormat: () => yTickFormat,\n yTickPadding: () => yTickPadding,\n yTickRotate: () => yTickRotate,\n yTickSize: () => yTickSize,\n yTickSpacing: () => yTickSpacing,\n yTicks: () => yTicks,\n yZero: () => yZero\n});\n\n// ../plot/src/symbols.js\nvar Fixed = Symbol(\"Fixed\");\nvar Transient = Symbol(\"Transient\");\nvar Transform = Symbol(\"Transform\");\n\n// ../../node_modules/@observablehq/plot/src/index.js\nvar src_exports = {};\n__export(src_exports, {\n Area: () => Area,\n Arrow: () => Arrow,\n BarX: () => BarX,\n BarY: () => BarY,\n Cell: () => Cell,\n Contour: () => Contour,\n Density: () => Density,\n Dot: () => Dot,\n Frame: () => Frame,\n Geo: () => Geo,\n Hexgrid: () => Hexgrid,\n Image: () => Image,\n Line: () => Line,\n Link: () => Link,\n Mark: () => Mark,\n Raster: () => Raster,\n Rect: () => Rect,\n RuleX: () => RuleX,\n RuleY: () => RuleY,\n Text: () => Text,\n TickX: () => TickX,\n TickY: () => TickY,\n Tip: () => Tip,\n Vector: () => Vector,\n WaffleX: () => WaffleX,\n WaffleY: () => WaffleY,\n area: () => area,\n areaX: () => areaX,\n areaY: () => areaY,\n arrow: () => arrow,\n auto: () => auto,\n autoSpec: () => autoSpec,\n axisFx: () => axisFx,\n axisFy: () => axisFy,\n axisX: () => axisX,\n axisY: () => axisY,\n barX: () => barX,\n barY: () => barY,\n bin: () => bin,\n binX: () => binX,\n binY: () => binY,\n bollinger: () => bollinger,\n bollingerX: () => bollingerX,\n bollingerY: () => bollingerY,\n boxX: () => boxX,\n boxY: () => boxY,\n cell: () => cell,\n cellX: () => cellX,\n cellY: () => cellY,\n centroid: () => centroid2,\n circle: () => circle,\n cluster: () => cluster,\n column: () => column2,\n contour: () => contour,\n crosshair: () => crosshair,\n crosshairX: () => crosshairX,\n crosshairY: () => crosshairY,\n delaunayLink: () => delaunayLink,\n delaunayMesh: () => delaunayMesh,\n density: () => density,\n differenceX: () => differenceX,\n differenceY: () => differenceY,\n dodgeX: () => dodgeX,\n dodgeY: () => dodgeY,\n dot: () => dot,\n dotX: () => dotX,\n dotY: () => dotY,\n filter: () => filter2,\n find: () => find2,\n formatIsoDate: () => formatIsoDate,\n formatMonth: () => formatMonth,\n formatNumber: () => formatNumber,\n formatWeekday: () => formatWeekday,\n frame: () => frame2,\n geo: () => geo,\n geoCentroid: () => geoCentroid,\n graticule: () => graticule2,\n gridFx: () => gridFx,\n gridFy: () => gridFy,\n gridX: () => gridX,\n gridY: () => gridY,\n group: () => group2,\n groupX: () => groupX,\n groupY: () => groupY,\n groupZ: () => groupZ,\n hexagon: () => hexagon,\n hexbin: () => hexbin,\n hexgrid: () => hexgrid,\n hull: () => hull,\n identity: () => identity7,\n image: () => image,\n indexOf: () => indexOf,\n initializer: () => initializer,\n interpolateNearest: () => interpolateNearest,\n interpolateNone: () => interpolateNone,\n interpolatorBarycentric: () => interpolatorBarycentric,\n interpolatorRandomWalk: () => interpolatorRandomWalk,\n legend: () => legend,\n line: () => line,\n lineX: () => lineX,\n lineY: () => lineY,\n linearRegressionX: () => linearRegressionX,\n linearRegressionY: () => linearRegressionY,\n link: () => link2,\n map: () => map4,\n mapX: () => mapX,\n mapY: () => mapY,\n marks: () => marks,\n normalize: () => normalize3,\n normalizeX: () => normalizeX,\n normalizeY: () => normalizeY,\n numberInterval: () => numberInterval,\n plot: () => plot,\n pointer: () => pointer,\n pointerX: () => pointerX,\n pointerY: () => pointerY,\n raster: () => raster,\n rect: () => rect,\n rectX: () => rectX,\n rectY: () => rectY,\n reverse: () => reverse2,\n ruleX: () => ruleX,\n ruleY: () => ruleY,\n scale: () => scale2,\n select: () => select,\n selectFirst: () => selectFirst,\n selectLast: () => selectLast,\n selectMaxX: () => selectMaxX,\n selectMaxY: () => selectMaxY,\n selectMinX: () => selectMinX,\n selectMinY: () => selectMinY,\n shiftX: () => shiftX,\n shiftY: () => shiftY,\n shuffle: () => shuffle,\n sort: () => sort2,\n sphere: () => sphere,\n spike: () => spike,\n stackX: () => stackX,\n stackX1: () => stackX1,\n stackX2: () => stackX2,\n stackY: () => stackY,\n stackY1: () => stackY1,\n stackY2: () => stackY2,\n text: () => text,\n textX: () => textX,\n textY: () => textY,\n tickX: () => tickX,\n tickY: () => tickY,\n timeInterval: () => timeInterval2,\n tip: () => tip,\n transform: () => basic,\n tree: () => tree,\n treeLink: () => treeLink,\n treeNode: () => treeNode,\n utcInterval: () => utcInterval,\n valueof: () => valueof,\n vector: () => vector,\n vectorX: () => vectorX,\n vectorY: () => vectorY,\n voronoi: () => voronoi,\n voronoiMesh: () => voronoiMesh,\n waffleX: () => waffleX,\n waffleY: () => waffleY,\n window: () => window2,\n windowX: () => windowX,\n windowY: () => windowY\n});\n\n// ../../node_modules/d3-array/src/ascending.js\nfunction ascending(a2, b) {\n return a2 == null || b == null ? NaN : a2 < b ? -1 : a2 > b ? 1 : a2 >= b ? 0 : NaN;\n}\n\n// ../../node_modules/d3-array/src/descending.js\nfunction descending(a2, b) {\n return a2 == null || b == null ? NaN : b < a2 ? -1 : b > a2 ? 1 : b >= a2 ? 0 : NaN;\n}\n\n// ../../node_modules/d3-array/src/bisector.js\nfunction bisector(f) {\n let compare1, compare2, delta;\n if (f.length !== 2) {\n compare1 = ascending;\n compare2 = (d, x3) => ascending(f(d), x3);\n delta = (d, x3) => f(d) - x3;\n } else {\n compare1 = f === ascending || f === descending ? f : zero;\n compare2 = f;\n delta = f;\n }\n function left2(a2, x3, lo = 0, hi = a2.length) {\n if (lo < hi) {\n if (compare1(x3, x3) !== 0) return hi;\n do {\n const mid2 = lo + hi >>> 1;\n if (compare2(a2[mid2], x3) < 0) lo = mid2 + 1;\n else hi = mid2;\n } while (lo < hi);\n }\n return lo;\n }\n function right2(a2, x3, lo = 0, hi = a2.length) {\n if (lo < hi) {\n if (compare1(x3, x3) !== 0) return hi;\n do {\n const mid2 = lo + hi >>> 1;\n if (compare2(a2[mid2], x3) <= 0) lo = mid2 + 1;\n else hi = mid2;\n } while (lo < hi);\n }\n return lo;\n }\n function center2(a2, x3, lo = 0, hi = a2.length) {\n const i = left2(a2, x3, lo, hi - 1);\n return i > lo && delta(a2[i - 1], x3) > -delta(a2[i], x3) ? i - 1 : i;\n }\n return { left: left2, center: center2, right: right2 };\n}\nfunction zero() {\n return 0;\n}\n\n// ../../node_modules/d3-array/src/number.js\nfunction number(x3) {\n return x3 === null ? NaN : +x3;\n}\nfunction* numbers(values2, valueof2) {\n if (valueof2 === void 0) {\n for (let value of values2) {\n if (value != null && (value = +value) >= value) {\n yield value;\n }\n }\n } else {\n let index2 = -1;\n for (let value of values2) {\n if ((value = valueof2(value, ++index2, values2)) != null && (value = +value) >= value) {\n yield value;\n }\n }\n }\n}\n\n// ../../node_modules/d3-array/src/bisect.js\nvar ascendingBisect = bisector(ascending);\nvar bisectRight = ascendingBisect.right;\nvar bisectLeft = ascendingBisect.left;\nvar bisectCenter = bisector(number).center;\nvar bisect_default = bisectRight;\n\n// ../../node_modules/d3-array/src/blur.js\nvar blur2 = Blur2(blurf);\nvar blurImage = Blur2(blurfImage);\nfunction Blur2(blur3) {\n return function(data, rx, ry = rx) {\n if (!((rx = +rx) >= 0)) throw new RangeError(\"invalid rx\");\n if (!((ry = +ry) >= 0)) throw new RangeError(\"invalid ry\");\n let { data: values2, width: width2, height: height2 } = data;\n if (!((width2 = Math.floor(width2)) >= 0)) throw new RangeError(\"invalid width\");\n if (!((height2 = Math.floor(height2 !== void 0 ? height2 : values2.length / width2)) >= 0)) throw new RangeError(\"invalid height\");\n if (!width2 || !height2 || !rx && !ry) return data;\n const blurx = rx && blur3(rx);\n const blury = ry && blur3(ry);\n const temp = values2.slice();\n if (blurx && blury) {\n blurh(blurx, temp, values2, width2, height2);\n blurh(blurx, values2, temp, width2, height2);\n blurh(blurx, temp, values2, width2, height2);\n blurv(blury, values2, temp, width2, height2);\n blurv(blury, temp, values2, width2, height2);\n blurv(blury, values2, temp, width2, height2);\n } else if (blurx) {\n blurh(blurx, values2, temp, width2, height2);\n blurh(blurx, temp, values2, width2, height2);\n blurh(blurx, values2, temp, width2, height2);\n } else if (blury) {\n blurv(blury, values2, temp, width2, height2);\n blurv(blury, temp, values2, width2, height2);\n blurv(blury, values2, temp, width2, height2);\n }\n return data;\n };\n}\nfunction blurh(blur3, T, S, w, h) {\n for (let y3 = 0, n = w * h; y3 < n; ) {\n blur3(T, S, y3, y3 += w, 1);\n }\n}\nfunction blurv(blur3, T, S, w, h) {\n for (let x3 = 0, n = w * h; x3 < w; ++x3) {\n blur3(T, S, x3, x3 + n, w);\n }\n}\nfunction blurfImage(radius2) {\n const blur3 = blurf(radius2);\n return (T, S, start2, stop, step) => {\n start2 <<= 2, stop <<= 2, step <<= 2;\n blur3(T, S, start2 + 0, stop + 0, step);\n blur3(T, S, start2 + 1, stop + 1, step);\n blur3(T, S, start2 + 2, stop + 2, step);\n blur3(T, S, start2 + 3, stop + 3, step);\n };\n}\nfunction blurf(radius2) {\n const radius0 = Math.floor(radius2);\n if (radius0 === radius2) return bluri(radius2);\n const t = radius2 - radius0;\n const w = 2 * radius2 + 1;\n return (T, S, start2, stop, step) => {\n if (!((stop -= step) >= start2)) return;\n let sum4 = radius0 * S[start2];\n const s0 = step * radius0;\n const s1 = s0 + step;\n for (let i = start2, j = start2 + s0; i < j; i += step) {\n sum4 += S[Math.min(stop, i)];\n }\n for (let i = start2, j = stop; i <= j; i += step) {\n sum4 += S[Math.min(stop, i + s0)];\n T[i] = (sum4 + t * (S[Math.max(start2, i - s1)] + S[Math.min(stop, i + s1)])) / w;\n sum4 -= S[Math.max(start2, i - s0)];\n }\n };\n}\nfunction bluri(radius2) {\n const w = 2 * radius2 + 1;\n return (T, S, start2, stop, step) => {\n if (!((stop -= step) >= start2)) return;\n let sum4 = radius2 * S[start2];\n const s2 = step * radius2;\n for (let i = start2, j = start2 + s2; i < j; i += step) {\n sum4 += S[Math.min(stop, i)];\n }\n for (let i = start2, j = stop; i <= j; i += step) {\n sum4 += S[Math.min(stop, i + s2)];\n T[i] = sum4 / w;\n sum4 -= S[Math.max(start2, i - s2)];\n }\n };\n}\n\n// ../../node_modules/d3-array/src/count.js\nfunction count2(values2, valueof2) {\n let count4 = 0;\n if (valueof2 === void 0) {\n for (let value of values2) {\n if (value != null && (value = +value) >= value) {\n ++count4;\n }\n }\n } else {\n let index2 = -1;\n for (let value of values2) {\n if ((value = valueof2(value, ++index2, values2)) != null && (value = +value) >= value) {\n ++count4;\n }\n }\n }\n return count4;\n}\n\n// ../../node_modules/d3-array/src/cross.js\nfunction length2(array4) {\n return array4.length | 0;\n}\nfunction empty(length4) {\n return !(length4 > 0);\n}\nfunction arrayify(values2) {\n return typeof values2 !== \"object\" || \"length\" in values2 ? values2 : Array.from(values2);\n}\nfunction reducer(reduce) {\n return (values2) => reduce(...values2);\n}\nfunction cross(...values2) {\n const reduce = typeof values2[values2.length - 1] === \"function\" && reducer(values2.pop());\n values2 = values2.map(arrayify);\n const lengths = values2.map(length2);\n const j = values2.length - 1;\n const index2 = new Array(j + 1).fill(0);\n const product2 = [];\n if (j < 0 || lengths.some(empty)) return product2;\n while (true) {\n product2.push(index2.map((j2, i2) => values2[i2][j2]));\n let i = j;\n while (++index2[i] === lengths[i]) {\n if (i === 0) return reduce ? product2.map(reduce) : product2;\n index2[i--] = 0;\n }\n }\n}\n\n// ../../node_modules/d3-array/src/cumsum.js\nfunction cumsum(values2, valueof2) {\n var sum4 = 0, index2 = 0;\n return Float64Array.from(values2, valueof2 === void 0 ? (v2) => sum4 += +v2 || 0 : (v2) => sum4 += +valueof2(v2, index2++, values2) || 0);\n}\n\n// ../../node_modules/d3-array/src/variance.js\nfunction variance2(values2, valueof2) {\n let count4 = 0;\n let delta;\n let mean3 = 0;\n let sum4 = 0;\n if (valueof2 === void 0) {\n for (let value of values2) {\n if (value != null && (value = +value) >= value) {\n delta = value - mean3;\n mean3 += delta / ++count4;\n sum4 += delta * (value - mean3);\n }\n }\n } else {\n let index2 = -1;\n for (let value of values2) {\n if ((value = valueof2(value, ++index2, values2)) != null && (value = +value) >= value) {\n delta = value - mean3;\n mean3 += delta / ++count4;\n sum4 += delta * (value - mean3);\n }\n }\n }\n if (count4 > 1) return sum4 / (count4 - 1);\n}\n\n// ../../node_modules/d3-array/src/deviation.js\nfunction deviation(values2, valueof2) {\n const v2 = variance2(values2, valueof2);\n return v2 ? Math.sqrt(v2) : v2;\n}\n\n// ../../node_modules/d3-array/src/extent.js\nfunction extent(values2, valueof2) {\n let min5;\n let max4;\n if (valueof2 === void 0) {\n for (const value of values2) {\n if (value != null) {\n if (min5 === void 0) {\n if (value >= value) min5 = max4 = value;\n } else {\n if (min5 > value) min5 = value;\n if (max4 < value) max4 = value;\n }\n }\n }\n } else {\n let index2 = -1;\n for (let value of values2) {\n if ((value = valueof2(value, ++index2, values2)) != null) {\n if (min5 === void 0) {\n if (value >= value) min5 = max4 = value;\n } else {\n if (min5 > value) min5 = value;\n if (max4 < value) max4 = value;\n }\n }\n }\n }\n return [min5, max4];\n}\n\n// ../../node_modules/d3-array/src/fsum.js\nvar Adder = class {\n constructor() {\n this._partials = new Float64Array(32);\n this._n = 0;\n }\n add(x3) {\n const p = this._partials;\n let i = 0;\n for (let j = 0; j < this._n && j < 32; j++) {\n const y3 = p[j], hi = x3 + y3, lo = Math.abs(x3) < Math.abs(y3) ? x3 - (hi - y3) : y3 - (hi - x3);\n if (lo) p[i++] = lo;\n x3 = hi;\n }\n p[i] = x3;\n this._n = i + 1;\n return this;\n }\n valueOf() {\n const p = this._partials;\n let n = this._n, x3, y3, lo, hi = 0;\n if (n > 0) {\n hi = p[--n];\n while (n > 0) {\n x3 = hi;\n y3 = p[--n];\n hi = x3 + y3;\n lo = y3 - (hi - x3);\n if (lo) break;\n }\n if (n > 0 && (lo < 0 && p[n - 1] < 0 || lo > 0 && p[n - 1] > 0)) {\n y3 = lo * 2;\n x3 = hi + y3;\n if (y3 == x3 - hi) hi = x3;\n }\n }\n return hi;\n }\n};\n\n// ../../node_modules/internmap/src/index.js\nvar InternMap = class extends Map {\n constructor(entries, key = keyof) {\n super();\n Object.defineProperties(this, { _intern: { value: /* @__PURE__ */ new Map() }, _key: { value: key } });\n if (entries != null) for (const [key2, value] of entries) this.set(key2, value);\n }\n get(key) {\n return super.get(intern_get(this, key));\n }\n has(key) {\n return super.has(intern_get(this, key));\n }\n set(key, value) {\n return super.set(intern_set(this, key), value);\n }\n delete(key) {\n return super.delete(intern_delete(this, key));\n }\n};\nvar InternSet = class extends Set {\n constructor(values2, key = keyof) {\n super();\n Object.defineProperties(this, { _intern: { value: /* @__PURE__ */ new Map() }, _key: { value: key } });\n if (values2 != null) for (const value of values2) this.add(value);\n }\n has(value) {\n return super.has(intern_get(this, value));\n }\n add(value) {\n return super.add(intern_set(this, value));\n }\n delete(value) {\n return super.delete(intern_delete(this, value));\n }\n};\nfunction intern_get({ _intern, _key }, value) {\n const key = _key(value);\n return _intern.has(key) ? _intern.get(key) : value;\n}\nfunction intern_set({ _intern, _key }, value) {\n const key = _key(value);\n if (_intern.has(key)) return _intern.get(key);\n _intern.set(key, value);\n return value;\n}\nfunction intern_delete({ _intern, _key }, value) {\n const key = _key(value);\n if (_intern.has(key)) {\n value = _intern.get(key);\n _intern.delete(key);\n }\n return value;\n}\nfunction keyof(value) {\n return value !== null && typeof value === \"object\" ? value.valueOf() : value;\n}\n\n// ../../node_modules/d3-array/src/identity.js\nfunction identity2(x3) {\n return x3;\n}\n\n// ../../node_modules/d3-array/src/group.js\nfunction group(values2, ...keys) {\n return nest(values2, identity2, identity2, keys);\n}\nfunction rollup(values2, reduce, ...keys) {\n return nest(values2, identity2, reduce, keys);\n}\nfunction rollups(values2, reduce, ...keys) {\n return nest(values2, Array.from, reduce, keys);\n}\nfunction nest(values2, map5, reduce, keys) {\n return function regroup(values3, i) {\n if (i >= keys.length) return reduce(values3);\n const groups2 = new InternMap();\n const keyof3 = keys[i++];\n let index2 = -1;\n for (const value of values3) {\n const key = keyof3(value, ++index2, values3);\n const group3 = groups2.get(key);\n if (group3) group3.push(value);\n else groups2.set(key, [value]);\n }\n for (const [key, values4] of groups2) {\n groups2.set(key, regroup(values4, i));\n }\n return map5(groups2);\n }(values2, 0);\n}\n\n// ../../node_modules/d3-array/src/permute.js\nfunction permute(source, keys) {\n return Array.from(keys, (key) => source[key]);\n}\n\n// ../../node_modules/d3-array/src/sort.js\nfunction sort(values2, ...F) {\n if (typeof values2[Symbol.iterator] !== \"function\") throw new TypeError(\"values is not iterable\");\n values2 = Array.from(values2);\n let [f] = F;\n if (f && f.length !== 2 || F.length > 1) {\n const index2 = Uint32Array.from(values2, (d, i) => i);\n if (F.length > 1) {\n F = F.map((f2) => values2.map(f2));\n index2.sort((i, j) => {\n for (const f2 of F) {\n const c4 = ascendingDefined(f2[i], f2[j]);\n if (c4) return c4;\n }\n });\n } else {\n f = values2.map(f);\n index2.sort((i, j) => ascendingDefined(f[i], f[j]));\n }\n return permute(values2, index2);\n }\n return values2.sort(compareDefined(f));\n}\nfunction compareDefined(compare = ascending) {\n if (compare === ascending) return ascendingDefined;\n if (typeof compare !== \"function\") throw new TypeError(\"compare is not a function\");\n return (a2, b) => {\n const x3 = compare(a2, b);\n if (x3 || x3 === 0) return x3;\n return (compare(b, b) === 0) - (compare(a2, a2) === 0);\n };\n}\nfunction ascendingDefined(a2, b) {\n return (a2 == null || !(a2 >= a2)) - (b == null || !(b >= b)) || (a2 < b ? -1 : a2 > b ? 1 : 0);\n}\n\n// ../../node_modules/d3-array/src/groupSort.js\nfunction groupSort(values2, reduce, key) {\n return (reduce.length !== 2 ? sort(rollup(values2, reduce, key), ([ak, av], [bk, bv]) => ascending(av, bv) || ascending(ak, bk)) : sort(group(values2, key), ([ak, av], [bk, bv]) => reduce(av, bv) || ascending(ak, bk))).map(([key2]) => key2);\n}\n\n// ../../node_modules/d3-array/src/ticks.js\nvar e10 = Math.sqrt(50);\nvar e5 = Math.sqrt(10);\nvar e2 = Math.sqrt(2);\nfunction tickSpec(start2, stop, count4) {\n const step = (stop - start2) / Math.max(0, count4), power = Math.floor(Math.log10(step)), error2 = step / Math.pow(10, power), factor = error2 >= e10 ? 10 : error2 >= e5 ? 5 : error2 >= e2 ? 2 : 1;\n let i1, i2, inc2;\n if (power < 0) {\n inc2 = Math.pow(10, -power) / factor;\n i1 = Math.round(start2 * inc2);\n i2 = Math.round(stop * inc2);\n if (i1 / inc2 < start2) ++i1;\n if (i2 / inc2 > stop) --i2;\n inc2 = -inc2;\n } else {\n inc2 = Math.pow(10, power) * factor;\n i1 = Math.round(start2 / inc2);\n i2 = Math.round(stop / inc2);\n if (i1 * inc2 < start2) ++i1;\n if (i2 * inc2 > stop) --i2;\n }\n if (i2 < i1 && 0.5 <= count4 && count4 < 2) return tickSpec(start2, stop, count4 * 2);\n return [i1, i2, inc2];\n}\nfunction ticks(start2, stop, count4) {\n stop = +stop, start2 = +start2, count4 = +count4;\n if (!(count4 > 0)) return [];\n if (start2 === stop) return [start2];\n const reverse3 = stop < start2, [i1, i2, inc2] = reverse3 ? tickSpec(stop, start2, count4) : tickSpec(start2, stop, count4);\n if (!(i2 >= i1)) return [];\n const n = i2 - i1 + 1, ticks2 = new Array(n);\n if (reverse3) {\n if (inc2 < 0) for (let i = 0; i < n; ++i) ticks2[i] = (i2 - i) / -inc2;\n else for (let i = 0; i < n; ++i) ticks2[i] = (i2 - i) * inc2;\n } else {\n if (inc2 < 0) for (let i = 0; i < n; ++i) ticks2[i] = (i1 + i) / -inc2;\n else for (let i = 0; i < n; ++i) ticks2[i] = (i1 + i) * inc2;\n }\n return ticks2;\n}\nfunction tickIncrement(start2, stop, count4) {\n stop = +stop, start2 = +start2, count4 = +count4;\n return tickSpec(start2, stop, count4)[2];\n}\nfunction tickStep(start2, stop, count4) {\n stop = +stop, start2 = +start2, count4 = +count4;\n const reverse3 = stop < start2, inc2 = reverse3 ? tickIncrement(stop, start2, count4) : tickIncrement(start2, stop, count4);\n return (reverse3 ? -1 : 1) * (inc2 < 0 ? 1 / -inc2 : inc2);\n}\n\n// ../../node_modules/d3-array/src/nice.js\nfunction nice(start2, stop, count4) {\n let prestep;\n while (true) {\n const step = tickIncrement(start2, stop, count4);\n if (step === prestep || step === 0 || !isFinite(step)) {\n return [start2, stop];\n } else if (step > 0) {\n start2 = Math.floor(start2 / step) * step;\n stop = Math.ceil(stop / step) * step;\n } else if (step < 0) {\n start2 = Math.ceil(start2 * step) / step;\n stop = Math.floor(stop * step) / step;\n }\n prestep = step;\n }\n}\n\n// ../../node_modules/d3-array/src/threshold/sturges.js\nfunction thresholdSturges(values2) {\n return Math.max(1, Math.ceil(Math.log(count2(values2)) / Math.LN2) + 1);\n}\n\n// ../../node_modules/d3-array/src/max.js\nfunction max2(values2, valueof2) {\n let max4;\n if (valueof2 === void 0) {\n for (const value of values2) {\n if (value != null && (max4 < value || max4 === void 0 && value >= value)) {\n max4 = value;\n }\n }\n } else {\n let index2 = -1;\n for (let value of values2) {\n if ((value = valueof2(value, ++index2, values2)) != null && (max4 < value || max4 === void 0 && value >= value)) {\n max4 = value;\n }\n }\n }\n return max4;\n}\n\n// ../../node_modules/d3-array/src/maxIndex.js\nfunction maxIndex(values2, valueof2) {\n let max4;\n let maxIndex2 = -1;\n let index2 = -1;\n if (valueof2 === void 0) {\n for (const value of values2) {\n ++index2;\n if (value != null && (max4 < value || max4 === void 0 && value >= value)) {\n max4 = value, maxIndex2 = index2;\n }\n }\n } else {\n for (let value of values2) {\n if ((value = valueof2(value, ++index2, values2)) != null && (max4 < value || max4 === void 0 && value >= value)) {\n max4 = value, maxIndex2 = index2;\n }\n }\n }\n return maxIndex2;\n}\n\n// ../../node_modules/d3-array/src/min.js\nfunction min2(values2, valueof2) {\n let min5;\n if (valueof2 === void 0) {\n for (const value of values2) {\n if (value != null && (min5 > value || min5 === void 0 && value >= value)) {\n min5 = value;\n }\n }\n } else {\n let index2 = -1;\n for (let value of values2) {\n if ((value = valueof2(value, ++index2, values2)) != null && (min5 > value || min5 === void 0 && value >= value)) {\n min5 = value;\n }\n }\n }\n return min5;\n}\n\n// ../../node_modules/d3-array/src/minIndex.js\nfunction minIndex(values2, valueof2) {\n let min5;\n let minIndex2 = -1;\n let index2 = -1;\n if (valueof2 === void 0) {\n for (const value of values2) {\n ++index2;\n if (value != null && (min5 > value || min5 === void 0 && value >= value)) {\n min5 = value, minIndex2 = index2;\n }\n }\n } else {\n for (let value of values2) {\n if ((value = valueof2(value, ++index2, values2)) != null && (min5 > value || min5 === void 0 && value >= value)) {\n min5 = value, minIndex2 = index2;\n }\n }\n }\n return minIndex2;\n}\n\n// ../../node_modules/d3-array/src/quickselect.js\nfunction quickselect(array4, k2, left2 = 0, right2 = Infinity, compare) {\n k2 = Math.floor(k2);\n left2 = Math.floor(Math.max(0, left2));\n right2 = Math.floor(Math.min(array4.length - 1, right2));\n if (!(left2 <= k2 && k2 <= right2)) return array4;\n compare = compare === void 0 ? ascendingDefined : compareDefined(compare);\n while (right2 > left2) {\n if (right2 - left2 > 600) {\n const n = right2 - left2 + 1;\n const m = k2 - left2 + 1;\n const z = Math.log(n);\n const s2 = 0.5 * Math.exp(2 * z / 3);\n const sd = 0.5 * Math.sqrt(z * s2 * (n - s2) / n) * (m - n / 2 < 0 ? -1 : 1);\n const newLeft = Math.max(left2, Math.floor(k2 - m * s2 / n + sd));\n const newRight = Math.min(right2, Math.floor(k2 + (n - m) * s2 / n + sd));\n quickselect(array4, k2, newLeft, newRight, compare);\n }\n const t = array4[k2];\n let i = left2;\n let j = right2;\n swap(array4, left2, k2);\n if (compare(array4[right2], t) > 0) swap(array4, left2, right2);\n while (i < j) {\n swap(array4, i, j), ++i, --j;\n while (compare(array4[i], t) < 0) ++i;\n while (compare(array4[j], t) > 0) --j;\n }\n if (compare(array4[left2], t) === 0) swap(array4, left2, j);\n else ++j, swap(array4, j, right2);\n if (j <= k2) left2 = j + 1;\n if (k2 <= j) right2 = j - 1;\n }\n return array4;\n}\nfunction swap(array4, i, j) {\n const t = array4[i];\n array4[i] = array4[j];\n array4[j] = t;\n}\n\n// ../../node_modules/d3-array/src/greatest.js\nfunction greatest(values2, compare = ascending) {\n let max4;\n let defined2 = false;\n if (compare.length === 1) {\n let maxValue;\n for (const element of values2) {\n const value = compare(element);\n if (defined2 ? ascending(value, maxValue) > 0 : ascending(value, value) === 0) {\n max4 = element;\n maxValue = value;\n defined2 = true;\n }\n }\n } else {\n for (const value of values2) {\n if (defined2 ? compare(value, max4) > 0 : compare(value, value) === 0) {\n max4 = value;\n defined2 = true;\n }\n }\n }\n return max4;\n}\n\n// ../../node_modules/d3-array/src/quantile.js\nfunction quantile2(values2, p, valueof2) {\n values2 = Float64Array.from(numbers(values2, valueof2));\n if (!(n = values2.length) || isNaN(p = +p)) return;\n if (p <= 0 || n < 2) return min2(values2);\n if (p >= 1) return max2(values2);\n var n, i = (n - 1) * p, i0 = Math.floor(i), value0 = max2(quickselect(values2, i0).subarray(0, i0 + 1)), value1 = min2(values2.subarray(i0 + 1));\n return value0 + (value1 - value0) * (i - i0);\n}\nfunction quantileSorted(values2, p, valueof2 = number) {\n if (!(n = values2.length) || isNaN(p = +p)) return;\n if (p <= 0 || n < 2) return +valueof2(values2[0], 0, values2);\n if (p >= 1) return +valueof2(values2[n - 1], n - 1, values2);\n var n, i = (n - 1) * p, i0 = Math.floor(i), value0 = +valueof2(values2[i0], i0, values2), value1 = +valueof2(values2[i0 + 1], i0 + 1, values2);\n return value0 + (value1 - value0) * (i - i0);\n}\n\n// ../../node_modules/d3-array/src/threshold/freedmanDiaconis.js\nfunction thresholdFreedmanDiaconis(values2, min5, max4) {\n const c4 = count2(values2), d = quantile2(values2, 0.75) - quantile2(values2, 0.25);\n return c4 && d ? Math.ceil((max4 - min5) / (2 * d * Math.pow(c4, -1 / 3))) : 1;\n}\n\n// ../../node_modules/d3-array/src/threshold/scott.js\nfunction thresholdScott(values2, min5, max4) {\n const c4 = count2(values2), d = deviation(values2);\n return c4 && d ? Math.ceil((max4 - min5) * Math.cbrt(c4) / (3.49 * d)) : 1;\n}\n\n// ../../node_modules/d3-array/src/mean.js\nfunction mean2(values2, valueof2) {\n let count4 = 0;\n let sum4 = 0;\n if (valueof2 === void 0) {\n for (let value of values2) {\n if (value != null && (value = +value) >= value) {\n ++count4, sum4 += value;\n }\n }\n } else {\n let index2 = -1;\n for (let value of values2) {\n if ((value = valueof2(value, ++index2, values2)) != null && (value = +value) >= value) {\n ++count4, sum4 += value;\n }\n }\n }\n if (count4) return sum4 / count4;\n}\n\n// ../../node_modules/d3-array/src/median.js\nfunction median2(values2, valueof2) {\n return quantile2(values2, 0.5, valueof2);\n}\n\n// ../../node_modules/d3-array/src/merge.js\nfunction* flatten(arrays) {\n for (const array4 of arrays) {\n yield* array4;\n }\n}\nfunction merge(arrays) {\n return Array.from(flatten(arrays));\n}\n\n// ../../node_modules/d3-array/src/mode.js\nfunction mode2(values2, valueof2) {\n const counts = new InternMap();\n if (valueof2 === void 0) {\n for (let value of values2) {\n if (value != null && value >= value) {\n counts.set(value, (counts.get(value) || 0) + 1);\n }\n }\n } else {\n let index2 = -1;\n for (let value of values2) {\n if ((value = valueof2(value, ++index2, values2)) != null && value >= value) {\n counts.set(value, (counts.get(value) || 0) + 1);\n }\n }\n }\n let modeValue;\n let modeCount = 0;\n for (const [value, count4] of counts) {\n if (count4 > modeCount) {\n modeCount = count4;\n modeValue = value;\n }\n }\n return modeValue;\n}\n\n// ../../node_modules/d3-array/src/pairs.js\nfunction pairs2(values2, pairof = pair) {\n const pairs3 = [];\n let previous;\n let first3 = false;\n for (const value of values2) {\n if (first3) pairs3.push(pairof(previous, value));\n previous = value;\n first3 = true;\n }\n return pairs3;\n}\nfunction pair(a2, b) {\n return [a2, b];\n}\n\n// ../../node_modules/d3-array/src/range.js\nfunction range(start2, stop, step) {\n start2 = +start2, stop = +stop, step = (n = arguments.length) < 2 ? (stop = start2, start2 = 0, 1) : n < 3 ? 1 : +step;\n var i = -1, n = Math.max(0, Math.ceil((stop - start2) / step)) | 0, range3 = new Array(n);\n while (++i < n) {\n range3[i] = start2 + i * step;\n }\n return range3;\n}\n\n// ../../node_modules/d3-array/src/rank.js\nfunction rank2(values2, valueof2 = ascending) {\n if (typeof values2[Symbol.iterator] !== \"function\") throw new TypeError(\"values is not iterable\");\n let V = Array.from(values2);\n const R = new Float64Array(V.length);\n if (valueof2.length !== 2) V = V.map(valueof2), valueof2 = ascending;\n const compareIndex = (i, j) => valueof2(V[i], V[j]);\n let k2, r;\n values2 = Uint32Array.from(V, (_, i) => i);\n values2.sort(valueof2 === ascending ? (i, j) => ascendingDefined(V[i], V[j]) : compareDefined(compareIndex));\n values2.forEach((j, i) => {\n const c4 = compareIndex(j, k2 === void 0 ? j : k2);\n if (c4 >= 0) {\n if (k2 === void 0 || c4 > 0) k2 = j, r = i;\n R[j] = r;\n } else {\n R[j] = NaN;\n }\n });\n return R;\n}\n\n// ../../node_modules/d3-array/src/least.js\nfunction least(values2, compare = ascending) {\n let min5;\n let defined2 = false;\n if (compare.length === 1) {\n let minValue;\n for (const element of values2) {\n const value = compare(element);\n if (defined2 ? ascending(value, minValue) < 0 : ascending(value, value) === 0) {\n min5 = element;\n minValue = value;\n defined2 = true;\n }\n }\n } else {\n for (const value of values2) {\n if (defined2 ? compare(value, min5) < 0 : compare(value, value) === 0) {\n min5 = value;\n defined2 = true;\n }\n }\n }\n return min5;\n}\n\n// ../../node_modules/d3-array/src/sum.js\nfunction sum2(values2, valueof2) {\n let sum4 = 0;\n if (valueof2 === void 0) {\n for (let value of values2) {\n if (value = +value) {\n sum4 += value;\n }\n }\n } else {\n let index2 = -1;\n for (let value of values2) {\n if (value = +valueof2(value, ++index2, values2)) {\n sum4 += value;\n }\n }\n }\n return sum4;\n}\n\n// ../../node_modules/d3-array/src/reverse.js\nfunction reverse(values2) {\n if (typeof values2[Symbol.iterator] !== \"function\") throw new TypeError(\"values is not iterable\");\n return Array.from(values2).reverse();\n}\n\n// ../../node_modules/d3-axis/src/identity.js\nfunction identity_default(x3) {\n return x3;\n}\n\n// ../../node_modules/d3-axis/src/axis.js\nvar top = 1;\nvar right = 2;\nvar bottom = 3;\nvar left = 4;\nvar epsilon = 1e-6;\nfunction translateX(x3) {\n return \"translate(\" + x3 + \",0)\";\n}\nfunction translateY(y3) {\n return \"translate(0,\" + y3 + \")\";\n}\nfunction number2(scale3) {\n return (d) => +scale3(d);\n}\nfunction center(scale3, offset2) {\n offset2 = Math.max(0, scale3.bandwidth() - offset2 * 2) / 2;\n if (scale3.round()) offset2 = Math.round(offset2);\n return (d) => +scale3(d) + offset2;\n}\nfunction entering() {\n return !this.__axis;\n}\nfunction axis(orient, scale3) {\n var tickArguments = [], tickValues = null, tickFormat2 = null, tickSizeInner = 6, tickSizeOuter = 6, tickPadding = 3, offset2 = typeof window !== \"undefined\" && window.devicePixelRatio > 1 ? 0 : 0.5, k2 = orient === top || orient === left ? -1 : 1, x3 = orient === left || orient === right ? \"x\" : \"y\", transform3 = orient === top || orient === bottom ? translateX : translateY;\n function axis3(context) {\n var values2 = tickValues == null ? scale3.ticks ? scale3.ticks.apply(scale3, tickArguments) : scale3.domain() : tickValues, format3 = tickFormat2 == null ? scale3.tickFormat ? scale3.tickFormat.apply(scale3, tickArguments) : identity_default : tickFormat2, spacing = Math.max(tickSizeInner, 0) + tickPadding, range3 = scale3.range(), range0 = +range3[0] + offset2, range1 = +range3[range3.length - 1] + offset2, position3 = (scale3.bandwidth ? center : number2)(scale3.copy(), offset2), selection2 = context.selection ? context.selection() : context, path2 = selection2.selectAll(\".domain\").data([null]), tick = selection2.selectAll(\".tick\").data(values2, scale3).order(), tickExit = tick.exit(), tickEnter = tick.enter().append(\"g\").attr(\"class\", \"tick\"), line3 = tick.select(\"line\"), text3 = tick.select(\"text\");\n path2 = path2.merge(path2.enter().insert(\"path\", \".tick\").attr(\"class\", \"domain\").attr(\"stroke\", \"currentColor\"));\n tick = tick.merge(tickEnter);\n line3 = line3.merge(tickEnter.append(\"line\").attr(\"stroke\", \"currentColor\").attr(x3 + \"2\", k2 * tickSizeInner));\n text3 = text3.merge(tickEnter.append(\"text\").attr(\"fill\", \"currentColor\").attr(x3, k2 * spacing).attr(\"dy\", orient === top ? \"0em\" : orient === bottom ? \"0.71em\" : \"0.32em\"));\n if (context !== selection2) {\n path2 = path2.transition(context);\n tick = tick.transition(context);\n line3 = line3.transition(context);\n text3 = text3.transition(context);\n tickExit = tickExit.transition(context).attr(\"opacity\", epsilon).attr(\"transform\", function(d) {\n return isFinite(d = position3(d)) ? transform3(d + offset2) : this.getAttribute(\"transform\");\n });\n tickEnter.attr(\"opacity\", epsilon).attr(\"transform\", function(d) {\n var p = this.parentNode.__axis;\n return transform3((p && isFinite(p = p(d)) ? p : position3(d)) + offset2);\n });\n }\n tickExit.remove();\n path2.attr(\"d\", orient === left || orient === right ? tickSizeOuter ? \"M\" + k2 * tickSizeOuter + \",\" + range0 + \"H\" + offset2 + \"V\" + range1 + \"H\" + k2 * tickSizeOuter : \"M\" + offset2 + \",\" + range0 + \"V\" + range1 : tickSizeOuter ? \"M\" + range0 + \",\" + k2 * tickSizeOuter + \"V\" + offset2 + \"H\" + range1 + \"V\" + k2 * tickSizeOuter : \"M\" + range0 + \",\" + offset2 + \"H\" + range1);\n tick.attr(\"opacity\", 1).attr(\"transform\", function(d) {\n return transform3(position3(d) + offset2);\n });\n line3.attr(x3 + \"2\", k2 * tickSizeInner);\n text3.attr(x3, k2 * spacing).text(format3);\n selection2.filter(entering).attr(\"fill\", \"none\").attr(\"font-size\", 10).attr(\"font-family\", \"sans-serif\").attr(\"text-anchor\", orient === right ? \"start\" : orient === left ? \"end\" : \"middle\");\n selection2.each(function() {\n this.__axis = position3;\n });\n }\n axis3.scale = function(_) {\n return arguments.length ? (scale3 = _, axis3) : scale3;\n };\n axis3.ticks = function() {\n return tickArguments = Array.from(arguments), axis3;\n };\n axis3.tickArguments = function(_) {\n return arguments.length ? (tickArguments = _ == null ? [] : Array.from(_), axis3) : tickArguments.slice();\n };\n axis3.tickValues = function(_) {\n return arguments.length ? (tickValues = _ == null ? null : Array.from(_), axis3) : tickValues && tickValues.slice();\n };\n axis3.tickFormat = function(_) {\n return arguments.length ? (tickFormat2 = _, axis3) : tickFormat2;\n };\n axis3.tickSize = function(_) {\n return arguments.length ? (tickSizeInner = tickSizeOuter = +_, axis3) : tickSizeInner;\n };\n axis3.tickSizeInner = function(_) {\n return arguments.length ? (tickSizeInner = +_, axis3) : tickSizeInner;\n };\n axis3.tickSizeOuter = function(_) {\n return arguments.length ? (tickSizeOuter = +_, axis3) : tickSizeOuter;\n };\n axis3.tickPadding = function(_) {\n return arguments.length ? (tickPadding = +_, axis3) : tickPadding;\n };\n axis3.offset = function(_) {\n return arguments.length ? (offset2 = +_, axis3) : offset2;\n };\n return axis3;\n}\nfunction axisBottom(scale3) {\n return axis(bottom, scale3);\n}\n\n// ../../node_modules/d3-dispatch/src/dispatch.js\nvar noop = { value: () => {\n} };\nfunction dispatch() {\n for (var i = 0, n = arguments.length, _ = {}, t; i < n; ++i) {\n if (!(t = arguments[i] + \"\") || t in _ || /[\\s.]/.test(t)) throw new Error(\"illegal type: \" + t);\n _[t] = [];\n }\n return new Dispatch(_);\n}\nfunction Dispatch(_) {\n this._ = _;\n}\nfunction parseTypenames(typenames, types) {\n return typenames.trim().split(/^|\\s+/).map(function(t) {\n var name2 = \"\", i = t.indexOf(\".\");\n if (i >= 0) name2 = t.slice(i + 1), t = t.slice(0, i);\n if (t && !types.hasOwnProperty(t)) throw new Error(\"unknown type: \" + t);\n return { type: t, name: name2 };\n });\n}\nDispatch.prototype = dispatch.prototype = {\n constructor: Dispatch,\n on: function(typename, callback) {\n var _ = this._, T = parseTypenames(typename + \"\", _), t, i = -1, n = T.length;\n if (arguments.length < 2) {\n while (++i < n) if ((t = (typename = T[i]).type) && (t = get(_[t], typename.name))) return t;\n return;\n }\n if (callback != null && typeof callback !== \"function\") throw new Error(\"invalid callback: \" + callback);\n while (++i < n) {\n if (t = (typename = T[i]).type) _[t] = set(_[t], typename.name, callback);\n else if (callback == null) for (t in _) _[t] = set(_[t], typename.name, null);\n }\n return this;\n },\n copy: function() {\n var copy4 = {}, _ = this._;\n for (var t in _) copy4[t] = _[t].slice();\n return new Dispatch(copy4);\n },\n call: function(type2, that) {\n if ((n = arguments.length - 2) > 0) for (var args = new Array(n), i = 0, n, t; i < n; ++i) args[i] = arguments[i + 2];\n if (!this._.hasOwnProperty(type2)) throw new Error(\"unknown type: \" + type2);\n for (t = this._[type2], i = 0, n = t.length; i < n; ++i) t[i].value.apply(that, args);\n },\n apply: function(type2, that, args) {\n if (!this._.hasOwnProperty(type2)) throw new Error(\"unknown type: \" + type2);\n for (var t = this._[type2], i = 0, n = t.length; i < n; ++i) t[i].value.apply(that, args);\n }\n};\nfunction get(type2, name2) {\n for (var i = 0, n = type2.length, c4; i < n; ++i) {\n if ((c4 = type2[i]).name === name2) {\n return c4.value;\n }\n }\n}\nfunction set(type2, name2, callback) {\n for (var i = 0, n = type2.length; i < n; ++i) {\n if (type2[i].name === name2) {\n type2[i] = noop, type2 = type2.slice(0, i).concat(type2.slice(i + 1));\n break;\n }\n }\n if (callback != null) type2.push({ name: name2, value: callback });\n return type2;\n}\nvar dispatch_default = dispatch;\n\n// ../../node_modules/d3-selection/src/namespaces.js\nvar xhtml = \"http://www.w3.org/1999/xhtml\";\nvar namespaces_default = {\n svg: \"http://www.w3.org/2000/svg\",\n xhtml,\n xlink: \"http://www.w3.org/1999/xlink\",\n xml: \"http://www.w3.org/XML/1998/namespace\",\n xmlns: \"http://www.w3.org/2000/xmlns/\"\n};\n\n// ../../node_modules/d3-selection/src/namespace.js\nfunction namespace_default(name2) {\n var prefix2 = name2 += \"\", i = prefix2.indexOf(\":\");\n if (i >= 0 && (prefix2 = name2.slice(0, i)) !== \"xmlns\") name2 = name2.slice(i + 1);\n return namespaces_default.hasOwnProperty(prefix2) ? { space: namespaces_default[prefix2], local: name2 } : name2;\n}\n\n// ../../node_modules/d3-selection/src/creator.js\nfunction creatorInherit(name2) {\n return function() {\n var document2 = this.ownerDocument, uri = this.namespaceURI;\n return uri === xhtml && document2.documentElement.namespaceURI === xhtml ? document2.createElement(name2) : document2.createElementNS(uri, name2);\n };\n}\nfunction creatorFixed(fullname) {\n return function() {\n return this.ownerDocument.createElementNS(fullname.space, fullname.local);\n };\n}\nfunction creator_default(name2) {\n var fullname = namespace_default(name2);\n return (fullname.local ? creatorFixed : creatorInherit)(fullname);\n}\n\n// ../../node_modules/d3-selection/src/selector.js\nfunction none() {\n}\nfunction selector_default(selector) {\n return selector == null ? none : function() {\n return this.querySelector(selector);\n };\n}\n\n// ../../node_modules/d3-selection/src/selection/select.js\nfunction select_default(select2) {\n if (typeof select2 !== \"function\") select2 = selector_default(select2);\n for (var groups2 = this._groups, m = groups2.length, subgroups = new Array(m), j = 0; j < m; ++j) {\n for (var group3 = groups2[j], n = group3.length, subgroup = subgroups[j] = new Array(n), node, subnode, i = 0; i < n; ++i) {\n if ((node = group3[i]) && (subnode = select2.call(node, node.__data__, i, group3))) {\n if (\"__data__\" in node) subnode.__data__ = node.__data__;\n subgroup[i] = subnode;\n }\n }\n }\n return new Selection2(subgroups, this._parents);\n}\n\n// ../../node_modules/d3-selection/src/array.js\nfunction array(x3) {\n return x3 == null ? [] : Array.isArray(x3) ? x3 : Array.from(x3);\n}\n\n// ../../node_modules/d3-selection/src/selectorAll.js\nfunction empty2() {\n return [];\n}\nfunction selectorAll_default(selector) {\n return selector == null ? empty2 : function() {\n return this.querySelectorAll(selector);\n };\n}\n\n// ../../node_modules/d3-selection/src/selection/selectAll.js\nfunction arrayAll(select2) {\n return function() {\n return array(select2.apply(this, arguments));\n };\n}\nfunction selectAll_default(select2) {\n if (typeof select2 === \"function\") select2 = arrayAll(select2);\n else select2 = selectorAll_default(select2);\n for (var groups2 = this._groups, m = groups2.length, subgroups = [], parents = [], j = 0; j < m; ++j) {\n for (var group3 = groups2[j], n = group3.length, node, i = 0; i < n; ++i) {\n if (node = group3[i]) {\n subgroups.push(select2.call(node, node.__data__, i, group3));\n parents.push(node);\n }\n }\n }\n return new Selection2(subgroups, parents);\n}\n\n// ../../node_modules/d3-selection/src/matcher.js\nfunction matcher_default(selector) {\n return function() {\n return this.matches(selector);\n };\n}\nfunction childMatcher(selector) {\n return function(node) {\n return node.matches(selector);\n };\n}\n\n// ../../node_modules/d3-selection/src/selection/selectChild.js\nvar find = Array.prototype.find;\nfunction childFind(match) {\n return function() {\n return find.call(this.children, match);\n };\n}\nfunction childFirst() {\n return this.firstElementChild;\n}\nfunction selectChild_default(match) {\n return this.select(match == null ? childFirst : childFind(typeof match === \"function\" ? match : childMatcher(match)));\n}\n\n// ../../node_modules/d3-selection/src/selection/selectChildren.js\nvar filter = Array.prototype.filter;\nfunction children() {\n return Array.from(this.children);\n}\nfunction childrenFilter(match) {\n return function() {\n return filter.call(this.children, match);\n };\n}\nfunction selectChildren_default(match) {\n return this.selectAll(match == null ? children : childrenFilter(typeof match === \"function\" ? match : childMatcher(match)));\n}\n\n// ../../node_modules/d3-selection/src/selection/filter.js\nfunction filter_default(match) {\n if (typeof match !== \"function\") match = matcher_default(match);\n for (var groups2 = this._groups, m = groups2.length, subgroups = new Array(m), j = 0; j < m; ++j) {\n for (var group3 = groups2[j], n = group3.length, subgroup = subgroups[j] = [], node, i = 0; i < n; ++i) {\n if ((node = group3[i]) && match.call(node, node.__data__, i, group3)) {\n subgroup.push(node);\n }\n }\n }\n return new Selection2(subgroups, this._parents);\n}\n\n// ../../node_modules/d3-selection/src/selection/sparse.js\nfunction sparse_default(update2) {\n return new Array(update2.length);\n}\n\n// ../../node_modules/d3-selection/src/selection/enter.js\nfunction enter_default() {\n return new Selection2(this._enter || this._groups.map(sparse_default), this._parents);\n}\nfunction EnterNode(parent, datum2) {\n this.ownerDocument = parent.ownerDocument;\n this.namespaceURI = parent.namespaceURI;\n this._next = null;\n this._parent = parent;\n this.__data__ = datum2;\n}\nEnterNode.prototype = {\n constructor: EnterNode,\n appendChild: function(child) {\n return this._parent.insertBefore(child, this._next);\n },\n insertBefore: function(child, next) {\n return this._parent.insertBefore(child, next);\n },\n querySelector: function(selector) {\n return this._parent.querySelector(selector);\n },\n querySelectorAll: function(selector) {\n return this._parent.querySelectorAll(selector);\n }\n};\n\n// ../../node_modules/d3-selection/src/constant.js\nfunction constant_default(x3) {\n return function() {\n return x3;\n };\n}\n\n// ../../node_modules/d3-selection/src/selection/data.js\nfunction bindIndex(parent, group3, enter, update2, exit, data) {\n var i = 0, node, groupLength = group3.length, dataLength = data.length;\n for (; i < dataLength; ++i) {\n if (node = group3[i]) {\n node.__data__ = data[i];\n update2[i] = node;\n } else {\n enter[i] = new EnterNode(parent, data[i]);\n }\n }\n for (; i < groupLength; ++i) {\n if (node = group3[i]) {\n exit[i] = node;\n }\n }\n}\nfunction bindKey(parent, group3, enter, update2, exit, data, key) {\n var i, node, nodeByKeyValue = /* @__PURE__ */ new Map(), groupLength = group3.length, dataLength = data.length, keyValues = new Array(groupLength), keyValue;\n for (i = 0; i < groupLength; ++i) {\n if (node = group3[i]) {\n keyValues[i] = keyValue = key.call(node, node.__data__, i, group3) + \"\";\n if (nodeByKeyValue.has(keyValue)) {\n exit[i] = node;\n } else {\n nodeByKeyValue.set(keyValue, node);\n }\n }\n }\n for (i = 0; i < dataLength; ++i) {\n keyValue = key.call(parent, data[i], i, data) + \"\";\n if (node = nodeByKeyValue.get(keyValue)) {\n update2[i] = node;\n node.__data__ = data[i];\n nodeByKeyValue.delete(keyValue);\n } else {\n enter[i] = new EnterNode(parent, data[i]);\n }\n }\n for (i = 0; i < groupLength; ++i) {\n if ((node = group3[i]) && nodeByKeyValue.get(keyValues[i]) === node) {\n exit[i] = node;\n }\n }\n}\nfunction datum(node) {\n return node.__data__;\n}\nfunction data_default(value, key) {\n if (!arguments.length) return Array.from(this, datum);\n var bind = key ? bindKey : bindIndex, parents = this._parents, groups2 = this._groups;\n if (typeof value !== \"function\") value = constant_default(value);\n for (var m = groups2.length, update2 = new Array(m), enter = new Array(m), exit = new Array(m), j = 0; j < m; ++j) {\n var parent = parents[j], group3 = groups2[j], groupLength = group3.length, data = arraylike(value.call(parent, parent && parent.__data__, j, parents)), dataLength = data.length, enterGroup = enter[j] = new Array(dataLength), updateGroup = update2[j] = new Array(dataLength), exitGroup = exit[j] = new Array(groupLength);\n bind(parent, group3, enterGroup, updateGroup, exitGroup, data, key);\n for (var i0 = 0, i1 = 0, previous, next; i0 < dataLength; ++i0) {\n if (previous = enterGroup[i0]) {\n if (i0 >= i1) i1 = i0 + 1;\n while (!(next = updateGroup[i1]) && ++i1 < dataLength) ;\n previous._next = next || null;\n }\n }\n }\n update2 = new Selection2(update2, parents);\n update2._enter = enter;\n update2._exit = exit;\n return update2;\n}\nfunction arraylike(data) {\n return typeof data === \"object\" && \"length\" in data ? data : Array.from(data);\n}\n\n// ../../node_modules/d3-selection/src/selection/exit.js\nfunction exit_default() {\n return new Selection2(this._exit || this._groups.map(sparse_default), this._parents);\n}\n\n// ../../node_modules/d3-selection/src/selection/join.js\nfunction join_default(onenter, onupdate, onexit) {\n var enter = this.enter(), update2 = this, exit = this.exit();\n if (typeof onenter === \"function\") {\n enter = onenter(enter);\n if (enter) enter = enter.selection();\n } else {\n enter = enter.append(onenter + \"\");\n }\n if (onupdate != null) {\n update2 = onupdate(update2);\n if (update2) update2 = update2.selection();\n }\n if (onexit == null) exit.remove();\n else onexit(exit);\n return enter && update2 ? enter.merge(update2).order() : update2;\n}\n\n// ../../node_modules/d3-selection/src/selection/merge.js\nfunction merge_default(context) {\n var selection2 = context.selection ? context.selection() : context;\n for (var groups0 = this._groups, groups1 = selection2._groups, m0 = groups0.length, m1 = groups1.length, m = Math.min(m0, m1), merges = new Array(m0), j = 0; j < m; ++j) {\n for (var group0 = groups0[j], group1 = groups1[j], n = group0.length, merge2 = merges[j] = new Array(n), node, i = 0; i < n; ++i) {\n if (node = group0[i] || group1[i]) {\n merge2[i] = node;\n }\n }\n }\n for (; j < m0; ++j) {\n merges[j] = groups0[j];\n }\n return new Selection2(merges, this._parents);\n}\n\n// ../../node_modules/d3-selection/src/selection/order.js\nfunction order_default() {\n for (var groups2 = this._groups, j = -1, m = groups2.length; ++j < m; ) {\n for (var group3 = groups2[j], i = group3.length - 1, next = group3[i], node; --i >= 0; ) {\n if (node = group3[i]) {\n if (next && node.compareDocumentPosition(next) ^ 4) next.parentNode.insertBefore(node, next);\n next = node;\n }\n }\n }\n return this;\n}\n\n// ../../node_modules/d3-selection/src/selection/sort.js\nfunction sort_default(compare) {\n if (!compare) compare = ascending2;\n function compareNode(a2, b) {\n return a2 && b ? compare(a2.__data__, b.__data__) : !a2 - !b;\n }\n for (var groups2 = this._groups, m = groups2.length, sortgroups = new Array(m), j = 0; j < m; ++j) {\n for (var group3 = groups2[j], n = group3.length, sortgroup = sortgroups[j] = new Array(n), node, i = 0; i < n; ++i) {\n if (node = group3[i]) {\n sortgroup[i] = node;\n }\n }\n sortgroup.sort(compareNode);\n }\n return new Selection2(sortgroups, this._parents).order();\n}\nfunction ascending2(a2, b) {\n return a2 < b ? -1 : a2 > b ? 1 : a2 >= b ? 0 : NaN;\n}\n\n// ../../node_modules/d3-selection/src/selection/call.js\nfunction call_default() {\n var callback = arguments[0];\n arguments[0] = this;\n callback.apply(null, arguments);\n return this;\n}\n\n// ../../node_modules/d3-selection/src/selection/nodes.js\nfunction nodes_default() {\n return Array.from(this);\n}\n\n// ../../node_modules/d3-selection/src/selection/node.js\nfunction node_default() {\n for (var groups2 = this._groups, j = 0, m = groups2.length; j < m; ++j) {\n for (var group3 = groups2[j], i = 0, n = group3.length; i < n; ++i) {\n var node = group3[i];\n if (node) return node;\n }\n }\n return null;\n}\n\n// ../../node_modules/d3-selection/src/selection/size.js\nfunction size_default() {\n let size = 0;\n for (const node of this) ++size;\n return size;\n}\n\n// ../../node_modules/d3-selection/src/selection/empty.js\nfunction empty_default() {\n return !this.node();\n}\n\n// ../../node_modules/d3-selection/src/selection/each.js\nfunction each_default(callback) {\n for (var groups2 = this._groups, j = 0, m = groups2.length; j < m; ++j) {\n for (var group3 = groups2[j], i = 0, n = group3.length, node; i < n; ++i) {\n if (node = group3[i]) callback.call(node, node.__data__, i, group3);\n }\n }\n return this;\n}\n\n// ../../node_modules/d3-selection/src/selection/attr.js\nfunction attrRemove(name2) {\n return function() {\n this.removeAttribute(name2);\n };\n}\nfunction attrRemoveNS(fullname) {\n return function() {\n this.removeAttributeNS(fullname.space, fullname.local);\n };\n}\nfunction attrConstant(name2, value) {\n return function() {\n this.setAttribute(name2, value);\n };\n}\nfunction attrConstantNS(fullname, value) {\n return function() {\n this.setAttributeNS(fullname.space, fullname.local, value);\n };\n}\nfunction attrFunction(name2, value) {\n return function() {\n var v2 = value.apply(this, arguments);\n if (v2 == null) this.removeAttribute(name2);\n else this.setAttribute(name2, v2);\n };\n}\nfunction attrFunctionNS(fullname, value) {\n return function() {\n var v2 = value.apply(this, arguments);\n if (v2 == null) this.removeAttributeNS(fullname.space, fullname.local);\n else this.setAttributeNS(fullname.space, fullname.local, v2);\n };\n}\nfunction attr_default(name2, value) {\n var fullname = namespace_default(name2);\n if (arguments.length < 2) {\n var node = this.node();\n return fullname.local ? node.getAttributeNS(fullname.space, fullname.local) : node.getAttribute(fullname);\n }\n return this.each((value == null ? fullname.local ? attrRemoveNS : attrRemove : typeof value === \"function\" ? fullname.local ? attrFunctionNS : attrFunction : fullname.local ? attrConstantNS : attrConstant)(fullname, value));\n}\n\n// ../../node_modules/d3-selection/src/window.js\nfunction window_default(node) {\n return node.ownerDocument && node.ownerDocument.defaultView || node.document && node || node.defaultView;\n}\n\n// ../../node_modules/d3-selection/src/selection/style.js\nfunction styleRemove(name2) {\n return function() {\n this.style.removeProperty(name2);\n };\n}\nfunction styleConstant(name2, value, priority) {\n return function() {\n this.style.setProperty(name2, value, priority);\n };\n}\nfunction styleFunction(name2, value, priority) {\n return function() {\n var v2 = value.apply(this, arguments);\n if (v2 == null) this.style.removeProperty(name2);\n else this.style.setProperty(name2, v2, priority);\n };\n}\nfunction style_default(name2, value, priority) {\n return arguments.length > 1 ? this.each((value == null ? styleRemove : typeof value === \"function\" ? styleFunction : styleConstant)(name2, value, priority == null ? \"\" : priority)) : styleValue(this.node(), name2);\n}\nfunction styleValue(node, name2) {\n return node.style.getPropertyValue(name2) || window_default(node).getComputedStyle(node, null).getPropertyValue(name2);\n}\n\n// ../../node_modules/d3-selection/src/selection/property.js\nfunction propertyRemove(name2) {\n return function() {\n delete this[name2];\n };\n}\nfunction propertyConstant(name2, value) {\n return function() {\n this[name2] = value;\n };\n}\nfunction propertyFunction(name2, value) {\n return function() {\n var v2 = value.apply(this, arguments);\n if (v2 == null) delete this[name2];\n else this[name2] = v2;\n };\n}\nfunction property_default(name2, value) {\n return arguments.length > 1 ? this.each((value == null ? propertyRemove : typeof value === \"function\" ? propertyFunction : propertyConstant)(name2, value)) : this.node()[name2];\n}\n\n// ../../node_modules/d3-selection/src/selection/classed.js\nfunction classArray(string2) {\n return string2.trim().split(/^|\\s+/);\n}\nfunction classList(node) {\n return node.classList || new ClassList(node);\n}\nfunction ClassList(node) {\n this._node = node;\n this._names = classArray(node.getAttribute(\"class\") || \"\");\n}\nClassList.prototype = {\n add: function(name2) {\n var i = this._names.indexOf(name2);\n if (i < 0) {\n this._names.push(name2);\n this._node.setAttribute(\"class\", this._names.join(\" \"));\n }\n },\n remove: function(name2) {\n var i = this._names.indexOf(name2);\n if (i >= 0) {\n this._names.splice(i, 1);\n this._node.setAttribute(\"class\", this._names.join(\" \"));\n }\n },\n contains: function(name2) {\n return this._names.indexOf(name2) >= 0;\n }\n};\nfunction classedAdd(node, names) {\n var list2 = classList(node), i = -1, n = names.length;\n while (++i < n) list2.add(names[i]);\n}\nfunction classedRemove(node, names) {\n var list2 = classList(node), i = -1, n = names.length;\n while (++i < n) list2.remove(names[i]);\n}\nfunction classedTrue(names) {\n return function() {\n classedAdd(this, names);\n };\n}\nfunction classedFalse(names) {\n return function() {\n classedRemove(this, names);\n };\n}\nfunction classedFunction(names, value) {\n return function() {\n (value.apply(this, arguments) ? classedAdd : classedRemove)(this, names);\n };\n}\nfunction classed_default(name2, value) {\n var names = classArray(name2 + \"\");\n if (arguments.length < 2) {\n var list2 = classList(this.node()), i = -1, n = names.length;\n while (++i < n) if (!list2.contains(names[i])) return false;\n return true;\n }\n return this.each((typeof value === \"function\" ? classedFunction : value ? classedTrue : classedFalse)(names, value));\n}\n\n// ../../node_modules/d3-selection/src/selection/text.js\nfunction textRemove() {\n this.textContent = \"\";\n}\nfunction textConstant(value) {\n return function() {\n this.textContent = value;\n };\n}\nfunction textFunction(value) {\n return function() {\n var v2 = value.apply(this, arguments);\n this.textContent = v2 == null ? \"\" : v2;\n };\n}\nfunction text_default(value) {\n return arguments.length ? this.each(value == null ? textRemove : (typeof value === \"function\" ? textFunction : textConstant)(value)) : this.node().textContent;\n}\n\n// ../../node_modules/d3-selection/src/selection/html.js\nfunction htmlRemove() {\n this.innerHTML = \"\";\n}\nfunction htmlConstant(value) {\n return function() {\n this.innerHTML = value;\n };\n}\nfunction htmlFunction(value) {\n return function() {\n var v2 = value.apply(this, arguments);\n this.innerHTML = v2 == null ? \"\" : v2;\n };\n}\nfunction html_default(value) {\n return arguments.length ? this.each(value == null ? htmlRemove : (typeof value === \"function\" ? htmlFunction : htmlConstant)(value)) : this.node().innerHTML;\n}\n\n// ../../node_modules/d3-selection/src/selection/raise.js\nfunction raise() {\n if (this.nextSibling) this.parentNode.appendChild(this);\n}\nfunction raise_default() {\n return this.each(raise);\n}\n\n// ../../node_modules/d3-selection/src/selection/lower.js\nfunction lower2() {\n if (this.previousSibling) this.parentNode.insertBefore(this, this.parentNode.firstChild);\n}\nfunction lower_default() {\n return this.each(lower2);\n}\n\n// ../../node_modules/d3-selection/src/selection/append.js\nfunction append_default(name2) {\n var create5 = typeof name2 === \"function\" ? name2 : creator_default(name2);\n return this.select(function() {\n return this.appendChild(create5.apply(this, arguments));\n });\n}\n\n// ../../node_modules/d3-selection/src/selection/insert.js\nfunction constantNull() {\n return null;\n}\nfunction insert_default(name2, before) {\n var create5 = typeof name2 === \"function\" ? name2 : creator_default(name2), select2 = before == null ? constantNull : typeof before === \"function\" ? before : selector_default(before);\n return this.select(function() {\n return this.insertBefore(create5.apply(this, arguments), select2.apply(this, arguments) || null);\n });\n}\n\n// ../../node_modules/d3-selection/src/selection/remove.js\nfunction remove() {\n var parent = this.parentNode;\n if (parent) parent.removeChild(this);\n}\nfunction remove_default() {\n return this.each(remove);\n}\n\n// ../../node_modules/d3-selection/src/selection/clone.js\nfunction selection_cloneShallow() {\n var clone = this.cloneNode(false), parent = this.parentNode;\n return parent ? parent.insertBefore(clone, this.nextSibling) : clone;\n}\nfunction selection_cloneDeep() {\n var clone = this.cloneNode(true), parent = this.parentNode;\n return parent ? parent.insertBefore(clone, this.nextSibling) : clone;\n}\nfunction clone_default(deep) {\n return this.select(deep ? selection_cloneDeep : selection_cloneShallow);\n}\n\n// ../../node_modules/d3-selection/src/selection/datum.js\nfunction datum_default(value) {\n return arguments.length ? this.property(\"__data__\", value) : this.node().__data__;\n}\n\n// ../../node_modules/d3-selection/src/selection/on.js\nfunction contextListener(listener) {\n return function(event) {\n listener.call(this, event, this.__data__);\n };\n}\nfunction parseTypenames2(typenames) {\n return typenames.trim().split(/^|\\s+/).map(function(t) {\n var name2 = \"\", i = t.indexOf(\".\");\n if (i >= 0) name2 = t.slice(i + 1), t = t.slice(0, i);\n return { type: t, name: name2 };\n });\n}\nfunction onRemove(typename) {\n return function() {\n var on = this.__on;\n if (!on) return;\n for (var j = 0, i = -1, m = on.length, o; j < m; ++j) {\n if (o = on[j], (!typename.type || o.type === typename.type) && o.name === typename.name) {\n this.removeEventListener(o.type, o.listener, o.options);\n } else {\n on[++i] = o;\n }\n }\n if (++i) on.length = i;\n else delete this.__on;\n };\n}\nfunction onAdd(typename, value, options) {\n return function() {\n var on = this.__on, o, listener = contextListener(value);\n if (on) for (var j = 0, m = on.length; j < m; ++j) {\n if ((o = on[j]).type === typename.type && o.name === typename.name) {\n this.removeEventListener(o.type, o.listener, o.options);\n this.addEventListener(o.type, o.listener = listener, o.options = options);\n o.value = value;\n return;\n }\n }\n this.addEventListener(typename.type, listener, options);\n o = { type: typename.type, name: typename.name, value, listener, options };\n if (!on) this.__on = [o];\n else on.push(o);\n };\n}\nfunction on_default(typename, value, options) {\n var typenames = parseTypenames2(typename + \"\"), i, n = typenames.length, t;\n if (arguments.length < 2) {\n var on = this.node().__on;\n if (on) for (var j = 0, m = on.length, o; j < m; ++j) {\n for (i = 0, o = on[j]; i < n; ++i) {\n if ((t = typenames[i]).type === o.type && t.name === o.name) {\n return o.value;\n }\n }\n }\n return;\n }\n on = value ? onAdd : onRemove;\n for (i = 0; i < n; ++i) this.each(on(typenames[i], value, options));\n return this;\n}\n\n// ../../node_modules/d3-selection/src/selection/dispatch.js\nfunction dispatchEvent(node, type2, params) {\n var window3 = window_default(node), event = window3.CustomEvent;\n if (typeof event === \"function\") {\n event = new event(type2, params);\n } else {\n event = window3.document.createEvent(\"Event\");\n if (params) event.initEvent(type2, params.bubbles, params.cancelable), event.detail = params.detail;\n else event.initEvent(type2, false, false);\n }\n node.dispatchEvent(event);\n}\nfunction dispatchConstant(type2, params) {\n return function() {\n return dispatchEvent(this, type2, params);\n };\n}\nfunction dispatchFunction(type2, params) {\n return function() {\n return dispatchEvent(this, type2, params.apply(this, arguments));\n };\n}\nfunction dispatch_default2(type2, params) {\n return this.each((typeof params === \"function\" ? dispatchFunction : dispatchConstant)(type2, params));\n}\n\n// ../../node_modules/d3-selection/src/selection/iterator.js\nfunction* iterator_default() {\n for (var groups2 = this._groups, j = 0, m = groups2.length; j < m; ++j) {\n for (var group3 = groups2[j], i = 0, n = group3.length, node; i < n; ++i) {\n if (node = group3[i]) yield node;\n }\n }\n}\n\n// ../../node_modules/d3-selection/src/selection/index.js\nvar root = [null];\nfunction Selection2(groups2, parents) {\n this._groups = groups2;\n this._parents = parents;\n}\nfunction selection() {\n return new Selection2([[document.documentElement]], root);\n}\nfunction selection_selection() {\n return this;\n}\nSelection2.prototype = selection.prototype = {\n constructor: Selection2,\n select: select_default,\n selectAll: selectAll_default,\n selectChild: selectChild_default,\n selectChildren: selectChildren_default,\n filter: filter_default,\n data: data_default,\n enter: enter_default,\n exit: exit_default,\n join: join_default,\n merge: merge_default,\n selection: selection_selection,\n order: order_default,\n sort: sort_default,\n call: call_default,\n nodes: nodes_default,\n node: node_default,\n size: size_default,\n empty: empty_default,\n each: each_default,\n attr: attr_default,\n style: style_default,\n property: property_default,\n classed: classed_default,\n text: text_default,\n html: html_default,\n raise: raise_default,\n lower: lower_default,\n append: append_default,\n insert: insert_default,\n remove: remove_default,\n clone: clone_default,\n datum: datum_default,\n on: on_default,\n dispatch: dispatch_default2,\n [Symbol.iterator]: iterator_default\n};\nvar selection_default = selection;\n\n// ../../node_modules/d3-selection/src/select.js\nfunction select_default2(selector) {\n return typeof selector === \"string\" ? new Selection2([[document.querySelector(selector)]], [document.documentElement]) : new Selection2([[selector]], root);\n}\n\n// ../../node_modules/d3-selection/src/sourceEvent.js\nfunction sourceEvent_default(event) {\n let sourceEvent;\n while (sourceEvent = event.sourceEvent) event = sourceEvent;\n return event;\n}\n\n// ../../node_modules/d3-selection/src/pointer.js\nfunction pointer_default(event, node) {\n event = sourceEvent_default(event);\n if (node === void 0) node = event.currentTarget;\n if (node) {\n var svg = node.ownerSVGElement || node;\n if (svg.createSVGPoint) {\n var point6 = svg.createSVGPoint();\n point6.x = event.clientX, point6.y = event.clientY;\n point6 = point6.matrixTransform(node.getScreenCTM().inverse());\n return [point6.x, point6.y];\n }\n if (node.getBoundingClientRect) {\n var rect3 = node.getBoundingClientRect();\n return [event.clientX - rect3.left - node.clientLeft, event.clientY - rect3.top - node.clientTop];\n }\n }\n return [event.pageX, event.pageY];\n}\n\n// ../../node_modules/d3-drag/src/noevent.js\nvar nonpassivecapture = { capture: true, passive: false };\nfunction noevent_default(event) {\n event.preventDefault();\n event.stopImmediatePropagation();\n}\n\n// ../../node_modules/d3-drag/src/nodrag.js\nfunction nodrag_default(view) {\n var root2 = view.document.documentElement, selection2 = select_default2(view).on(\"dragstart.drag\", noevent_default, nonpassivecapture);\n if (\"onselectstart\" in root2) {\n selection2.on(\"selectstart.drag\", noevent_default, nonpassivecapture);\n } else {\n root2.__noselect = root2.style.MozUserSelect;\n root2.style.MozUserSelect = \"none\";\n }\n}\nfunction yesdrag(view, noclick) {\n var root2 = view.document.documentElement, selection2 = select_default2(view).on(\"dragstart.drag\", null);\n if (noclick) {\n selection2.on(\"click.drag\", noevent_default, nonpassivecapture);\n setTimeout(function() {\n selection2.on(\"click.drag\", null);\n }, 0);\n }\n if (\"onselectstart\" in root2) {\n selection2.on(\"selectstart.drag\", null);\n } else {\n root2.style.MozUserSelect = root2.__noselect;\n delete root2.__noselect;\n }\n}\n\n// ../../node_modules/d3-color/src/define.js\nfunction define_default(constructor, factory, prototype) {\n constructor.prototype = factory.prototype = prototype;\n prototype.constructor = constructor;\n}\nfunction extend(parent, definition) {\n var prototype = Object.create(parent.prototype);\n for (var key in definition) prototype[key] = definition[key];\n return prototype;\n}\n\n// ../../node_modules/d3-color/src/color.js\nfunction Color() {\n}\nvar darker = 0.7;\nvar brighter = 1 / darker;\nvar reI = \"\\\\s*([+-]?\\\\d+)\\\\s*\";\nvar reN = \"\\\\s*([+-]?(?:\\\\d*\\\\.)?\\\\d+(?:[eE][+-]?\\\\d+)?)\\\\s*\";\nvar reP = \"\\\\s*([+-]?(?:\\\\d*\\\\.)?\\\\d+(?:[eE][+-]?\\\\d+)?)%\\\\s*\";\nvar reHex = /^#([0-9a-f]{3,8})$/;\nvar reRgbInteger = new RegExp(`^rgb\\\\(${reI},${reI},${reI}\\\\)$`);\nvar reRgbPercent = new RegExp(`^rgb\\\\(${reP},${reP},${reP}\\\\)$`);\nvar reRgbaInteger = new RegExp(`^rgba\\\\(${reI},${reI},${reI},${reN}\\\\)$`);\nvar reRgbaPercent = new RegExp(`^rgba\\\\(${reP},${reP},${reP},${reN}\\\\)$`);\nvar reHslPercent = new RegExp(`^hsl\\\\(${reN},${reP},${reP}\\\\)$`);\nvar reHslaPercent = new RegExp(`^hsla\\\\(${reN},${reP},${reP},${reN}\\\\)$`);\nvar named = {\n aliceblue: 15792383,\n antiquewhite: 16444375,\n aqua: 65535,\n aquamarine: 8388564,\n azure: 15794175,\n beige: 16119260,\n bisque: 16770244,\n black: 0,\n blanchedalmond: 16772045,\n blue: 255,\n blueviolet: 9055202,\n brown: 10824234,\n burlywood: 14596231,\n cadetblue: 6266528,\n chartreuse: 8388352,\n chocolate: 13789470,\n coral: 16744272,\n cornflowerblue: 6591981,\n cornsilk: 16775388,\n crimson: 14423100,\n cyan: 65535,\n darkblue: 139,\n darkcyan: 35723,\n darkgoldenrod: 12092939,\n darkgray: 11119017,\n darkgreen: 25600,\n darkgrey: 11119017,\n darkkhaki: 12433259,\n darkmagenta: 9109643,\n darkolivegreen: 5597999,\n darkorange: 16747520,\n darkorchid: 10040012,\n darkred: 9109504,\n darksalmon: 15308410,\n darkseagreen: 9419919,\n darkslateblue: 4734347,\n darkslategray: 3100495,\n darkslategrey: 3100495,\n darkturquoise: 52945,\n darkviolet: 9699539,\n deeppink: 16716947,\n deepskyblue: 49151,\n dimgray: 6908265,\n dimgrey: 6908265,\n dodgerblue: 2003199,\n firebrick: 11674146,\n floralwhite: 16775920,\n forestgreen: 2263842,\n fuchsia: 16711935,\n gainsboro: 14474460,\n ghostwhite: 16316671,\n gold: 16766720,\n goldenrod: 14329120,\n gray: 8421504,\n green: 32768,\n greenyellow: 11403055,\n grey: 8421504,\n honeydew: 15794160,\n hotpink: 16738740,\n indianred: 13458524,\n indigo: 4915330,\n ivory: 16777200,\n khaki: 15787660,\n lavender: 15132410,\n lavenderblush: 16773365,\n lawngreen: 8190976,\n lemonchiffon: 16775885,\n lightblue: 11393254,\n lightcoral: 15761536,\n lightcyan: 14745599,\n lightgoldenrodyellow: 16448210,\n lightgray: 13882323,\n lightgreen: 9498256,\n lightgrey: 13882323,\n lightpink: 16758465,\n lightsalmon: 16752762,\n lightseagreen: 2142890,\n lightskyblue: 8900346,\n lightslategray: 7833753,\n lightslategrey: 7833753,\n lightsteelblue: 11584734,\n lightyellow: 16777184,\n lime: 65280,\n limegreen: 3329330,\n linen: 16445670,\n magenta: 16711935,\n maroon: 8388608,\n mediumaquamarine: 6737322,\n mediumblue: 205,\n mediumorchid: 12211667,\n mediumpurple: 9662683,\n mediumseagreen: 3978097,\n mediumslateblue: 8087790,\n mediumspringgreen: 64154,\n mediumturquoise: 4772300,\n mediumvioletred: 13047173,\n midnightblue: 1644912,\n mintcream: 16121850,\n mistyrose: 16770273,\n moccasin: 16770229,\n navajowhite: 16768685,\n navy: 128,\n oldlace: 16643558,\n olive: 8421376,\n olivedrab: 7048739,\n orange: 16753920,\n orangered: 16729344,\n orchid: 14315734,\n palegoldenrod: 15657130,\n palegreen: 10025880,\n paleturquoise: 11529966,\n palevioletred: 14381203,\n papayawhip: 16773077,\n peachpuff: 16767673,\n peru: 13468991,\n pink: 16761035,\n plum: 14524637,\n powderblue: 11591910,\n purple: 8388736,\n rebeccapurple: 6697881,\n red: 16711680,\n rosybrown: 12357519,\n royalblue: 4286945,\n saddlebrown: 9127187,\n salmon: 16416882,\n sandybrown: 16032864,\n seagreen: 3050327,\n seashell: 16774638,\n sienna: 10506797,\n silver: 12632256,\n skyblue: 8900331,\n slateblue: 6970061,\n slategray: 7372944,\n slategrey: 7372944,\n snow: 16775930,\n springgreen: 65407,\n steelblue: 4620980,\n tan: 13808780,\n teal: 32896,\n thistle: 14204888,\n tomato: 16737095,\n turquoise: 4251856,\n violet: 15631086,\n wheat: 16113331,\n white: 16777215,\n whitesmoke: 16119285,\n yellow: 16776960,\n yellowgreen: 10145074\n};\ndefine_default(Color, color, {\n copy(channels) {\n return Object.assign(new this.constructor(), this, channels);\n },\n displayable() {\n return this.rgb().displayable();\n },\n hex: color_formatHex,\n // Deprecated! Use color.formatHex.\n formatHex: color_formatHex,\n formatHex8: color_formatHex8,\n formatHsl: color_formatHsl,\n formatRgb: color_formatRgb,\n toString: color_formatRgb\n});\nfunction color_formatHex() {\n return this.rgb().formatHex();\n}\nfunction color_formatHex8() {\n return this.rgb().formatHex8();\n}\nfunction color_formatHsl() {\n return hslConvert(this).formatHsl();\n}\nfunction color_formatRgb() {\n return this.rgb().formatRgb();\n}\nfunction color(format3) {\n var m, l;\n format3 = (format3 + \"\").trim().toLowerCase();\n return (m = reHex.exec(format3)) ? (l = m[1].length, m = parseInt(m[1], 16), l === 6 ? rgbn(m) : l === 3 ? new Rgb(m >> 8 & 15 | m >> 4 & 240, m >> 4 & 15 | m & 240, (m & 15) << 4 | m & 15, 1) : l === 8 ? rgba(m >> 24 & 255, m >> 16 & 255, m >> 8 & 255, (m & 255) / 255) : l === 4 ? rgba(m >> 12 & 15 | m >> 8 & 240, m >> 8 & 15 | m >> 4 & 240, m >> 4 & 15 | m & 240, ((m & 15) << 4 | m & 15) / 255) : null) : (m = reRgbInteger.exec(format3)) ? new Rgb(m[1], m[2], m[3], 1) : (m = reRgbPercent.exec(format3)) ? new Rgb(m[1] * 255 / 100, m[2] * 255 / 100, m[3] * 255 / 100, 1) : (m = reRgbaInteger.exec(format3)) ? rgba(m[1], m[2], m[3], m[4]) : (m = reRgbaPercent.exec(format3)) ? rgba(m[1] * 255 / 100, m[2] * 255 / 100, m[3] * 255 / 100, m[4]) : (m = reHslPercent.exec(format3)) ? hsla(m[1], m[2] / 100, m[3] / 100, 1) : (m = reHslaPercent.exec(format3)) ? hsla(m[1], m[2] / 100, m[3] / 100, m[4]) : named.hasOwnProperty(format3) ? rgbn(named[format3]) : format3 === \"transparent\" ? new Rgb(NaN, NaN, NaN, 0) : null;\n}\nfunction rgbn(n) {\n return new Rgb(n >> 16 & 255, n >> 8 & 255, n & 255, 1);\n}\nfunction rgba(r, g, b, a2) {\n if (a2 <= 0) r = g = b = NaN;\n return new Rgb(r, g, b, a2);\n}\nfunction rgbConvert(o) {\n if (!(o instanceof Color)) o = color(o);\n if (!o) return new Rgb();\n o = o.rgb();\n return new Rgb(o.r, o.g, o.b, o.opacity);\n}\nfunction rgb(r, g, b, opacity2) {\n return arguments.length === 1 ? rgbConvert(r) : new Rgb(r, g, b, opacity2 == null ? 1 : opacity2);\n}\nfunction Rgb(r, g, b, opacity2) {\n this.r = +r;\n this.g = +g;\n this.b = +b;\n this.opacity = +opacity2;\n}\ndefine_default(Rgb, rgb, extend(Color, {\n brighter(k2) {\n k2 = k2 == null ? brighter : Math.pow(brighter, k2);\n return new Rgb(this.r * k2, this.g * k2, this.b * k2, this.opacity);\n },\n darker(k2) {\n k2 = k2 == null ? darker : Math.pow(darker, k2);\n return new Rgb(this.r * k2, this.g * k2, this.b * k2, this.opacity);\n },\n rgb() {\n return this;\n },\n clamp() {\n return new Rgb(clampi(this.r), clampi(this.g), clampi(this.b), clampa(this.opacity));\n },\n displayable() {\n return -0.5 <= this.r && this.r < 255.5 && (-0.5 <= this.g && this.g < 255.5) && (-0.5 <= this.b && this.b < 255.5) && (0 <= this.opacity && this.opacity <= 1);\n },\n hex: rgb_formatHex,\n // Deprecated! Use color.formatHex.\n formatHex: rgb_formatHex,\n formatHex8: rgb_formatHex8,\n formatRgb: rgb_formatRgb,\n toString: rgb_formatRgb\n}));\nfunction rgb_formatHex() {\n return `#${hex(this.r)}${hex(this.g)}${hex(this.b)}`;\n}\nfunction rgb_formatHex8() {\n return `#${hex(this.r)}${hex(this.g)}${hex(this.b)}${hex((isNaN(this.opacity) ? 1 : this.opacity) * 255)}`;\n}\nfunction rgb_formatRgb() {\n const a2 = clampa(this.opacity);\n return `${a2 === 1 ? \"rgb(\" : \"rgba(\"}${clampi(this.r)}, ${clampi(this.g)}, ${clampi(this.b)}${a2 === 1 ? \")\" : `, ${a2})`}`;\n}\nfunction clampa(opacity2) {\n return isNaN(opacity2) ? 1 : Math.max(0, Math.min(1, opacity2));\n}\nfunction clampi(value) {\n return Math.max(0, Math.min(255, Math.round(value) || 0));\n}\nfunction hex(value) {\n value = clampi(value);\n return (value < 16 ? \"0\" : \"\") + value.toString(16);\n}\nfunction hsla(h, s2, l, a2) {\n if (a2 <= 0) h = s2 = l = NaN;\n else if (l <= 0 || l >= 1) h = s2 = NaN;\n else if (s2 <= 0) h = NaN;\n return new Hsl(h, s2, l, a2);\n}\nfunction hslConvert(o) {\n if (o instanceof Hsl) return new Hsl(o.h, o.s, o.l, o.opacity);\n if (!(o instanceof Color)) o = color(o);\n if (!o) return new Hsl();\n if (o instanceof Hsl) return o;\n o = o.rgb();\n var r = o.r / 255, g = o.g / 255, b = o.b / 255, min5 = Math.min(r, g, b), max4 = Math.max(r, g, b), h = NaN, s2 = max4 - min5, l = (max4 + min5) / 2;\n if (s2) {\n if (r === max4) h = (g - b) / s2 + (g < b) * 6;\n else if (g === max4) h = (b - r) / s2 + 2;\n else h = (r - g) / s2 + 4;\n s2 /= l < 0.5 ? max4 + min5 : 2 - max4 - min5;\n h *= 60;\n } else {\n s2 = l > 0 && l < 1 ? 0 : h;\n }\n return new Hsl(h, s2, l, o.opacity);\n}\nfunction hsl(h, s2, l, opacity2) {\n return arguments.length === 1 ? hslConvert(h) : new Hsl(h, s2, l, opacity2 == null ? 1 : opacity2);\n}\nfunction Hsl(h, s2, l, opacity2) {\n this.h = +h;\n this.s = +s2;\n this.l = +l;\n this.opacity = +opacity2;\n}\ndefine_default(Hsl, hsl, extend(Color, {\n brighter(k2) {\n k2 = k2 == null ? brighter : Math.pow(brighter, k2);\n return new Hsl(this.h, this.s, this.l * k2, this.opacity);\n },\n darker(k2) {\n k2 = k2 == null ? darker : Math.pow(darker, k2);\n return new Hsl(this.h, this.s, this.l * k2, this.opacity);\n },\n rgb() {\n var h = this.h % 360 + (this.h < 0) * 360, s2 = isNaN(h) || isNaN(this.s) ? 0 : this.s, l = this.l, m2 = l + (l < 0.5 ? l : 1 - l) * s2, m1 = 2 * l - m2;\n return new Rgb(\n hsl2rgb(h >= 240 ? h - 240 : h + 120, m1, m2),\n hsl2rgb(h, m1, m2),\n hsl2rgb(h < 120 ? h + 240 : h - 120, m1, m2),\n this.opacity\n );\n },\n clamp() {\n return new Hsl(clamph(this.h), clampt(this.s), clampt(this.l), clampa(this.opacity));\n },\n displayable() {\n return (0 <= this.s && this.s <= 1 || isNaN(this.s)) && (0 <= this.l && this.l <= 1) && (0 <= this.opacity && this.opacity <= 1);\n },\n formatHsl() {\n const a2 = clampa(this.opacity);\n return `${a2 === 1 ? \"hsl(\" : \"hsla(\"}${clamph(this.h)}, ${clampt(this.s) * 100}%, ${clampt(this.l) * 100}%${a2 === 1 ? \")\" : `, ${a2})`}`;\n }\n}));\nfunction clamph(value) {\n value = (value || 0) % 360;\n return value < 0 ? value + 360 : value;\n}\nfunction clampt(value) {\n return Math.max(0, Math.min(1, value || 0));\n}\nfunction hsl2rgb(h, m1, m2) {\n return (h < 60 ? m1 + (m2 - m1) * h / 60 : h < 180 ? m2 : h < 240 ? m1 + (m2 - m1) * (240 - h) / 60 : m1) * 255;\n}\n\n// ../../node_modules/d3-color/src/math.js\nvar radians = Math.PI / 180;\nvar degrees = 180 / Math.PI;\n\n// ../../node_modules/d3-color/src/lab.js\nvar K = 18;\nvar Xn = 0.96422;\nvar Yn = 1;\nvar Zn = 0.82521;\nvar t0 = 4 / 29;\nvar t1 = 6 / 29;\nvar t2 = 3 * t1 * t1;\nvar t3 = t1 * t1 * t1;\nfunction labConvert(o) {\n if (o instanceof Lab) return new Lab(o.l, o.a, o.b, o.opacity);\n if (o instanceof Hcl) return hcl2lab(o);\n if (!(o instanceof Rgb)) o = rgbConvert(o);\n var r = rgb2lrgb(o.r), g = rgb2lrgb(o.g), b = rgb2lrgb(o.b), y3 = xyz2lab((0.2225045 * r + 0.7168786 * g + 0.0606169 * b) / Yn), x3, z;\n if (r === g && g === b) x3 = z = y3;\n else {\n x3 = xyz2lab((0.4360747 * r + 0.3850649 * g + 0.1430804 * b) / Xn);\n z = xyz2lab((0.0139322 * r + 0.0971045 * g + 0.7141733 * b) / Zn);\n }\n return new Lab(116 * y3 - 16, 500 * (x3 - y3), 200 * (y3 - z), o.opacity);\n}\nfunction lab(l, a2, b, opacity2) {\n return arguments.length === 1 ? labConvert(l) : new Lab(l, a2, b, opacity2 == null ? 1 : opacity2);\n}\nfunction Lab(l, a2, b, opacity2) {\n this.l = +l;\n this.a = +a2;\n this.b = +b;\n this.opacity = +opacity2;\n}\ndefine_default(Lab, lab, extend(Color, {\n brighter(k2) {\n return new Lab(this.l + K * (k2 == null ? 1 : k2), this.a, this.b, this.opacity);\n },\n darker(k2) {\n return new Lab(this.l - K * (k2 == null ? 1 : k2), this.a, this.b, this.opacity);\n },\n rgb() {\n var y3 = (this.l + 16) / 116, x3 = isNaN(this.a) ? y3 : y3 + this.a / 500, z = isNaN(this.b) ? y3 : y3 - this.b / 200;\n x3 = Xn * lab2xyz(x3);\n y3 = Yn * lab2xyz(y3);\n z = Zn * lab2xyz(z);\n return new Rgb(\n lrgb2rgb(3.1338561 * x3 - 1.6168667 * y3 - 0.4906146 * z),\n lrgb2rgb(-0.9787684 * x3 + 1.9161415 * y3 + 0.033454 * z),\n lrgb2rgb(0.0719453 * x3 - 0.2289914 * y3 + 1.4052427 * z),\n this.opacity\n );\n }\n}));\nfunction xyz2lab(t) {\n return t > t3 ? Math.pow(t, 1 / 3) : t / t2 + t0;\n}\nfunction lab2xyz(t) {\n return t > t1 ? t * t * t : t2 * (t - t0);\n}\nfunction lrgb2rgb(x3) {\n return 255 * (x3 <= 31308e-7 ? 12.92 * x3 : 1.055 * Math.pow(x3, 1 / 2.4) - 0.055);\n}\nfunction rgb2lrgb(x3) {\n return (x3 /= 255) <= 0.04045 ? x3 / 12.92 : Math.pow((x3 + 0.055) / 1.055, 2.4);\n}\nfunction hclConvert(o) {\n if (o instanceof Hcl) return new Hcl(o.h, o.c, o.l, o.opacity);\n if (!(o instanceof Lab)) o = labConvert(o);\n if (o.a === 0 && o.b === 0) return new Hcl(NaN, 0 < o.l && o.l < 100 ? 0 : NaN, o.l, o.opacity);\n var h = Math.atan2(o.b, o.a) * degrees;\n return new Hcl(h < 0 ? h + 360 : h, Math.sqrt(o.a * o.a + o.b * o.b), o.l, o.opacity);\n}\nfunction hcl(h, c4, l, opacity2) {\n return arguments.length === 1 ? hclConvert(h) : new Hcl(h, c4, l, opacity2 == null ? 1 : opacity2);\n}\nfunction Hcl(h, c4, l, opacity2) {\n this.h = +h;\n this.c = +c4;\n this.l = +l;\n this.opacity = +opacity2;\n}\nfunction hcl2lab(o) {\n if (isNaN(o.h)) return new Lab(o.l, 0, 0, o.opacity);\n var h = o.h * radians;\n return new Lab(o.l, Math.cos(h) * o.c, Math.sin(h) * o.c, o.opacity);\n}\ndefine_default(Hcl, hcl, extend(Color, {\n brighter(k2) {\n return new Hcl(this.h, this.c, this.l + K * (k2 == null ? 1 : k2), this.opacity);\n },\n darker(k2) {\n return new Hcl(this.h, this.c, this.l - K * (k2 == null ? 1 : k2), this.opacity);\n },\n rgb() {\n return hcl2lab(this).rgb();\n }\n}));\n\n// ../../node_modules/d3-color/src/cubehelix.js\nvar A = -0.14861;\nvar B = 1.78277;\nvar C = -0.29227;\nvar D = -0.90649;\nvar E = 1.97294;\nvar ED = E * D;\nvar EB = E * B;\nvar BC_DA = B * C - D * A;\nfunction cubehelixConvert(o) {\n if (o instanceof Cubehelix) return new Cubehelix(o.h, o.s, o.l, o.opacity);\n if (!(o instanceof Rgb)) o = rgbConvert(o);\n var r = o.r / 255, g = o.g / 255, b = o.b / 255, l = (BC_DA * b + ED * r - EB * g) / (BC_DA + ED - EB), bl = b - l, k2 = (E * (g - l) - C * bl) / D, s2 = Math.sqrt(k2 * k2 + bl * bl) / (E * l * (1 - l)), h = s2 ? Math.atan2(k2, bl) * degrees - 120 : NaN;\n return new Cubehelix(h < 0 ? h + 360 : h, s2, l, o.opacity);\n}\nfunction cubehelix(h, s2, l, opacity2) {\n return arguments.length === 1 ? cubehelixConvert(h) : new Cubehelix(h, s2, l, opacity2 == null ? 1 : opacity2);\n}\nfunction Cubehelix(h, s2, l, opacity2) {\n this.h = +h;\n this.s = +s2;\n this.l = +l;\n this.opacity = +opacity2;\n}\ndefine_default(Cubehelix, cubehelix, extend(Color, {\n brighter(k2) {\n k2 = k2 == null ? brighter : Math.pow(brighter, k2);\n return new Cubehelix(this.h, this.s, this.l * k2, this.opacity);\n },\n darker(k2) {\n k2 = k2 == null ? darker : Math.pow(darker, k2);\n return new Cubehelix(this.h, this.s, this.l * k2, this.opacity);\n },\n rgb() {\n var h = isNaN(this.h) ? 0 : (this.h + 120) * radians, l = +this.l, a2 = isNaN(this.s) ? 0 : this.s * l * (1 - l), cosh2 = Math.cos(h), sinh2 = Math.sin(h);\n return new Rgb(\n 255 * (l + a2 * (A * cosh2 + B * sinh2)),\n 255 * (l + a2 * (C * cosh2 + D * sinh2)),\n 255 * (l + a2 * (E * cosh2)),\n this.opacity\n );\n }\n}));\n\n// ../../node_modules/d3-interpolate/src/basis.js\nfunction basis(t13, v0, v1, v2, v3) {\n var t22 = t13 * t13, t32 = t22 * t13;\n return ((1 - 3 * t13 + 3 * t22 - t32) * v0 + (4 - 6 * t22 + 3 * t32) * v1 + (1 + 3 * t13 + 3 * t22 - 3 * t32) * v2 + t32 * v3) / 6;\n}\nfunction basis_default(values2) {\n var n = values2.length - 1;\n return function(t) {\n var i = t <= 0 ? t = 0 : t >= 1 ? (t = 1, n - 1) : Math.floor(t * n), v1 = values2[i], v2 = values2[i + 1], v0 = i > 0 ? values2[i - 1] : 2 * v1 - v2, v3 = i < n - 1 ? values2[i + 2] : 2 * v2 - v1;\n return basis((t - i / n) * n, v0, v1, v2, v3);\n };\n}\n\n// ../../node_modules/d3-interpolate/src/basisClosed.js\nfunction basisClosed_default(values2) {\n var n = values2.length;\n return function(t) {\n var i = Math.floor(((t %= 1) < 0 ? ++t : t) * n), v0 = values2[(i + n - 1) % n], v1 = values2[i % n], v2 = values2[(i + 1) % n], v3 = values2[(i + 2) % n];\n return basis((t - i / n) * n, v0, v1, v2, v3);\n };\n}\n\n// ../../node_modules/d3-interpolate/src/constant.js\nvar constant_default2 = (x3) => () => x3;\n\n// ../../node_modules/d3-interpolate/src/color.js\nfunction linear(a2, d) {\n return function(t) {\n return a2 + t * d;\n };\n}\nfunction exponential(a2, b, y3) {\n return a2 = Math.pow(a2, y3), b = Math.pow(b, y3) - a2, y3 = 1 / y3, function(t) {\n return Math.pow(a2 + t * b, y3);\n };\n}\nfunction hue(a2, b) {\n var d = b - a2;\n return d ? linear(a2, d > 180 || d < -180 ? d - 360 * Math.round(d / 360) : d) : constant_default2(isNaN(a2) ? b : a2);\n}\nfunction gamma(y3) {\n return (y3 = +y3) === 1 ? nogamma : function(a2, b) {\n return b - a2 ? exponential(a2, b, y3) : constant_default2(isNaN(a2) ? b : a2);\n };\n}\nfunction nogamma(a2, b) {\n var d = b - a2;\n return d ? linear(a2, d) : constant_default2(isNaN(a2) ? b : a2);\n}\n\n// ../../node_modules/d3-interpolate/src/rgb.js\nvar rgb_default = function rgbGamma(y3) {\n var color3 = gamma(y3);\n function rgb2(start2, end) {\n var r = color3((start2 = rgb(start2)).r, (end = rgb(end)).r), g = color3(start2.g, end.g), b = color3(start2.b, end.b), opacity2 = nogamma(start2.opacity, end.opacity);\n return function(t) {\n start2.r = r(t);\n start2.g = g(t);\n start2.b = b(t);\n start2.opacity = opacity2(t);\n return start2 + \"\";\n };\n }\n rgb2.gamma = rgbGamma;\n return rgb2;\n}(1);\nfunction rgbSpline(spline) {\n return function(colors) {\n var n = colors.length, r = new Array(n), g = new Array(n), b = new Array(n), i, color3;\n for (i = 0; i < n; ++i) {\n color3 = rgb(colors[i]);\n r[i] = color3.r || 0;\n g[i] = color3.g || 0;\n b[i] = color3.b || 0;\n }\n r = spline(r);\n g = spline(g);\n b = spline(b);\n color3.opacity = 1;\n return function(t) {\n color3.r = r(t);\n color3.g = g(t);\n color3.b = b(t);\n return color3 + \"\";\n };\n };\n}\nvar rgbBasis = rgbSpline(basis_default);\nvar rgbBasisClosed = rgbSpline(basisClosed_default);\n\n// ../../node_modules/d3-interpolate/src/numberArray.js\nfunction numberArray_default(a2, b) {\n if (!b) b = [];\n var n = a2 ? Math.min(b.length, a2.length) : 0, c4 = b.slice(), i;\n return function(t) {\n for (i = 0; i < n; ++i) c4[i] = a2[i] * (1 - t) + b[i] * t;\n return c4;\n };\n}\nfunction isNumberArray(x3) {\n return ArrayBuffer.isView(x3) && !(x3 instanceof DataView);\n}\n\n// ../../node_modules/d3-interpolate/src/array.js\nfunction genericArray(a2, b) {\n var nb = b ? b.length : 0, na = a2 ? Math.min(nb, a2.length) : 0, x3 = new Array(na), c4 = new Array(nb), i;\n for (i = 0; i < na; ++i) x3[i] = value_default(a2[i], b[i]);\n for (; i < nb; ++i) c4[i] = b[i];\n return function(t) {\n for (i = 0; i < na; ++i) c4[i] = x3[i](t);\n return c4;\n };\n}\n\n// ../../node_modules/d3-interpolate/src/date.js\nfunction date_default(a2, b) {\n var d = /* @__PURE__ */ new Date();\n return a2 = +a2, b = +b, function(t) {\n return d.setTime(a2 * (1 - t) + b * t), d;\n };\n}\n\n// ../../node_modules/d3-interpolate/src/number.js\nfunction number_default(a2, b) {\n return a2 = +a2, b = +b, function(t) {\n return a2 * (1 - t) + b * t;\n };\n}\n\n// ../../node_modules/d3-interpolate/src/object.js\nfunction object_default(a2, b) {\n var i = {}, c4 = {}, k2;\n if (a2 === null || typeof a2 !== \"object\") a2 = {};\n if (b === null || typeof b !== \"object\") b = {};\n for (k2 in b) {\n if (k2 in a2) {\n i[k2] = value_default(a2[k2], b[k2]);\n } else {\n c4[k2] = b[k2];\n }\n }\n return function(t) {\n for (k2 in i) c4[k2] = i[k2](t);\n return c4;\n };\n}\n\n// ../../node_modules/d3-interpolate/src/string.js\nvar reA = /[-+]?(?:\\d+\\.?\\d*|\\.?\\d+)(?:[eE][-+]?\\d+)?/g;\nvar reB = new RegExp(reA.source, \"g\");\nfunction zero2(b) {\n return function() {\n return b;\n };\n}\nfunction one(b) {\n return function(t) {\n return b(t) + \"\";\n };\n}\nfunction string_default(a2, b) {\n var bi = reA.lastIndex = reB.lastIndex = 0, am, bm, bs, i = -1, s2 = [], q = [];\n a2 = a2 + \"\", b = b + \"\";\n while ((am = reA.exec(a2)) && (bm = reB.exec(b))) {\n if ((bs = bm.index) > bi) {\n bs = b.slice(bi, bs);\n if (s2[i]) s2[i] += bs;\n else s2[++i] = bs;\n }\n if ((am = am[0]) === (bm = bm[0])) {\n if (s2[i]) s2[i] += bm;\n else s2[++i] = bm;\n } else {\n s2[++i] = null;\n q.push({ i, x: number_default(am, bm) });\n }\n bi = reB.lastIndex;\n }\n if (bi < b.length) {\n bs = b.slice(bi);\n if (s2[i]) s2[i] += bs;\n else s2[++i] = bs;\n }\n return s2.length < 2 ? q[0] ? one(q[0].x) : zero2(b) : (b = q.length, function(t) {\n for (var i2 = 0, o; i2 < b; ++i2) s2[(o = q[i2]).i] = o.x(t);\n return s2.join(\"\");\n });\n}\n\n// ../../node_modules/d3-interpolate/src/value.js\nfunction value_default(a2, b) {\n var t = typeof b, c4;\n return b == null || t === \"boolean\" ? constant_default2(b) : (t === \"number\" ? number_default : t === \"string\" ? (c4 = color(b)) ? (b = c4, rgb_default) : string_default : b instanceof color ? rgb_default : b instanceof Date ? date_default : isNumberArray(b) ? numberArray_default : Array.isArray(b) ? genericArray : typeof b.valueOf !== \"function\" && typeof b.toString !== \"function\" || isNaN(b) ? object_default : number_default)(a2, b);\n}\n\n// ../../node_modules/d3-interpolate/src/round.js\nfunction round_default(a2, b) {\n return a2 = +a2, b = +b, function(t) {\n return Math.round(a2 * (1 - t) + b * t);\n };\n}\n\n// ../../node_modules/d3-interpolate/src/transform/decompose.js\nvar degrees2 = 180 / Math.PI;\nvar identity3 = {\n translateX: 0,\n translateY: 0,\n rotate: 0,\n skewX: 0,\n scaleX: 1,\n scaleY: 1\n};\nfunction decompose_default(a2, b, c4, d, e, f) {\n var scaleX, scaleY, skewX;\n if (scaleX = Math.sqrt(a2 * a2 + b * b)) a2 /= scaleX, b /= scaleX;\n if (skewX = a2 * c4 + b * d) c4 -= a2 * skewX, d -= b * skewX;\n if (scaleY = Math.sqrt(c4 * c4 + d * d)) c4 /= scaleY, d /= scaleY, skewX /= scaleY;\n if (a2 * d < b * c4) a2 = -a2, b = -b, skewX = -skewX, scaleX = -scaleX;\n return {\n translateX: e,\n translateY: f,\n rotate: Math.atan2(b, a2) * degrees2,\n skewX: Math.atan(skewX) * degrees2,\n scaleX,\n scaleY\n };\n}\n\n// ../../node_modules/d3-interpolate/src/transform/parse.js\nvar svgNode;\nfunction parseCss(value) {\n const m = new (typeof DOMMatrix === \"function\" ? DOMMatrix : WebKitCSSMatrix)(value + \"\");\n return m.isIdentity ? identity3 : decompose_default(m.a, m.b, m.c, m.d, m.e, m.f);\n}\nfunction parseSvg(value) {\n if (value == null) return identity3;\n if (!svgNode) svgNode = document.createElementNS(\"http://www.w3.org/2000/svg\", \"g\");\n svgNode.setAttribute(\"transform\", value);\n if (!(value = svgNode.transform.baseVal.consolidate())) return identity3;\n value = value.matrix;\n return decompose_default(value.a, value.b, value.c, value.d, value.e, value.f);\n}\n\n// ../../node_modules/d3-interpolate/src/transform/index.js\nfunction interpolateTransform(parse2, pxComma, pxParen, degParen) {\n function pop(s2) {\n return s2.length ? s2.pop() + \" \" : \"\";\n }\n function translate(xa, ya, xb, yb, s2, q) {\n if (xa !== xb || ya !== yb) {\n var i = s2.push(\"translate(\", null, pxComma, null, pxParen);\n q.push({ i: i - 4, x: number_default(xa, xb) }, { i: i - 2, x: number_default(ya, yb) });\n } else if (xb || yb) {\n s2.push(\"translate(\" + xb + pxComma + yb + pxParen);\n }\n }\n function rotate(a2, b, s2, q) {\n if (a2 !== b) {\n if (a2 - b > 180) b += 360;\n else if (b - a2 > 180) a2 += 360;\n q.push({ i: s2.push(pop(s2) + \"rotate(\", null, degParen) - 2, x: number_default(a2, b) });\n } else if (b) {\n s2.push(pop(s2) + \"rotate(\" + b + degParen);\n }\n }\n function skewX(a2, b, s2, q) {\n if (a2 !== b) {\n q.push({ i: s2.push(pop(s2) + \"skewX(\", null, degParen) - 2, x: number_default(a2, b) });\n } else if (b) {\n s2.push(pop(s2) + \"skewX(\" + b + degParen);\n }\n }\n function scale3(xa, ya, xb, yb, s2, q) {\n if (xa !== xb || ya !== yb) {\n var i = s2.push(pop(s2) + \"scale(\", null, \",\", null, \")\");\n q.push({ i: i - 4, x: number_default(xa, xb) }, { i: i - 2, x: number_default(ya, yb) });\n } else if (xb !== 1 || yb !== 1) {\n s2.push(pop(s2) + \"scale(\" + xb + \",\" + yb + \")\");\n }\n }\n return function(a2, b) {\n var s2 = [], q = [];\n a2 = parse2(a2), b = parse2(b);\n translate(a2.translateX, a2.translateY, b.translateX, b.translateY, s2, q);\n rotate(a2.rotate, b.rotate, s2, q);\n skewX(a2.skewX, b.skewX, s2, q);\n scale3(a2.scaleX, a2.scaleY, b.scaleX, b.scaleY, s2, q);\n a2 = b = null;\n return function(t) {\n var i = -1, n = q.length, o;\n while (++i < n) s2[(o = q[i]).i] = o.x(t);\n return s2.join(\"\");\n };\n };\n}\nvar interpolateTransformCss = interpolateTransform(parseCss, \"px, \", \"px)\", \"deg)\");\nvar interpolateTransformSvg = interpolateTransform(parseSvg, \", \", \")\", \")\");\n\n// ../../node_modules/d3-interpolate/src/zoom.js\nvar epsilon2 = 1e-12;\nfunction cosh(x3) {\n return ((x3 = Math.exp(x3)) + 1 / x3) / 2;\n}\nfunction sinh(x3) {\n return ((x3 = Math.exp(x3)) - 1 / x3) / 2;\n}\nfunction tanh(x3) {\n return ((x3 = Math.exp(2 * x3)) - 1) / (x3 + 1);\n}\nvar zoom_default = function zoomRho(rho, rho2, rho4) {\n function zoom2(p0, p1) {\n var ux0 = p0[0], uy0 = p0[1], w0 = p0[2], ux1 = p1[0], uy1 = p1[1], w1 = p1[2], dx = ux1 - ux0, dy = uy1 - uy0, d2 = dx * dx + dy * dy, i, S;\n if (d2 < epsilon2) {\n S = Math.log(w1 / w0) / rho;\n i = function(t) {\n return [\n ux0 + t * dx,\n uy0 + t * dy,\n w0 * Math.exp(rho * t * S)\n ];\n };\n } else {\n var d1 = Math.sqrt(d2), b0 = (w1 * w1 - w0 * w0 + rho4 * d2) / (2 * w0 * rho2 * d1), b1 = (w1 * w1 - w0 * w0 - rho4 * d2) / (2 * w1 * rho2 * d1), r0 = Math.log(Math.sqrt(b0 * b0 + 1) - b0), r1 = Math.log(Math.sqrt(b1 * b1 + 1) - b1);\n S = (r1 - r0) / rho;\n i = function(t) {\n var s2 = t * S, coshr0 = cosh(r0), u4 = w0 / (rho2 * d1) * (coshr0 * tanh(rho * s2 + r0) - sinh(r0));\n return [\n ux0 + u4 * dx,\n uy0 + u4 * dy,\n w0 * coshr0 / cosh(rho * s2 + r0)\n ];\n };\n }\n i.duration = S * 1e3 * rho / Math.SQRT2;\n return i;\n }\n zoom2.rho = function(_) {\n var _1 = Math.max(1e-3, +_), _2 = _1 * _1, _4 = _2 * _2;\n return zoomRho(_1, _2, _4);\n };\n return zoom2;\n}(Math.SQRT2, 2, 4);\n\n// ../../node_modules/d3-interpolate/src/hsl.js\nfunction hsl2(hue2) {\n return function(start2, end) {\n var h = hue2((start2 = hsl(start2)).h, (end = hsl(end)).h), s2 = nogamma(start2.s, end.s), l = nogamma(start2.l, end.l), opacity2 = nogamma(start2.opacity, end.opacity);\n return function(t) {\n start2.h = h(t);\n start2.s = s2(t);\n start2.l = l(t);\n start2.opacity = opacity2(t);\n return start2 + \"\";\n };\n };\n}\nvar hsl_default = hsl2(hue);\nvar hslLong = hsl2(nogamma);\n\n// ../../node_modules/d3-interpolate/src/lab.js\nfunction lab2(start2, end) {\n var l = nogamma((start2 = lab(start2)).l, (end = lab(end)).l), a2 = nogamma(start2.a, end.a), b = nogamma(start2.b, end.b), opacity2 = nogamma(start2.opacity, end.opacity);\n return function(t) {\n start2.l = l(t);\n start2.a = a2(t);\n start2.b = b(t);\n start2.opacity = opacity2(t);\n return start2 + \"\";\n };\n}\n\n// ../../node_modules/d3-interpolate/src/hcl.js\nfunction hcl2(hue2) {\n return function(start2, end) {\n var h = hue2((start2 = hcl(start2)).h, (end = hcl(end)).h), c4 = nogamma(start2.c, end.c), l = nogamma(start2.l, end.l), opacity2 = nogamma(start2.opacity, end.opacity);\n return function(t) {\n start2.h = h(t);\n start2.c = c4(t);\n start2.l = l(t);\n start2.opacity = opacity2(t);\n return start2 + \"\";\n };\n };\n}\nvar hcl_default = hcl2(hue);\nvar hclLong = hcl2(nogamma);\n\n// ../../node_modules/d3-interpolate/src/cubehelix.js\nfunction cubehelix2(hue2) {\n return function cubehelixGamma(y3) {\n y3 = +y3;\n function cubehelix3(start2, end) {\n var h = hue2((start2 = cubehelix(start2)).h, (end = cubehelix(end)).h), s2 = nogamma(start2.s, end.s), l = nogamma(start2.l, end.l), opacity2 = nogamma(start2.opacity, end.opacity);\n return function(t) {\n start2.h = h(t);\n start2.s = s2(t);\n start2.l = l(Math.pow(t, y3));\n start2.opacity = opacity2(t);\n return start2 + \"\";\n };\n }\n cubehelix3.gamma = cubehelixGamma;\n return cubehelix3;\n }(1);\n}\nvar cubehelix_default = cubehelix2(hue);\nvar cubehelixLong = cubehelix2(nogamma);\n\n// ../../node_modules/d3-interpolate/src/piecewise.js\nfunction piecewise(interpolate, values2) {\n if (values2 === void 0) values2 = interpolate, interpolate = value_default;\n var i = 0, n = values2.length - 1, v2 = values2[0], I = new Array(n < 0 ? 0 : n);\n while (i < n) I[i] = interpolate(v2, v2 = values2[++i]);\n return function(t) {\n var i2 = Math.max(0, Math.min(n - 1, Math.floor(t *= n)));\n return I[i2](t - i2);\n };\n}\n\n// ../../node_modules/d3-interpolate/src/quantize.js\nfunction quantize_default(interpolator, n) {\n var samples = new Array(n);\n for (var i = 0; i < n; ++i) samples[i] = interpolator(i / (n - 1));\n return samples;\n}\n\n// ../../node_modules/d3-timer/src/timer.js\nvar frame = 0;\nvar timeout = 0;\nvar interval2 = 0;\nvar pokeDelay = 1e3;\nvar taskHead;\nvar taskTail;\nvar clockLast = 0;\nvar clockNow = 0;\nvar clockSkew = 0;\nvar clock = typeof performance === \"object\" && performance.now ? performance : Date;\nvar setFrame = typeof window === \"object\" && window.requestAnimationFrame ? window.requestAnimationFrame.bind(window) : function(f) {\n setTimeout(f, 17);\n};\nfunction now() {\n return clockNow || (setFrame(clearNow), clockNow = clock.now() + clockSkew);\n}\nfunction clearNow() {\n clockNow = 0;\n}\nfunction Timer() {\n this._call = this._time = this._next = null;\n}\nTimer.prototype = timer.prototype = {\n constructor: Timer,\n restart: function(callback, delay, time3) {\n if (typeof callback !== \"function\") throw new TypeError(\"callback is not a function\");\n time3 = (time3 == null ? now() : +time3) + (delay == null ? 0 : +delay);\n if (!this._next && taskTail !== this) {\n if (taskTail) taskTail._next = this;\n else taskHead = this;\n taskTail = this;\n }\n this._call = callback;\n this._time = time3;\n sleep();\n },\n stop: function() {\n if (this._call) {\n this._call = null;\n this._time = Infinity;\n sleep();\n }\n }\n};\nfunction timer(callback, delay, time3) {\n var t = new Timer();\n t.restart(callback, delay, time3);\n return t;\n}\nfunction timerFlush() {\n now();\n ++frame;\n var t = taskHead, e;\n while (t) {\n if ((e = clockNow - t._time) >= 0) t._call.call(void 0, e);\n t = t._next;\n }\n --frame;\n}\nfunction wake() {\n clockNow = (clockLast = clock.now()) + clockSkew;\n frame = timeout = 0;\n try {\n timerFlush();\n } finally {\n frame = 0;\n nap();\n clockNow = 0;\n }\n}\nfunction poke() {\n var now2 = clock.now(), delay = now2 - clockLast;\n if (delay > pokeDelay) clockSkew -= delay, clockLast = now2;\n}\nfunction nap() {\n var t03, t13 = taskHead, t22, time3 = Infinity;\n while (t13) {\n if (t13._call) {\n if (time3 > t13._time) time3 = t13._time;\n t03 = t13, t13 = t13._next;\n } else {\n t22 = t13._next, t13._next = null;\n t13 = t03 ? t03._next = t22 : taskHead = t22;\n }\n }\n taskTail = t03;\n sleep(time3);\n}\nfunction sleep(time3) {\n if (frame) return;\n if (timeout) timeout = clearTimeout(timeout);\n var delay = time3 - clockNow;\n if (delay > 24) {\n if (time3 < Infinity) timeout = setTimeout(wake, time3 - clock.now() - clockSkew);\n if (interval2) interval2 = clearInterval(interval2);\n } else {\n if (!interval2) clockLast = clock.now(), interval2 = setInterval(poke, pokeDelay);\n frame = 1, setFrame(wake);\n }\n}\n\n// ../../node_modules/d3-timer/src/timeout.js\nfunction timeout_default(callback, delay, time3) {\n var t = new Timer();\n delay = delay == null ? 0 : +delay;\n t.restart((elapsed) => {\n t.stop();\n callback(elapsed + delay);\n }, delay, time3);\n return t;\n}\n\n// ../../node_modules/d3-transition/src/transition/schedule.js\nvar emptyOn = dispatch_default(\"start\", \"end\", \"cancel\", \"interrupt\");\nvar emptyTween = [];\nvar CREATED = 0;\nvar SCHEDULED = 1;\nvar STARTING = 2;\nvar STARTED = 3;\nvar RUNNING = 4;\nvar ENDING = 5;\nvar ENDED = 6;\nfunction schedule_default(node, name2, id2, index2, group3, timing) {\n var schedules = node.__transition;\n if (!schedules) node.__transition = {};\n else if (id2 in schedules) return;\n create3(node, id2, {\n name: name2,\n index: index2,\n // For context during callback.\n group: group3,\n // For context during callback.\n on: emptyOn,\n tween: emptyTween,\n time: timing.time,\n delay: timing.delay,\n duration: timing.duration,\n ease: timing.ease,\n timer: null,\n state: CREATED\n });\n}\nfunction init(node, id2) {\n var schedule = get2(node, id2);\n if (schedule.state > CREATED) throw new Error(\"too late; already scheduled\");\n return schedule;\n}\nfunction set2(node, id2) {\n var schedule = get2(node, id2);\n if (schedule.state > STARTED) throw new Error(\"too late; already running\");\n return schedule;\n}\nfunction get2(node, id2) {\n var schedule = node.__transition;\n if (!schedule || !(schedule = schedule[id2])) throw new Error(\"transition not found\");\n return schedule;\n}\nfunction create3(node, id2, self) {\n var schedules = node.__transition, tween;\n schedules[id2] = self;\n self.timer = timer(schedule, 0, self.time);\n function schedule(elapsed) {\n self.state = SCHEDULED;\n self.timer.restart(start2, self.delay, self.time);\n if (self.delay <= elapsed) start2(elapsed - self.delay);\n }\n function start2(elapsed) {\n var i, j, n, o;\n if (self.state !== SCHEDULED) return stop();\n for (i in schedules) {\n o = schedules[i];\n if (o.name !== self.name) continue;\n if (o.state === STARTED) return timeout_default(start2);\n if (o.state === RUNNING) {\n o.state = ENDED;\n o.timer.stop();\n o.on.call(\"interrupt\", node, node.__data__, o.index, o.group);\n delete schedules[i];\n } else if (+i < id2) {\n o.state = ENDED;\n o.timer.stop();\n o.on.call(\"cancel\", node, node.__data__, o.index, o.group);\n delete schedules[i];\n }\n }\n timeout_default(function() {\n if (self.state === STARTED) {\n self.state = RUNNING;\n self.timer.restart(tick, self.delay, self.time);\n tick(elapsed);\n }\n });\n self.state = STARTING;\n self.on.call(\"start\", node, node.__data__, self.index, self.group);\n if (self.state !== STARTING) return;\n self.state = STARTED;\n tween = new Array(n = self.tween.length);\n for (i = 0, j = -1; i < n; ++i) {\n if (o = self.tween[i].value.call(node, node.__data__, self.index, self.group)) {\n tween[++j] = o;\n }\n }\n tween.length = j + 1;\n }\n function tick(elapsed) {\n var t = elapsed < self.duration ? self.ease.call(null, elapsed / self.duration) : (self.timer.restart(stop), self.state = ENDING, 1), i = -1, n = tween.length;\n while (++i < n) {\n tween[i].call(node, t);\n }\n if (self.state === ENDING) {\n self.on.call(\"end\", node, node.__data__, self.index, self.group);\n stop();\n }\n }\n function stop() {\n self.state = ENDED;\n self.timer.stop();\n delete schedules[id2];\n for (var i in schedules) return;\n delete node.__transition;\n }\n}\n\n// ../../node_modules/d3-transition/src/interrupt.js\nfunction interrupt_default(node, name2) {\n var schedules = node.__transition, schedule, active, empty4 = true, i;\n if (!schedules) return;\n name2 = name2 == null ? null : name2 + \"\";\n for (i in schedules) {\n if ((schedule = schedules[i]).name !== name2) {\n empty4 = false;\n continue;\n }\n active = schedule.state > STARTING && schedule.state < ENDING;\n schedule.state = ENDED;\n schedule.timer.stop();\n schedule.on.call(active ? \"interrupt\" : \"cancel\", node, node.__data__, schedule.index, schedule.group);\n delete schedules[i];\n }\n if (empty4) delete node.__transition;\n}\n\n// ../../node_modules/d3-transition/src/selection/interrupt.js\nfunction interrupt_default2(name2) {\n return this.each(function() {\n interrupt_default(this, name2);\n });\n}\n\n// ../../node_modules/d3-transition/src/transition/tween.js\nfunction tweenRemove(id2, name2) {\n var tween0, tween1;\n return function() {\n var schedule = set2(this, id2), tween = schedule.tween;\n if (tween !== tween0) {\n tween1 = tween0 = tween;\n for (var i = 0, n = tween1.length; i < n; ++i) {\n if (tween1[i].name === name2) {\n tween1 = tween1.slice();\n tween1.splice(i, 1);\n break;\n }\n }\n }\n schedule.tween = tween1;\n };\n}\nfunction tweenFunction(id2, name2, value) {\n var tween0, tween1;\n if (typeof value !== \"function\") throw new Error();\n return function() {\n var schedule = set2(this, id2), tween = schedule.tween;\n if (tween !== tween0) {\n tween1 = (tween0 = tween).slice();\n for (var t = { name: name2, value }, i = 0, n = tween1.length; i < n; ++i) {\n if (tween1[i].name === name2) {\n tween1[i] = t;\n break;\n }\n }\n if (i === n) tween1.push(t);\n }\n schedule.tween = tween1;\n };\n}\nfunction tween_default(name2, value) {\n var id2 = this._id;\n name2 += \"\";\n if (arguments.length < 2) {\n var tween = get2(this.node(), id2).tween;\n for (var i = 0, n = tween.length, t; i < n; ++i) {\n if ((t = tween[i]).name === name2) {\n return t.value;\n }\n }\n return null;\n }\n return this.each((value == null ? tweenRemove : tweenFunction)(id2, name2, value));\n}\nfunction tweenValue(transition2, name2, value) {\n var id2 = transition2._id;\n transition2.each(function() {\n var schedule = set2(this, id2);\n (schedule.value || (schedule.value = {}))[name2] = value.apply(this, arguments);\n });\n return function(node) {\n return get2(node, id2).value[name2];\n };\n}\n\n// ../../node_modules/d3-transition/src/transition/interpolate.js\nfunction interpolate_default(a2, b) {\n var c4;\n return (typeof b === \"number\" ? number_default : b instanceof color ? rgb_default : (c4 = color(b)) ? (b = c4, rgb_default) : string_default)(a2, b);\n}\n\n// ../../node_modules/d3-transition/src/transition/attr.js\nfunction attrRemove2(name2) {\n return function() {\n this.removeAttribute(name2);\n };\n}\nfunction attrRemoveNS2(fullname) {\n return function() {\n this.removeAttributeNS(fullname.space, fullname.local);\n };\n}\nfunction attrConstant2(name2, interpolate, value1) {\n var string00, string1 = value1 + \"\", interpolate0;\n return function() {\n var string0 = this.getAttribute(name2);\n return string0 === string1 ? null : string0 === string00 ? interpolate0 : interpolate0 = interpolate(string00 = string0, value1);\n };\n}\nfunction attrConstantNS2(fullname, interpolate, value1) {\n var string00, string1 = value1 + \"\", interpolate0;\n return function() {\n var string0 = this.getAttributeNS(fullname.space, fullname.local);\n return string0 === string1 ? null : string0 === string00 ? interpolate0 : interpolate0 = interpolate(string00 = string0, value1);\n };\n}\nfunction attrFunction2(name2, interpolate, value) {\n var string00, string10, interpolate0;\n return function() {\n var string0, value1 = value(this), string1;\n if (value1 == null) return void this.removeAttribute(name2);\n string0 = this.getAttribute(name2);\n string1 = value1 + \"\";\n return string0 === string1 ? null : string0 === string00 && string1 === string10 ? interpolate0 : (string10 = string1, interpolate0 = interpolate(string00 = string0, value1));\n };\n}\nfunction attrFunctionNS2(fullname, interpolate, value) {\n var string00, string10, interpolate0;\n return function() {\n var string0, value1 = value(this), string1;\n if (value1 == null) return void this.removeAttributeNS(fullname.space, fullname.local);\n string0 = this.getAttributeNS(fullname.space, fullname.local);\n string1 = value1 + \"\";\n return string0 === string1 ? null : string0 === string00 && string1 === string10 ? interpolate0 : (string10 = string1, interpolate0 = interpolate(string00 = string0, value1));\n };\n}\nfunction attr_default2(name2, value) {\n var fullname = namespace_default(name2), i = fullname === \"transform\" ? interpolateTransformSvg : interpolate_default;\n return this.attrTween(name2, typeof value === \"function\" ? (fullname.local ? attrFunctionNS2 : attrFunction2)(fullname, i, tweenValue(this, \"attr.\" + name2, value)) : value == null ? (fullname.local ? attrRemoveNS2 : attrRemove2)(fullname) : (fullname.local ? attrConstantNS2 : attrConstant2)(fullname, i, value));\n}\n\n// ../../node_modules/d3-transition/src/transition/attrTween.js\nfunction attrInterpolate(name2, i) {\n return function(t) {\n this.setAttribute(name2, i.call(this, t));\n };\n}\nfunction attrInterpolateNS(fullname, i) {\n return function(t) {\n this.setAttributeNS(fullname.space, fullname.local, i.call(this, t));\n };\n}\nfunction attrTweenNS(fullname, value) {\n var t03, i0;\n function tween() {\n var i = value.apply(this, arguments);\n if (i !== i0) t03 = (i0 = i) && attrInterpolateNS(fullname, i);\n return t03;\n }\n tween._value = value;\n return tween;\n}\nfunction attrTween(name2, value) {\n var t03, i0;\n function tween() {\n var i = value.apply(this, arguments);\n if (i !== i0) t03 = (i0 = i) && attrInterpolate(name2, i);\n return t03;\n }\n tween._value = value;\n return tween;\n}\nfunction attrTween_default(name2, value) {\n var key = \"attr.\" + name2;\n if (arguments.length < 2) return (key = this.tween(key)) && key._value;\n if (value == null) return this.tween(key, null);\n if (typeof value !== \"function\") throw new Error();\n var fullname = namespace_default(name2);\n return this.tween(key, (fullname.local ? attrTweenNS : attrTween)(fullname, value));\n}\n\n// ../../node_modules/d3-transition/src/transition/delay.js\nfunction delayFunction(id2, value) {\n return function() {\n init(this, id2).delay = +value.apply(this, arguments);\n };\n}\nfunction delayConstant(id2, value) {\n return value = +value, function() {\n init(this, id2).delay = value;\n };\n}\nfunction delay_default(value) {\n var id2 = this._id;\n return arguments.length ? this.each((typeof value === \"function\" ? delayFunction : delayConstant)(id2, value)) : get2(this.node(), id2).delay;\n}\n\n// ../../node_modules/d3-transition/src/transition/duration.js\nfunction durationFunction(id2, value) {\n return function() {\n set2(this, id2).duration = +value.apply(this, arguments);\n };\n}\nfunction durationConstant(id2, value) {\n return value = +value, function() {\n set2(this, id2).duration = value;\n };\n}\nfunction duration_default(value) {\n var id2 = this._id;\n return arguments.length ? this.each((typeof value === \"function\" ? durationFunction : durationConstant)(id2, value)) : get2(this.node(), id2).duration;\n}\n\n// ../../node_modules/d3-transition/src/transition/ease.js\nfunction easeConstant(id2, value) {\n if (typeof value !== \"function\") throw new Error();\n return function() {\n set2(this, id2).ease = value;\n };\n}\nfunction ease_default(value) {\n var id2 = this._id;\n return arguments.length ? this.each(easeConstant(id2, value)) : get2(this.node(), id2).ease;\n}\n\n// ../../node_modules/d3-transition/src/transition/easeVarying.js\nfunction easeVarying(id2, value) {\n return function() {\n var v2 = value.apply(this, arguments);\n if (typeof v2 !== \"function\") throw new Error();\n set2(this, id2).ease = v2;\n };\n}\nfunction easeVarying_default(value) {\n if (typeof value !== \"function\") throw new Error();\n return this.each(easeVarying(this._id, value));\n}\n\n// ../../node_modules/d3-transition/src/transition/filter.js\nfunction filter_default2(match) {\n if (typeof match !== \"function\") match = matcher_default(match);\n for (var groups2 = this._groups, m = groups2.length, subgroups = new Array(m), j = 0; j < m; ++j) {\n for (var group3 = groups2[j], n = group3.length, subgroup = subgroups[j] = [], node, i = 0; i < n; ++i) {\n if ((node = group3[i]) && match.call(node, node.__data__, i, group3)) {\n subgroup.push(node);\n }\n }\n }\n return new Transition(subgroups, this._parents, this._name, this._id);\n}\n\n// ../../node_modules/d3-transition/src/transition/merge.js\nfunction merge_default2(transition2) {\n if (transition2._id !== this._id) throw new Error();\n for (var groups0 = this._groups, groups1 = transition2._groups, m0 = groups0.length, m1 = groups1.length, m = Math.min(m0, m1), merges = new Array(m0), j = 0; j < m; ++j) {\n for (var group0 = groups0[j], group1 = groups1[j], n = group0.length, merge2 = merges[j] = new Array(n), node, i = 0; i < n; ++i) {\n if (node = group0[i] || group1[i]) {\n merge2[i] = node;\n }\n }\n }\n for (; j < m0; ++j) {\n merges[j] = groups0[j];\n }\n return new Transition(merges, this._parents, this._name, this._id);\n}\n\n// ../../node_modules/d3-transition/src/transition/on.js\nfunction start(name2) {\n return (name2 + \"\").trim().split(/^|\\s+/).every(function(t) {\n var i = t.indexOf(\".\");\n if (i >= 0) t = t.slice(0, i);\n return !t || t === \"start\";\n });\n}\nfunction onFunction(id2, name2, listener) {\n var on0, on1, sit = start(name2) ? init : set2;\n return function() {\n var schedule = sit(this, id2), on = schedule.on;\n if (on !== on0) (on1 = (on0 = on).copy()).on(name2, listener);\n schedule.on = on1;\n };\n}\nfunction on_default2(name2, listener) {\n var id2 = this._id;\n return arguments.length < 2 ? get2(this.node(), id2).on.on(name2) : this.each(onFunction(id2, name2, listener));\n}\n\n// ../../node_modules/d3-transition/src/transition/remove.js\nfunction removeFunction(id2) {\n return function() {\n var parent = this.parentNode;\n for (var i in this.__transition) if (+i !== id2) return;\n if (parent) parent.removeChild(this);\n };\n}\nfunction remove_default2() {\n return this.on(\"end.remove\", removeFunction(this._id));\n}\n\n// ../../node_modules/d3-transition/src/transition/select.js\nfunction select_default3(select2) {\n var name2 = this._name, id2 = this._id;\n if (typeof select2 !== \"function\") select2 = selector_default(select2);\n for (var groups2 = this._groups, m = groups2.length, subgroups = new Array(m), j = 0; j < m; ++j) {\n for (var group3 = groups2[j], n = group3.length, subgroup = subgroups[j] = new Array(n), node, subnode, i = 0; i < n; ++i) {\n if ((node = group3[i]) && (subnode = select2.call(node, node.__data__, i, group3))) {\n if (\"__data__\" in node) subnode.__data__ = node.__data__;\n subgroup[i] = subnode;\n schedule_default(subgroup[i], name2, id2, i, subgroup, get2(node, id2));\n }\n }\n }\n return new Transition(subgroups, this._parents, name2, id2);\n}\n\n// ../../node_modules/d3-transition/src/transition/selectAll.js\nfunction selectAll_default2(select2) {\n var name2 = this._name, id2 = this._id;\n if (typeof select2 !== \"function\") select2 = selectorAll_default(select2);\n for (var groups2 = this._groups, m = groups2.length, subgroups = [], parents = [], j = 0; j < m; ++j) {\n for (var group3 = groups2[j], n = group3.length, node, i = 0; i < n; ++i) {\n if (node = group3[i]) {\n for (var children2 = select2.call(node, node.__data__, i, group3), child, inherit3 = get2(node, id2), k2 = 0, l = children2.length; k2 < l; ++k2) {\n if (child = children2[k2]) {\n schedule_default(child, name2, id2, k2, children2, inherit3);\n }\n }\n subgroups.push(children2);\n parents.push(node);\n }\n }\n }\n return new Transition(subgroups, parents, name2, id2);\n}\n\n// ../../node_modules/d3-transition/src/transition/selection.js\nvar Selection3 = selection_default.prototype.constructor;\nfunction selection_default2() {\n return new Selection3(this._groups, this._parents);\n}\n\n// ../../node_modules/d3-transition/src/transition/style.js\nfunction styleNull(name2, interpolate) {\n var string00, string10, interpolate0;\n return function() {\n var string0 = styleValue(this, name2), string1 = (this.style.removeProperty(name2), styleValue(this, name2));\n return string0 === string1 ? null : string0 === string00 && string1 === string10 ? interpolate0 : interpolate0 = interpolate(string00 = string0, string10 = string1);\n };\n}\nfunction styleRemove2(name2) {\n return function() {\n this.style.removeProperty(name2);\n };\n}\nfunction styleConstant2(name2, interpolate, value1) {\n var string00, string1 = value1 + \"\", interpolate0;\n return function() {\n var string0 = styleValue(this, name2);\n return string0 === string1 ? null : string0 === string00 ? interpolate0 : interpolate0 = interpolate(string00 = string0, value1);\n };\n}\nfunction styleFunction2(name2, interpolate, value) {\n var string00, string10, interpolate0;\n return function() {\n var string0 = styleValue(this, name2), value1 = value(this), string1 = value1 + \"\";\n if (value1 == null) string1 = value1 = (this.style.removeProperty(name2), styleValue(this, name2));\n return string0 === string1 ? null : string0 === string00 && string1 === string10 ? interpolate0 : (string10 = string1, interpolate0 = interpolate(string00 = string0, value1));\n };\n}\nfunction styleMaybeRemove(id2, name2) {\n var on0, on1, listener0, key = \"style.\" + name2, event = \"end.\" + key, remove2;\n return function() {\n var schedule = set2(this, id2), on = schedule.on, listener = schedule.value[key] == null ? remove2 || (remove2 = styleRemove2(name2)) : void 0;\n if (on !== on0 || listener0 !== listener) (on1 = (on0 = on).copy()).on(event, listener0 = listener);\n schedule.on = on1;\n };\n}\nfunction style_default2(name2, value, priority) {\n var i = (name2 += \"\") === \"transform\" ? interpolateTransformCss : interpolate_default;\n return value == null ? this.styleTween(name2, styleNull(name2, i)).on(\"end.style.\" + name2, styleRemove2(name2)) : typeof value === \"function\" ? this.styleTween(name2, styleFunction2(name2, i, tweenValue(this, \"style.\" + name2, value))).each(styleMaybeRemove(this._id, name2)) : this.styleTween(name2, styleConstant2(name2, i, value), priority).on(\"end.style.\" + name2, null);\n}\n\n// ../../node_modules/d3-transition/src/transition/styleTween.js\nfunction styleInterpolate(name2, i, priority) {\n return function(t) {\n this.style.setProperty(name2, i.call(this, t), priority);\n };\n}\nfunction styleTween(name2, value, priority) {\n var t, i0;\n function tween() {\n var i = value.apply(this, arguments);\n if (i !== i0) t = (i0 = i) && styleInterpolate(name2, i, priority);\n return t;\n }\n tween._value = value;\n return tween;\n}\nfunction styleTween_default(name2, value, priority) {\n var key = \"style.\" + (name2 += \"\");\n if (arguments.length < 2) return (key = this.tween(key)) && key._value;\n if (value == null) return this.tween(key, null);\n if (typeof value !== \"function\") throw new Error();\n return this.tween(key, styleTween(name2, value, priority == null ? \"\" : priority));\n}\n\n// ../../node_modules/d3-transition/src/transition/text.js\nfunction textConstant2(value) {\n return function() {\n this.textContent = value;\n };\n}\nfunction textFunction2(value) {\n return function() {\n var value1 = value(this);\n this.textContent = value1 == null ? \"\" : value1;\n };\n}\nfunction text_default2(value) {\n return this.tween(\"text\", typeof value === \"function\" ? textFunction2(tweenValue(this, \"text\", value)) : textConstant2(value == null ? \"\" : value + \"\"));\n}\n\n// ../../node_modules/d3-transition/src/transition/textTween.js\nfunction textInterpolate(i) {\n return function(t) {\n this.textContent = i.call(this, t);\n };\n}\nfunction textTween(value) {\n var t03, i0;\n function tween() {\n var i = value.apply(this, arguments);\n if (i !== i0) t03 = (i0 = i) && textInterpolate(i);\n return t03;\n }\n tween._value = value;\n return tween;\n}\nfunction textTween_default(value) {\n var key = \"text\";\n if (arguments.length < 1) return (key = this.tween(key)) && key._value;\n if (value == null) return this.tween(key, null);\n if (typeof value !== \"function\") throw new Error();\n return this.tween(key, textTween(value));\n}\n\n// ../../node_modules/d3-transition/src/transition/transition.js\nfunction transition_default() {\n var name2 = this._name, id0 = this._id, id1 = newId();\n for (var groups2 = this._groups, m = groups2.length, j = 0; j < m; ++j) {\n for (var group3 = groups2[j], n = group3.length, node, i = 0; i < n; ++i) {\n if (node = group3[i]) {\n var inherit3 = get2(node, id0);\n schedule_default(node, name2, id1, i, group3, {\n time: inherit3.time + inherit3.delay + inherit3.duration,\n delay: 0,\n duration: inherit3.duration,\n ease: inherit3.ease\n });\n }\n }\n }\n return new Transition(groups2, this._parents, name2, id1);\n}\n\n// ../../node_modules/d3-transition/src/transition/end.js\nfunction end_default() {\n var on0, on1, that = this, id2 = that._id, size = that.size();\n return new Promise(function(resolve, reject) {\n var cancel = { value: reject }, end = { value: function() {\n if (--size === 0) resolve();\n } };\n that.each(function() {\n var schedule = set2(this, id2), on = schedule.on;\n if (on !== on0) {\n on1 = (on0 = on).copy();\n on1._.cancel.push(cancel);\n on1._.interrupt.push(cancel);\n on1._.end.push(end);\n }\n schedule.on = on1;\n });\n if (size === 0) resolve();\n });\n}\n\n// ../../node_modules/d3-transition/src/transition/index.js\nvar id = 0;\nfunction Transition(groups2, parents, name2, id2) {\n this._groups = groups2;\n this._parents = parents;\n this._name = name2;\n this._id = id2;\n}\nfunction transition(name2) {\n return selection_default().transition(name2);\n}\nfunction newId() {\n return ++id;\n}\nvar selection_prototype = selection_default.prototype;\nTransition.prototype = transition.prototype = {\n constructor: Transition,\n select: select_default3,\n selectAll: selectAll_default2,\n selectChild: selection_prototype.selectChild,\n selectChildren: selection_prototype.selectChildren,\n filter: filter_default2,\n merge: merge_default2,\n selection: selection_default2,\n transition: transition_default,\n call: selection_prototype.call,\n nodes: selection_prototype.nodes,\n node: selection_prototype.node,\n size: selection_prototype.size,\n empty: selection_prototype.empty,\n each: selection_prototype.each,\n on: on_default2,\n attr: attr_default2,\n attrTween: attrTween_default,\n style: style_default2,\n styleTween: styleTween_default,\n text: text_default2,\n textTween: textTween_default,\n remove: remove_default2,\n tween: tween_default,\n delay: delay_default,\n duration: duration_default,\n ease: ease_default,\n easeVarying: easeVarying_default,\n end: end_default,\n [Symbol.iterator]: selection_prototype[Symbol.iterator]\n};\n\n// ../../node_modules/d3-ease/src/cubic.js\nfunction cubicInOut(t) {\n return ((t *= 2) <= 1 ? t * t * t : (t -= 2) * t * t + 2) / 2;\n}\n\n// ../../node_modules/d3-transition/src/selection/transition.js\nvar defaultTiming = {\n time: null,\n // Set on use.\n delay: 0,\n duration: 250,\n ease: cubicInOut\n};\nfunction inherit(node, id2) {\n var timing;\n while (!(timing = node.__transition) || !(timing = timing[id2])) {\n if (!(node = node.parentNode)) {\n throw new Error(`transition ${id2} not found`);\n }\n }\n return timing;\n}\nfunction transition_default2(name2) {\n var id2, timing;\n if (name2 instanceof Transition) {\n id2 = name2._id, name2 = name2._name;\n } else {\n id2 = newId(), (timing = defaultTiming).time = now(), name2 = name2 == null ? null : name2 + \"\";\n }\n for (var groups2 = this._groups, m = groups2.length, j = 0; j < m; ++j) {\n for (var group3 = groups2[j], n = group3.length, node, i = 0; i < n; ++i) {\n if (node = group3[i]) {\n schedule_default(node, name2, id2, i, group3, timing || inherit(node, id2));\n }\n }\n }\n return new Transition(groups2, this._parents, name2, id2);\n}\n\n// ../../node_modules/d3-transition/src/selection/index.js\nselection_default.prototype.interrupt = interrupt_default2;\nselection_default.prototype.transition = transition_default2;\n\n// ../../node_modules/d3-brush/src/constant.js\nvar constant_default3 = (x3) => () => x3;\n\n// ../../node_modules/d3-brush/src/event.js\nfunction BrushEvent(type2, {\n sourceEvent,\n target,\n selection: selection2,\n mode: mode3,\n dispatch: dispatch2\n}) {\n Object.defineProperties(this, {\n type: { value: type2, enumerable: true, configurable: true },\n sourceEvent: { value: sourceEvent, enumerable: true, configurable: true },\n target: { value: target, enumerable: true, configurable: true },\n selection: { value: selection2, enumerable: true, configurable: true },\n mode: { value: mode3, enumerable: true, configurable: true },\n _: { value: dispatch2 }\n });\n}\n\n// ../../node_modules/d3-brush/src/noevent.js\nfunction nopropagation(event) {\n event.stopImmediatePropagation();\n}\nfunction noevent_default2(event) {\n event.preventDefault();\n event.stopImmediatePropagation();\n}\n\n// ../../node_modules/d3-brush/src/brush.js\nvar MODE_DRAG = { name: \"drag\" };\nvar MODE_SPACE = { name: \"space\" };\nvar MODE_HANDLE = { name: \"handle\" };\nvar MODE_CENTER = { name: \"center\" };\nvar { abs, max: max3, min: min3 } = Math;\nfunction number1(e) {\n return [+e[0], +e[1]];\n}\nfunction number22(e) {\n return [number1(e[0]), number1(e[1])];\n}\nvar X = {\n name: \"x\",\n handles: [\"w\", \"e\"].map(type),\n input: function(x3, e) {\n return x3 == null ? null : [[+x3[0], e[0][1]], [+x3[1], e[1][1]]];\n },\n output: function(xy) {\n return xy && [xy[0][0], xy[1][0]];\n }\n};\nvar Y = {\n name: \"y\",\n handles: [\"n\", \"s\"].map(type),\n input: function(y3, e) {\n return y3 == null ? null : [[e[0][0], +y3[0]], [e[1][0], +y3[1]]];\n },\n output: function(xy) {\n return xy && [xy[0][1], xy[1][1]];\n }\n};\nvar XY = {\n name: \"xy\",\n handles: [\"n\", \"w\", \"e\", \"s\", \"nw\", \"ne\", \"sw\", \"se\"].map(type),\n input: function(xy) {\n return xy == null ? null : number22(xy);\n },\n output: function(xy) {\n return xy;\n }\n};\nvar cursors = {\n overlay: \"crosshair\",\n selection: \"move\",\n n: \"ns-resize\",\n e: \"ew-resize\",\n s: \"ns-resize\",\n w: \"ew-resize\",\n nw: \"nwse-resize\",\n ne: \"nesw-resize\",\n se: \"nwse-resize\",\n sw: \"nesw-resize\"\n};\nvar flipX = {\n e: \"w\",\n w: \"e\",\n nw: \"ne\",\n ne: \"nw\",\n se: \"sw\",\n sw: \"se\"\n};\nvar flipY = {\n n: \"s\",\n s: \"n\",\n nw: \"sw\",\n ne: \"se\",\n se: \"ne\",\n sw: \"nw\"\n};\nvar signsX = {\n overlay: 1,\n selection: 1,\n n: null,\n e: 1,\n s: null,\n w: -1,\n nw: -1,\n ne: 1,\n se: 1,\n sw: -1\n};\nvar signsY = {\n overlay: 1,\n selection: 1,\n n: -1,\n e: null,\n s: 1,\n w: null,\n nw: -1,\n ne: -1,\n se: 1,\n sw: 1\n};\nfunction type(t) {\n return { type: t };\n}\nfunction defaultFilter(event) {\n return !event.ctrlKey && !event.button;\n}\nfunction defaultExtent() {\n var svg = this.ownerSVGElement || this;\n if (svg.hasAttribute(\"viewBox\")) {\n svg = svg.viewBox.baseVal;\n return [[svg.x, svg.y], [svg.x + svg.width, svg.y + svg.height]];\n }\n return [[0, 0], [svg.width.baseVal.value, svg.height.baseVal.value]];\n}\nfunction defaultTouchable() {\n return navigator.maxTouchPoints || \"ontouchstart\" in this;\n}\nfunction local(node) {\n while (!node.__brush) if (!(node = node.parentNode)) return;\n return node.__brush;\n}\nfunction empty3(extent4) {\n return extent4[0][0] === extent4[1][0] || extent4[0][1] === extent4[1][1];\n}\nfunction brushX() {\n return brush(X);\n}\nfunction brushY() {\n return brush(Y);\n}\nfunction brush_default() {\n return brush(XY);\n}\nfunction brush(dim) {\n var extent4 = defaultExtent, filter3 = defaultFilter, touchable = defaultTouchable, keys = true, listeners = dispatch_default(\"start\", \"brush\", \"end\"), handleSize = 6, touchending;\n function brush3(group3) {\n var overlay = group3.property(\"__brush\", initialize).selectAll(\".overlay\").data([type(\"overlay\")]);\n overlay.enter().append(\"rect\").attr(\"class\", \"overlay\").attr(\"pointer-events\", \"all\").attr(\"cursor\", cursors.overlay).merge(overlay).each(function() {\n var extent5 = local(this).extent;\n select_default2(this).attr(\"x\", extent5[0][0]).attr(\"y\", extent5[0][1]).attr(\"width\", extent5[1][0] - extent5[0][0]).attr(\"height\", extent5[1][1] - extent5[0][1]);\n });\n group3.selectAll(\".selection\").data([type(\"selection\")]).enter().append(\"rect\").attr(\"class\", \"selection\").attr(\"cursor\", cursors.selection).attr(\"fill\", \"#777\").attr(\"fill-opacity\", 0.3).attr(\"stroke\", \"#fff\").attr(\"shape-rendering\", \"crispEdges\");\n var handle = group3.selectAll(\".handle\").data(dim.handles, function(d) {\n return d.type;\n });\n handle.exit().remove();\n handle.enter().append(\"rect\").attr(\"class\", function(d) {\n return \"handle handle--\" + d.type;\n }).attr(\"cursor\", function(d) {\n return cursors[d.type];\n });\n group3.each(redraw).attr(\"fill\", \"none\").attr(\"pointer-events\", \"all\").on(\"mousedown.brush\", started).filter(touchable).on(\"touchstart.brush\", started).on(\"touchmove.brush\", touchmoved).on(\"touchend.brush touchcancel.brush\", touchended).style(\"touch-action\", \"none\").style(\"-webkit-tap-highlight-color\", \"rgba(0,0,0,0)\");\n }\n brush3.move = function(group3, selection2, event) {\n if (group3.tween) {\n group3.on(\"start.brush\", function(event2) {\n emitter(this, arguments).beforestart().start(event2);\n }).on(\"interrupt.brush end.brush\", function(event2) {\n emitter(this, arguments).end(event2);\n }).tween(\"brush\", function() {\n var that = this, state = that.__brush, emit = emitter(that, arguments), selection0 = state.selection, selection1 = dim.input(typeof selection2 === \"function\" ? selection2.apply(this, arguments) : selection2, state.extent), i = value_default(selection0, selection1);\n function tween(t) {\n state.selection = t === 1 && selection1 === null ? null : i(t);\n redraw.call(that);\n emit.brush();\n }\n return selection0 !== null && selection1 !== null ? tween : tween(1);\n });\n } else {\n group3.each(function() {\n var that = this, args = arguments, state = that.__brush, selection1 = dim.input(typeof selection2 === \"function\" ? selection2.apply(that, args) : selection2, state.extent), emit = emitter(that, args).beforestart();\n interrupt_default(that);\n state.selection = selection1 === null ? null : selection1;\n redraw.call(that);\n emit.start(event).brush(event).end(event);\n });\n }\n };\n brush3.clear = function(group3, event) {\n brush3.move(group3, null, event);\n };\n function redraw() {\n var group3 = select_default2(this), selection2 = local(this).selection;\n if (selection2) {\n group3.selectAll(\".selection\").style(\"display\", null).attr(\"x\", selection2[0][0]).attr(\"y\", selection2[0][1]).attr(\"width\", selection2[1][0] - selection2[0][0]).attr(\"height\", selection2[1][1] - selection2[0][1]);\n group3.selectAll(\".handle\").style(\"display\", null).attr(\"x\", function(d) {\n return d.type[d.type.length - 1] === \"e\" ? selection2[1][0] - handleSize / 2 : selection2[0][0] - handleSize / 2;\n }).attr(\"y\", function(d) {\n return d.type[0] === \"s\" ? selection2[1][1] - handleSize / 2 : selection2[0][1] - handleSize / 2;\n }).attr(\"width\", function(d) {\n return d.type === \"n\" || d.type === \"s\" ? selection2[1][0] - selection2[0][0] + handleSize : handleSize;\n }).attr(\"height\", function(d) {\n return d.type === \"e\" || d.type === \"w\" ? selection2[1][1] - selection2[0][1] + handleSize : handleSize;\n });\n } else {\n group3.selectAll(\".selection,.handle\").style(\"display\", \"none\").attr(\"x\", null).attr(\"y\", null).attr(\"width\", null).attr(\"height\", null);\n }\n }\n function emitter(that, args, clean) {\n var emit = that.__brush.emitter;\n return emit && (!clean || !emit.clean) ? emit : new Emitter(that, args, clean);\n }\n function Emitter(that, args, clean) {\n this.that = that;\n this.args = args;\n this.state = that.__brush;\n this.active = 0;\n this.clean = clean;\n }\n Emitter.prototype = {\n beforestart: function() {\n if (++this.active === 1) this.state.emitter = this, this.starting = true;\n return this;\n },\n start: function(event, mode3) {\n if (this.starting) this.starting = false, this.emit(\"start\", event, mode3);\n else this.emit(\"brush\", event);\n return this;\n },\n brush: function(event, mode3) {\n this.emit(\"brush\", event, mode3);\n return this;\n },\n end: function(event, mode3) {\n if (--this.active === 0) delete this.state.emitter, this.emit(\"end\", event, mode3);\n return this;\n },\n emit: function(type2, event, mode3) {\n var d = select_default2(this.that).datum();\n listeners.call(\n type2,\n this.that,\n new BrushEvent(type2, {\n sourceEvent: event,\n target: brush3,\n selection: dim.output(this.state.selection),\n mode: mode3,\n dispatch: listeners\n }),\n d\n );\n }\n };\n function started(event) {\n if (touchending && !event.touches) return;\n if (!filter3.apply(this, arguments)) return;\n var that = this, type2 = event.target.__data__.type, mode3 = (keys && event.metaKey ? type2 = \"overlay\" : type2) === \"selection\" ? MODE_DRAG : keys && event.altKey ? MODE_CENTER : MODE_HANDLE, signX = dim === Y ? null : signsX[type2], signY = dim === X ? null : signsY[type2], state = local(that), extent5 = state.extent, selection2 = state.selection, W = extent5[0][0], w0, w1, N = extent5[0][1], n0, n1, E2 = extent5[1][0], e0, e1, S = extent5[1][1], s0, s1, dx = 0, dy = 0, moving, shifting = signX && signY && keys && event.shiftKey, lockX, lockY, points2 = Array.from(event.touches || [event], (t) => {\n const i = t.identifier;\n t = pointer_default(t, that);\n t.point0 = t.slice();\n t.identifier = i;\n return t;\n });\n interrupt_default(that);\n var emit = emitter(that, arguments, true).beforestart();\n if (type2 === \"overlay\") {\n if (selection2) moving = true;\n const pts = [points2[0], points2[1] || points2[0]];\n state.selection = selection2 = [[\n w0 = dim === Y ? W : min3(pts[0][0], pts[1][0]),\n n0 = dim === X ? N : min3(pts[0][1], pts[1][1])\n ], [\n e0 = dim === Y ? E2 : max3(pts[0][0], pts[1][0]),\n s0 = dim === X ? S : max3(pts[0][1], pts[1][1])\n ]];\n if (points2.length > 1) move(event);\n } else {\n w0 = selection2[0][0];\n n0 = selection2[0][1];\n e0 = selection2[1][0];\n s0 = selection2[1][1];\n }\n w1 = w0;\n n1 = n0;\n e1 = e0;\n s1 = s0;\n var group3 = select_default2(that).attr(\"pointer-events\", \"none\");\n var overlay = group3.selectAll(\".overlay\").attr(\"cursor\", cursors[type2]);\n if (event.touches) {\n emit.moved = moved;\n emit.ended = ended;\n } else {\n var view = select_default2(event.view).on(\"mousemove.brush\", moved, true).on(\"mouseup.brush\", ended, true);\n if (keys) view.on(\"keydown.brush\", keydowned, true).on(\"keyup.brush\", keyupped, true);\n nodrag_default(event.view);\n }\n redraw.call(that);\n emit.start(event, mode3.name);\n function moved(event2) {\n for (const p of event2.changedTouches || [event2]) {\n for (const d of points2)\n if (d.identifier === p.identifier) d.cur = pointer_default(p, that);\n }\n if (shifting && !lockX && !lockY && points2.length === 1) {\n const point6 = points2[0];\n if (abs(point6.cur[0] - point6[0]) > abs(point6.cur[1] - point6[1]))\n lockY = true;\n else\n lockX = true;\n }\n for (const point6 of points2)\n if (point6.cur) point6[0] = point6.cur[0], point6[1] = point6.cur[1];\n moving = true;\n noevent_default2(event2);\n move(event2);\n }\n function move(event2) {\n const point6 = points2[0], point0 = point6.point0;\n var t;\n dx = point6[0] - point0[0];\n dy = point6[1] - point0[1];\n switch (mode3) {\n case MODE_SPACE:\n case MODE_DRAG: {\n if (signX) dx = max3(W - w0, min3(E2 - e0, dx)), w1 = w0 + dx, e1 = e0 + dx;\n if (signY) dy = max3(N - n0, min3(S - s0, dy)), n1 = n0 + dy, s1 = s0 + dy;\n break;\n }\n case MODE_HANDLE: {\n if (points2[1]) {\n if (signX) w1 = max3(W, min3(E2, points2[0][0])), e1 = max3(W, min3(E2, points2[1][0])), signX = 1;\n if (signY) n1 = max3(N, min3(S, points2[0][1])), s1 = max3(N, min3(S, points2[1][1])), signY = 1;\n } else {\n if (signX < 0) dx = max3(W - w0, min3(E2 - w0, dx)), w1 = w0 + dx, e1 = e0;\n else if (signX > 0) dx = max3(W - e0, min3(E2 - e0, dx)), w1 = w0, e1 = e0 + dx;\n if (signY < 0) dy = max3(N - n0, min3(S - n0, dy)), n1 = n0 + dy, s1 = s0;\n else if (signY > 0) dy = max3(N - s0, min3(S - s0, dy)), n1 = n0, s1 = s0 + dy;\n }\n break;\n }\n case MODE_CENTER: {\n if (signX) w1 = max3(W, min3(E2, w0 - dx * signX)), e1 = max3(W, min3(E2, e0 + dx * signX));\n if (signY) n1 = max3(N, min3(S, n0 - dy * signY)), s1 = max3(N, min3(S, s0 + dy * signY));\n break;\n }\n }\n if (e1 < w1) {\n signX *= -1;\n t = w0, w0 = e0, e0 = t;\n t = w1, w1 = e1, e1 = t;\n if (type2 in flipX) overlay.attr(\"cursor\", cursors[type2 = flipX[type2]]);\n }\n if (s1 < n1) {\n signY *= -1;\n t = n0, n0 = s0, s0 = t;\n t = n1, n1 = s1, s1 = t;\n if (type2 in flipY) overlay.attr(\"cursor\", cursors[type2 = flipY[type2]]);\n }\n if (state.selection) selection2 = state.selection;\n if (lockX) w1 = selection2[0][0], e1 = selection2[1][0];\n if (lockY) n1 = selection2[0][1], s1 = selection2[1][1];\n if (selection2[0][0] !== w1 || selection2[0][1] !== n1 || selection2[1][0] !== e1 || selection2[1][1] !== s1) {\n state.selection = [[w1, n1], [e1, s1]];\n redraw.call(that);\n emit.brush(event2, mode3.name);\n }\n }\n function ended(event2) {\n nopropagation(event2);\n if (event2.touches) {\n if (event2.touches.length) return;\n if (touchending) clearTimeout(touchending);\n touchending = setTimeout(function() {\n touchending = null;\n }, 500);\n } else {\n yesdrag(event2.view, moving);\n view.on(\"keydown.brush keyup.brush mousemove.brush mouseup.brush\", null);\n }\n group3.attr(\"pointer-events\", \"all\");\n overlay.attr(\"cursor\", cursors.overlay);\n if (state.selection) selection2 = state.selection;\n if (empty3(selection2)) state.selection = null, redraw.call(that);\n emit.end(event2, mode3.name);\n }\n function keydowned(event2) {\n switch (event2.keyCode) {\n case 16: {\n shifting = signX && signY;\n break;\n }\n case 18: {\n if (mode3 === MODE_HANDLE) {\n if (signX) e0 = e1 - dx * signX, w0 = w1 + dx * signX;\n if (signY) s0 = s1 - dy * signY, n0 = n1 + dy * signY;\n mode3 = MODE_CENTER;\n move(event2);\n }\n break;\n }\n case 32: {\n if (mode3 === MODE_HANDLE || mode3 === MODE_CENTER) {\n if (signX < 0) e0 = e1 - dx;\n else if (signX > 0) w0 = w1 - dx;\n if (signY < 0) s0 = s1 - dy;\n else if (signY > 0) n0 = n1 - dy;\n mode3 = MODE_SPACE;\n overlay.attr(\"cursor\", cursors.selection);\n move(event2);\n }\n break;\n }\n default:\n return;\n }\n noevent_default2(event2);\n }\n function keyupped(event2) {\n switch (event2.keyCode) {\n case 16: {\n if (shifting) {\n lockX = lockY = shifting = false;\n move(event2);\n }\n break;\n }\n case 18: {\n if (mode3 === MODE_CENTER) {\n if (signX < 0) e0 = e1;\n else if (signX > 0) w0 = w1;\n if (signY < 0) s0 = s1;\n else if (signY > 0) n0 = n1;\n mode3 = MODE_HANDLE;\n move(event2);\n }\n break;\n }\n case 32: {\n if (mode3 === MODE_SPACE) {\n if (event2.altKey) {\n if (signX) e0 = e1 - dx * signX, w0 = w1 + dx * signX;\n if (signY) s0 = s1 - dy * signY, n0 = n1 + dy * signY;\n mode3 = MODE_CENTER;\n } else {\n if (signX < 0) e0 = e1;\n else if (signX > 0) w0 = w1;\n if (signY < 0) s0 = s1;\n else if (signY > 0) n0 = n1;\n mode3 = MODE_HANDLE;\n }\n overlay.attr(\"cursor\", cursors[type2]);\n move(event2);\n }\n break;\n }\n default:\n return;\n }\n noevent_default2(event2);\n }\n }\n function touchmoved(event) {\n emitter(this, arguments).moved(event);\n }\n function touchended(event) {\n emitter(this, arguments).ended(event);\n }\n function initialize() {\n var state = this.__brush || { selection: null };\n state.extent = number22(extent4.apply(this, arguments));\n state.dim = dim;\n return state;\n }\n brush3.extent = function(_) {\n return arguments.length ? (extent4 = typeof _ === \"function\" ? _ : constant_default3(number22(_)), brush3) : extent4;\n };\n brush3.filter = function(_) {\n return arguments.length ? (filter3 = typeof _ === \"function\" ? _ : constant_default3(!!_), brush3) : filter3;\n };\n brush3.touchable = function(_) {\n return arguments.length ? (touchable = typeof _ === \"function\" ? _ : constant_default3(!!_), brush3) : touchable;\n };\n brush3.handleSize = function(_) {\n return arguments.length ? (handleSize = +_, brush3) : handleSize;\n };\n brush3.keyModifiers = function(_) {\n return arguments.length ? (keys = !!_, brush3) : keys;\n };\n brush3.on = function() {\n var value = listeners.on.apply(listeners, arguments);\n return value === listeners ? brush3 : value;\n };\n return brush3;\n}\n\n// ../../node_modules/d3-path/src/path.js\nvar pi = Math.PI;\nvar tau = 2 * pi;\nvar epsilon3 = 1e-6;\nvar tauEpsilon = tau - epsilon3;\nfunction append(strings) {\n this._ += strings[0];\n for (let i = 1, n = strings.length; i < n; ++i) {\n this._ += arguments[i] + strings[i];\n }\n}\nfunction appendRound(digits) {\n let d = Math.floor(digits);\n if (!(d >= 0)) throw new Error(`invalid digits: ${digits}`);\n if (d > 15) return append;\n const k2 = 10 ** d;\n return function(strings) {\n this._ += strings[0];\n for (let i = 1, n = strings.length; i < n; ++i) {\n this._ += Math.round(arguments[i] * k2) / k2 + strings[i];\n }\n };\n}\nvar Path = class {\n constructor(digits) {\n this._x0 = this._y0 = // start of current subpath\n this._x1 = this._y1 = null;\n this._ = \"\";\n this._append = digits == null ? append : appendRound(digits);\n }\n moveTo(x3, y3) {\n this._append`M${this._x0 = this._x1 = +x3},${this._y0 = this._y1 = +y3}`;\n }\n closePath() {\n if (this._x1 !== null) {\n this._x1 = this._x0, this._y1 = this._y0;\n this._append`Z`;\n }\n }\n lineTo(x3, y3) {\n this._append`L${this._x1 = +x3},${this._y1 = +y3}`;\n }\n quadraticCurveTo(x12, y12, x3, y3) {\n this._append`Q${+x12},${+y12},${this._x1 = +x3},${this._y1 = +y3}`;\n }\n bezierCurveTo(x12, y12, x22, y22, x3, y3) {\n this._append`C${+x12},${+y12},${+x22},${+y22},${this._x1 = +x3},${this._y1 = +y3}`;\n }\n arcTo(x12, y12, x22, y22, r) {\n x12 = +x12, y12 = +y12, x22 = +x22, y22 = +y22, r = +r;\n if (r < 0) throw new Error(`negative radius: ${r}`);\n let x06 = this._x1, y06 = this._y1, x21 = x22 - x12, y21 = y22 - y12, x01 = x06 - x12, y01 = y06 - y12, l01_2 = x01 * x01 + y01 * y01;\n if (this._x1 === null) {\n this._append`M${this._x1 = x12},${this._y1 = y12}`;\n } else if (!(l01_2 > epsilon3)) ;\n else if (!(Math.abs(y01 * x21 - y21 * x01) > epsilon3) || !r) {\n this._append`L${this._x1 = x12},${this._y1 = y12}`;\n } else {\n let x20 = x22 - x06, y20 = y22 - y06, l21_2 = x21 * x21 + y21 * y21, l20_2 = x20 * x20 + y20 * y20, l21 = Math.sqrt(l21_2), l01 = Math.sqrt(l01_2), l = r * Math.tan((pi - Math.acos((l21_2 + l01_2 - l20_2) / (2 * l21 * l01))) / 2), t01 = l / l01, t21 = l / l21;\n if (Math.abs(t01 - 1) > epsilon3) {\n this._append`L${x12 + t01 * x01},${y12 + t01 * y01}`;\n }\n this._append`A${r},${r},0,0,${+(y01 * x20 > x01 * y20)},${this._x1 = x12 + t21 * x21},${this._y1 = y12 + t21 * y21}`;\n }\n }\n arc(x3, y3, r, a0, a1, ccw) {\n x3 = +x3, y3 = +y3, r = +r, ccw = !!ccw;\n if (r < 0) throw new Error(`negative radius: ${r}`);\n let dx = r * Math.cos(a0), dy = r * Math.sin(a0), x06 = x3 + dx, y06 = y3 + dy, cw = 1 ^ ccw, da2 = ccw ? a0 - a1 : a1 - a0;\n if (this._x1 === null) {\n this._append`M${x06},${y06}`;\n } else if (Math.abs(this._x1 - x06) > epsilon3 || Math.abs(this._y1 - y06) > epsilon3) {\n this._append`L${x06},${y06}`;\n }\n if (!r) return;\n if (da2 < 0) da2 = da2 % tau + tau;\n if (da2 > tauEpsilon) {\n this._append`A${r},${r},0,1,${cw},${x3 - dx},${y3 - dy}A${r},${r},0,1,${cw},${this._x1 = x06},${this._y1 = y06}`;\n } else if (da2 > epsilon3) {\n this._append`A${r},${r},0,${+(da2 >= pi)},${cw},${this._x1 = x3 + r * Math.cos(a1)},${this._y1 = y3 + r * Math.sin(a1)}`;\n }\n }\n rect(x3, y3, w, h) {\n this._append`M${this._x0 = this._x1 = +x3},${this._y0 = this._y1 = +y3}h${w = +w}v${+h}h${-w}Z`;\n }\n toString() {\n return this._;\n }\n};\nfunction path() {\n return new Path();\n}\npath.prototype = Path.prototype;\nfunction pathRound(digits = 3) {\n return new Path(+digits);\n}\n\n// ../../node_modules/d3-contour/src/array.js\nvar array2 = Array.prototype;\nvar slice = array2.slice;\n\n// ../../node_modules/d3-contour/src/ascending.js\nfunction ascending_default(a2, b) {\n return a2 - b;\n}\n\n// ../../node_modules/d3-contour/src/area.js\nfunction area_default(ring) {\n var i = 0, n = ring.length, area3 = ring[n - 1][1] * ring[0][0] - ring[n - 1][0] * ring[0][1];\n while (++i < n) area3 += ring[i - 1][1] * ring[i][0] - ring[i - 1][0] * ring[i][1];\n return area3;\n}\n\n// ../../node_modules/d3-contour/src/constant.js\nvar constant_default4 = (x3) => () => x3;\n\n// ../../node_modules/d3-contour/src/contains.js\nfunction contains_default(ring, hole) {\n var i = -1, n = hole.length, c4;\n while (++i < n) if (c4 = ringContains(ring, hole[i])) return c4;\n return 0;\n}\nfunction ringContains(ring, point6) {\n var x3 = point6[0], y3 = point6[1], contains2 = -1;\n for (var i = 0, n = ring.length, j = n - 1; i < n; j = i++) {\n var pi5 = ring[i], xi = pi5[0], yi = pi5[1], pj = ring[j], xj = pj[0], yj = pj[1];\n if (segmentContains(pi5, pj, point6)) return 0;\n if (yi > y3 !== yj > y3 && x3 < (xj - xi) * (y3 - yi) / (yj - yi) + xi) contains2 = -contains2;\n }\n return contains2;\n}\nfunction segmentContains(a2, b, c4) {\n var i;\n return collinear(a2, b, c4) && within(a2[i = +(a2[0] === b[0])], c4[i], b[i]);\n}\nfunction collinear(a2, b, c4) {\n return (b[0] - a2[0]) * (c4[1] - a2[1]) === (c4[0] - a2[0]) * (b[1] - a2[1]);\n}\nfunction within(p, q, r) {\n return p <= q && q <= r || r <= q && q <= p;\n}\n\n// ../../node_modules/d3-contour/src/noop.js\nfunction noop_default() {\n}\n\n// ../../node_modules/d3-contour/src/contours.js\nvar cases = [\n [],\n [[[1, 1.5], [0.5, 1]]],\n [[[1.5, 1], [1, 1.5]]],\n [[[1.5, 1], [0.5, 1]]],\n [[[1, 0.5], [1.5, 1]]],\n [[[1, 1.5], [0.5, 1]], [[1, 0.5], [1.5, 1]]],\n [[[1, 0.5], [1, 1.5]]],\n [[[1, 0.5], [0.5, 1]]],\n [[[0.5, 1], [1, 0.5]]],\n [[[1, 1.5], [1, 0.5]]],\n [[[0.5, 1], [1, 0.5]], [[1.5, 1], [1, 1.5]]],\n [[[1.5, 1], [1, 0.5]]],\n [[[0.5, 1], [1.5, 1]]],\n [[[1, 1.5], [1.5, 1]]],\n [[[0.5, 1], [1, 1.5]]],\n []\n];\nfunction contours_default() {\n var dx = 1, dy = 1, threshold2 = thresholdSturges, smooth = smoothLinear;\n function contours(values2) {\n var tz = threshold2(values2);\n if (!Array.isArray(tz)) {\n const e = extent(values2, finite);\n tz = ticks(...nice(e[0], e[1], tz), tz);\n while (tz[tz.length - 1] >= e[1]) tz.pop();\n while (tz[1] < e[0]) tz.shift();\n } else {\n tz = tz.slice().sort(ascending_default);\n }\n return tz.map((value) => contour3(values2, value));\n }\n function contour3(values2, value) {\n const v2 = value == null ? NaN : +value;\n if (isNaN(v2)) throw new Error(`invalid value: ${value}`);\n var polygons = [], holes = [];\n isorings(values2, v2, function(ring) {\n smooth(ring, values2, v2);\n if (area_default(ring) > 0) polygons.push([ring]);\n else holes.push(ring);\n });\n holes.forEach(function(hole) {\n for (var i = 0, n = polygons.length, polygon; i < n; ++i) {\n if (contains_default((polygon = polygons[i])[0], hole) !== -1) {\n polygon.push(hole);\n return;\n }\n }\n });\n return {\n type: \"MultiPolygon\",\n value,\n coordinates: polygons\n };\n }\n function isorings(values2, value, callback) {\n var fragmentByStart = new Array(), fragmentByEnd = new Array(), x3, y3, t03, t13, t22, t32;\n x3 = y3 = -1;\n t13 = above(values2[0], value);\n cases[t13 << 1].forEach(stitch);\n while (++x3 < dx - 1) {\n t03 = t13, t13 = above(values2[x3 + 1], value);\n cases[t03 | t13 << 1].forEach(stitch);\n }\n cases[t13 << 0].forEach(stitch);\n while (++y3 < dy - 1) {\n x3 = -1;\n t13 = above(values2[y3 * dx + dx], value);\n t22 = above(values2[y3 * dx], value);\n cases[t13 << 1 | t22 << 2].forEach(stitch);\n while (++x3 < dx - 1) {\n t03 = t13, t13 = above(values2[y3 * dx + dx + x3 + 1], value);\n t32 = t22, t22 = above(values2[y3 * dx + x3 + 1], value);\n cases[t03 | t13 << 1 | t22 << 2 | t32 << 3].forEach(stitch);\n }\n cases[t13 | t22 << 3].forEach(stitch);\n }\n x3 = -1;\n t22 = values2[y3 * dx] >= value;\n cases[t22 << 2].forEach(stitch);\n while (++x3 < dx - 1) {\n t32 = t22, t22 = above(values2[y3 * dx + x3 + 1], value);\n cases[t22 << 2 | t32 << 3].forEach(stitch);\n }\n cases[t22 << 3].forEach(stitch);\n function stitch(line3) {\n var start2 = [line3[0][0] + x3, line3[0][1] + y3], end = [line3[1][0] + x3, line3[1][1] + y3], startIndex = index2(start2), endIndex = index2(end), f, g;\n if (f = fragmentByEnd[startIndex]) {\n if (g = fragmentByStart[endIndex]) {\n delete fragmentByEnd[f.end];\n delete fragmentByStart[g.start];\n if (f === g) {\n f.ring.push(end);\n callback(f.ring);\n } else {\n fragmentByStart[f.start] = fragmentByEnd[g.end] = { start: f.start, end: g.end, ring: f.ring.concat(g.ring) };\n }\n } else {\n delete fragmentByEnd[f.end];\n f.ring.push(end);\n fragmentByEnd[f.end = endIndex] = f;\n }\n } else if (f = fragmentByStart[endIndex]) {\n if (g = fragmentByEnd[startIndex]) {\n delete fragmentByStart[f.start];\n delete fragmentByEnd[g.end];\n if (f === g) {\n f.ring.push(end);\n callback(f.ring);\n } else {\n fragmentByStart[g.start] = fragmentByEnd[f.end] = { start: g.start, end: f.end, ring: g.ring.concat(f.ring) };\n }\n } else {\n delete fragmentByStart[f.start];\n f.ring.unshift(start2);\n fragmentByStart[f.start = startIndex] = f;\n }\n } else {\n fragmentByStart[startIndex] = fragmentByEnd[endIndex] = { start: startIndex, end: endIndex, ring: [start2, end] };\n }\n }\n }\n function index2(point6) {\n return point6[0] * 2 + point6[1] * (dx + 1) * 4;\n }\n function smoothLinear(ring, values2, value) {\n ring.forEach(function(point6) {\n var x3 = point6[0], y3 = point6[1], xt = x3 | 0, yt = y3 | 0, v1 = valid(values2[yt * dx + xt]);\n if (x3 > 0 && x3 < dx && xt === x3) {\n point6[0] = smooth1(x3, valid(values2[yt * dx + xt - 1]), v1, value);\n }\n if (y3 > 0 && y3 < dy && yt === y3) {\n point6[1] = smooth1(y3, valid(values2[(yt - 1) * dx + xt]), v1, value);\n }\n });\n }\n contours.contour = contour3;\n contours.size = function(_) {\n if (!arguments.length) return [dx, dy];\n var _0 = Math.floor(_[0]), _1 = Math.floor(_[1]);\n if (!(_0 >= 0 && _1 >= 0)) throw new Error(\"invalid size\");\n return dx = _0, dy = _1, contours;\n };\n contours.thresholds = function(_) {\n return arguments.length ? (threshold2 = typeof _ === \"function\" ? _ : Array.isArray(_) ? constant_default4(slice.call(_)) : constant_default4(_), contours) : threshold2;\n };\n contours.smooth = function(_) {\n return arguments.length ? (smooth = _ ? smoothLinear : noop_default, contours) : smooth === smoothLinear;\n };\n return contours;\n}\nfunction finite(x3) {\n return isFinite(x3) ? x3 : NaN;\n}\nfunction above(x3, value) {\n return x3 == null ? false : +x3 >= value;\n}\nfunction valid(v2) {\n return v2 == null || isNaN(v2 = +v2) ? -Infinity : v2;\n}\nfunction smooth1(x3, v0, v1, value) {\n const a2 = value - v0;\n const b = v1 - v0;\n const d = isFinite(a2) || isFinite(b) ? a2 / b : Math.sign(a2) / Math.sign(b);\n return isNaN(d) ? x3 : x3 + d - 0.5;\n}\n\n// ../../node_modules/d3-contour/src/density.js\nfunction defaultX(d) {\n return d[0];\n}\nfunction defaultY(d) {\n return d[1];\n}\nfunction defaultWeight() {\n return 1;\n}\nfunction density_default() {\n var x3 = defaultX, y3 = defaultY, weight = defaultWeight, dx = 960, dy = 500, r = 20, k2 = 2, o = r * 3, n = dx + o * 2 >> k2, m = dy + o * 2 >> k2, threshold2 = constant_default4(20);\n function grid2(data) {\n var values2 = new Float32Array(n * m), pow2k = Math.pow(2, -k2), i = -1;\n for (const d of data) {\n var xi = (x3(d, ++i, data) + o) * pow2k, yi = (y3(d, i, data) + o) * pow2k, wi = +weight(d, i, data);\n if (wi && xi >= 0 && xi < n && yi >= 0 && yi < m) {\n var x06 = Math.floor(xi), y06 = Math.floor(yi), xt = xi - x06 - 0.5, yt = yi - y06 - 0.5;\n values2[x06 + y06 * n] += (1 - xt) * (1 - yt) * wi;\n values2[x06 + 1 + y06 * n] += xt * (1 - yt) * wi;\n values2[x06 + 1 + (y06 + 1) * n] += xt * yt * wi;\n values2[x06 + (y06 + 1) * n] += (1 - xt) * yt * wi;\n }\n }\n blur2({ data: values2, width: n, height: m }, r * pow2k);\n return values2;\n }\n function density3(data) {\n var values2 = grid2(data), tz = threshold2(values2), pow4k = Math.pow(2, 2 * k2);\n if (!Array.isArray(tz)) {\n tz = ticks(Number.MIN_VALUE, max2(values2) / pow4k, tz);\n }\n return contours_default().size([n, m]).thresholds(tz.map((d) => d * pow4k))(values2).map((c4, i) => (c4.value = +tz[i], transform3(c4)));\n }\n density3.contours = function(data) {\n var values2 = grid2(data), contours = contours_default().size([n, m]), pow4k = Math.pow(2, 2 * k2), contour3 = (value) => {\n value = +value;\n var c4 = transform3(contours.contour(values2, value * pow4k));\n c4.value = value;\n return c4;\n };\n Object.defineProperty(contour3, \"max\", { get: () => max2(values2) / pow4k });\n return contour3;\n };\n function transform3(geometry) {\n geometry.coordinates.forEach(transformPolygon);\n return geometry;\n }\n function transformPolygon(coordinates) {\n coordinates.forEach(transformRing);\n }\n function transformRing(coordinates) {\n coordinates.forEach(transformPoint);\n }\n function transformPoint(coordinates) {\n coordinates[0] = coordinates[0] * Math.pow(2, k2) - o;\n coordinates[1] = coordinates[1] * Math.pow(2, k2) - o;\n }\n function resize() {\n o = r * 3;\n n = dx + o * 2 >> k2;\n m = dy + o * 2 >> k2;\n return density3;\n }\n density3.x = function(_) {\n return arguments.length ? (x3 = typeof _ === \"function\" ? _ : constant_default4(+_), density3) : x3;\n };\n density3.y = function(_) {\n return arguments.length ? (y3 = typeof _ === \"function\" ? _ : constant_default4(+_), density3) : y3;\n };\n density3.weight = function(_) {\n return arguments.length ? (weight = typeof _ === \"function\" ? _ : constant_default4(+_), density3) : weight;\n };\n density3.size = function(_) {\n if (!arguments.length) return [dx, dy];\n var _0 = +_[0], _1 = +_[1];\n if (!(_0 >= 0 && _1 >= 0)) throw new Error(\"invalid size\");\n return dx = _0, dy = _1, resize();\n };\n density3.cellSize = function(_) {\n if (!arguments.length) return 1 << k2;\n if (!((_ = +_) >= 1)) throw new Error(\"invalid cell size\");\n return k2 = Math.floor(Math.log(_) / Math.LN2), resize();\n };\n density3.thresholds = function(_) {\n return arguments.length ? (threshold2 = typeof _ === \"function\" ? _ : Array.isArray(_) ? constant_default4(slice.call(_)) : constant_default4(_), density3) : threshold2;\n };\n density3.bandwidth = function(_) {\n if (!arguments.length) return Math.sqrt(r * (r + 1));\n if (!((_ = +_) >= 0)) throw new Error(\"invalid bandwidth\");\n return r = (Math.sqrt(4 * _ * _ + 1) - 1) / 2, resize();\n };\n return density3;\n}\n\n// ../../node_modules/robust-predicates/esm/util.js\nvar epsilon4 = 11102230246251565e-32;\nvar splitter = 134217729;\nvar resulterrbound = (3 + 8 * epsilon4) * epsilon4;\nfunction sum3(elen, e, flen, f, h) {\n let Q, Qnew, hh, bvirt;\n let enow = e[0];\n let fnow = f[0];\n let eindex = 0;\n let findex = 0;\n if (fnow > enow === fnow > -enow) {\n Q = enow;\n enow = e[++eindex];\n } else {\n Q = fnow;\n fnow = f[++findex];\n }\n let hindex = 0;\n if (eindex < elen && findex < flen) {\n if (fnow > enow === fnow > -enow) {\n Qnew = enow + Q;\n hh = Q - (Qnew - enow);\n enow = e[++eindex];\n } else {\n Qnew = fnow + Q;\n hh = Q - (Qnew - fnow);\n fnow = f[++findex];\n }\n Q = Qnew;\n if (hh !== 0) {\n h[hindex++] = hh;\n }\n while (eindex < elen && findex < flen) {\n if (fnow > enow === fnow > -enow) {\n Qnew = Q + enow;\n bvirt = Qnew - Q;\n hh = Q - (Qnew - bvirt) + (enow - bvirt);\n enow = e[++eindex];\n } else {\n Qnew = Q + fnow;\n bvirt = Qnew - Q;\n hh = Q - (Qnew - bvirt) + (fnow - bvirt);\n fnow = f[++findex];\n }\n Q = Qnew;\n if (hh !== 0) {\n h[hindex++] = hh;\n }\n }\n }\n while (eindex < elen) {\n Qnew = Q + enow;\n bvirt = Qnew - Q;\n hh = Q - (Qnew - bvirt) + (enow - bvirt);\n enow = e[++eindex];\n Q = Qnew;\n if (hh !== 0) {\n h[hindex++] = hh;\n }\n }\n while (findex < flen) {\n Qnew = Q + fnow;\n bvirt = Qnew - Q;\n hh = Q - (Qnew - bvirt) + (fnow - bvirt);\n fnow = f[++findex];\n Q = Qnew;\n if (hh !== 0) {\n h[hindex++] = hh;\n }\n }\n if (Q !== 0 || hindex === 0) {\n h[hindex++] = Q;\n }\n return hindex;\n}\nfunction estimate(elen, e) {\n let Q = e[0];\n for (let i = 1; i < elen; i++) Q += e[i];\n return Q;\n}\nfunction vec(n) {\n return new Float64Array(n);\n}\n\n// ../../node_modules/robust-predicates/esm/orient2d.js\nvar ccwerrboundA = (3 + 16 * epsilon4) * epsilon4;\nvar ccwerrboundB = (2 + 12 * epsilon4) * epsilon4;\nvar ccwerrboundC = (9 + 64 * epsilon4) * epsilon4 * epsilon4;\nvar B2 = vec(4);\nvar C1 = vec(8);\nvar C2 = vec(12);\nvar D2 = vec(16);\nvar u = vec(4);\nfunction orient2dadapt(ax, ay, bx, by, cx, cy, detsum) {\n let acxtail, acytail, bcxtail, bcytail;\n let bvirt, c4, ahi, alo, bhi, blo, _i, _j, _0, s1, s0, t13, t03, u33;\n const acx = ax - cx;\n const bcx = bx - cx;\n const acy = ay - cy;\n const bcy = by - cy;\n s1 = acx * bcy;\n c4 = splitter * acx;\n ahi = c4 - (c4 - acx);\n alo = acx - ahi;\n c4 = splitter * bcy;\n bhi = c4 - (c4 - bcy);\n blo = bcy - bhi;\n s0 = alo * blo - (s1 - ahi * bhi - alo * bhi - ahi * blo);\n t13 = acy * bcx;\n c4 = splitter * acy;\n ahi = c4 - (c4 - acy);\n alo = acy - ahi;\n c4 = splitter * bcx;\n bhi = c4 - (c4 - bcx);\n blo = bcx - bhi;\n t03 = alo * blo - (t13 - ahi * bhi - alo * bhi - ahi * blo);\n _i = s0 - t03;\n bvirt = s0 - _i;\n B2[0] = s0 - (_i + bvirt) + (bvirt - t03);\n _j = s1 + _i;\n bvirt = _j - s1;\n _0 = s1 - (_j - bvirt) + (_i - bvirt);\n _i = _0 - t13;\n bvirt = _0 - _i;\n B2[1] = _0 - (_i + bvirt) + (bvirt - t13);\n u33 = _j + _i;\n bvirt = u33 - _j;\n B2[2] = _j - (u33 - bvirt) + (_i - bvirt);\n B2[3] = u33;\n let det = estimate(4, B2);\n let errbound = ccwerrboundB * detsum;\n if (det >= errbound || -det >= errbound) {\n return det;\n }\n bvirt = ax - acx;\n acxtail = ax - (acx + bvirt) + (bvirt - cx);\n bvirt = bx - bcx;\n bcxtail = bx - (bcx + bvirt) + (bvirt - cx);\n bvirt = ay - acy;\n acytail = ay - (acy + bvirt) + (bvirt - cy);\n bvirt = by - bcy;\n bcytail = by - (bcy + bvirt) + (bvirt - cy);\n if (acxtail === 0 && acytail === 0 && bcxtail === 0 && bcytail === 0) {\n return det;\n }\n errbound = ccwerrboundC * detsum + resulterrbound * Math.abs(det);\n det += acx * bcytail + bcy * acxtail - (acy * bcxtail + bcx * acytail);\n if (det >= errbound || -det >= errbound) return det;\n s1 = acxtail * bcy;\n c4 = splitter * acxtail;\n ahi = c4 - (c4 - acxtail);\n alo = acxtail - ahi;\n c4 = splitter * bcy;\n bhi = c4 - (c4 - bcy);\n blo = bcy - bhi;\n s0 = alo * blo - (s1 - ahi * bhi - alo * bhi - ahi * blo);\n t13 = acytail * bcx;\n c4 = splitter * acytail;\n ahi = c4 - (c4 - acytail);\n alo = acytail - ahi;\n c4 = splitter * bcx;\n bhi = c4 - (c4 - bcx);\n blo = bcx - bhi;\n t03 = alo * blo - (t13 - ahi * bhi - alo * bhi - ahi * blo);\n _i = s0 - t03;\n bvirt = s0 - _i;\n u[0] = s0 - (_i + bvirt) + (bvirt - t03);\n _j = s1 + _i;\n bvirt = _j - s1;\n _0 = s1 - (_j - bvirt) + (_i - bvirt);\n _i = _0 - t13;\n bvirt = _0 - _i;\n u[1] = _0 - (_i + bvirt) + (bvirt - t13);\n u33 = _j + _i;\n bvirt = u33 - _j;\n u[2] = _j - (u33 - bvirt) + (_i - bvirt);\n u[3] = u33;\n const C1len = sum3(4, B2, 4, u, C1);\n s1 = acx * bcytail;\n c4 = splitter * acx;\n ahi = c4 - (c4 - acx);\n alo = acx - ahi;\n c4 = splitter * bcytail;\n bhi = c4 - (c4 - bcytail);\n blo = bcytail - bhi;\n s0 = alo * blo - (s1 - ahi * bhi - alo * bhi - ahi * blo);\n t13 = acy * bcxtail;\n c4 = splitter * acy;\n ahi = c4 - (c4 - acy);\n alo = acy - ahi;\n c4 = splitter * bcxtail;\n bhi = c4 - (c4 - bcxtail);\n blo = bcxtail - bhi;\n t03 = alo * blo - (t13 - ahi * bhi - alo * bhi - ahi * blo);\n _i = s0 - t03;\n bvirt = s0 - _i;\n u[0] = s0 - (_i + bvirt) + (bvirt - t03);\n _j = s1 + _i;\n bvirt = _j - s1;\n _0 = s1 - (_j - bvirt) + (_i - bvirt);\n _i = _0 - t13;\n bvirt = _0 - _i;\n u[1] = _0 - (_i + bvirt) + (bvirt - t13);\n u33 = _j + _i;\n bvirt = u33 - _j;\n u[2] = _j - (u33 - bvirt) + (_i - bvirt);\n u[3] = u33;\n const C2len = sum3(C1len, C1, 4, u, C2);\n s1 = acxtail * bcytail;\n c4 = splitter * acxtail;\n ahi = c4 - (c4 - acxtail);\n alo = acxtail - ahi;\n c4 = splitter * bcytail;\n bhi = c4 - (c4 - bcytail);\n blo = bcytail - bhi;\n s0 = alo * blo - (s1 - ahi * bhi - alo * bhi - ahi * blo);\n t13 = acytail * bcxtail;\n c4 = splitter * acytail;\n ahi = c4 - (c4 - acytail);\n alo = acytail - ahi;\n c4 = splitter * bcxtail;\n bhi = c4 - (c4 - bcxtail);\n blo = bcxtail - bhi;\n t03 = alo * blo - (t13 - ahi * bhi - alo * bhi - ahi * blo);\n _i = s0 - t03;\n bvirt = s0 - _i;\n u[0] = s0 - (_i + bvirt) + (bvirt - t03);\n _j = s1 + _i;\n bvirt = _j - s1;\n _0 = s1 - (_j - bvirt) + (_i - bvirt);\n _i = _0 - t13;\n bvirt = _0 - _i;\n u[1] = _0 - (_i + bvirt) + (bvirt - t13);\n u33 = _j + _i;\n bvirt = u33 - _j;\n u[2] = _j - (u33 - bvirt) + (_i - bvirt);\n u[3] = u33;\n const Dlen = sum3(C2len, C2, 4, u, D2);\n return D2[Dlen - 1];\n}\nfunction orient2d(ax, ay, bx, by, cx, cy) {\n const detleft = (ay - cy) * (bx - cx);\n const detright = (ax - cx) * (by - cy);\n const det = detleft - detright;\n const detsum = Math.abs(detleft + detright);\n if (Math.abs(det) >= ccwerrboundA * detsum) return det;\n return -orient2dadapt(ax, ay, bx, by, cx, cy, detsum);\n}\n\n// ../../node_modules/robust-predicates/esm/orient3d.js\nvar o3derrboundA = (7 + 56 * epsilon4) * epsilon4;\nvar o3derrboundB = (3 + 28 * epsilon4) * epsilon4;\nvar o3derrboundC = (26 + 288 * epsilon4) * epsilon4 * epsilon4;\nvar bc = vec(4);\nvar ca = vec(4);\nvar ab = vec(4);\nvar at_b = vec(4);\nvar at_c = vec(4);\nvar bt_c = vec(4);\nvar bt_a = vec(4);\nvar ct_a = vec(4);\nvar ct_b = vec(4);\nvar bct = vec(8);\nvar cat = vec(8);\nvar abt = vec(8);\nvar u2 = vec(4);\nvar _8 = vec(8);\nvar _8b = vec(8);\nvar _16 = vec(8);\nvar _12 = vec(12);\nvar fin = vec(192);\nvar fin2 = vec(192);\n\n// ../../node_modules/robust-predicates/esm/incircle.js\nvar iccerrboundA = (10 + 96 * epsilon4) * epsilon4;\nvar iccerrboundB = (4 + 48 * epsilon4) * epsilon4;\nvar iccerrboundC = (44 + 576 * epsilon4) * epsilon4 * epsilon4;\nvar bc2 = vec(4);\nvar ca2 = vec(4);\nvar ab2 = vec(4);\nvar aa = vec(4);\nvar bb = vec(4);\nvar cc = vec(4);\nvar u3 = vec(4);\nvar v = vec(4);\nvar axtbc = vec(8);\nvar aytbc = vec(8);\nvar bxtca = vec(8);\nvar bytca = vec(8);\nvar cxtab = vec(8);\nvar cytab = vec(8);\nvar abt2 = vec(8);\nvar bct2 = vec(8);\nvar cat2 = vec(8);\nvar abtt = vec(4);\nvar bctt = vec(4);\nvar catt = vec(4);\nvar _82 = vec(8);\nvar _162 = vec(16);\nvar _16b = vec(16);\nvar _16c = vec(16);\nvar _32 = vec(32);\nvar _32b = vec(32);\nvar _48 = vec(48);\nvar _64 = vec(64);\nvar fin3 = vec(1152);\nvar fin22 = vec(1152);\n\n// ../../node_modules/robust-predicates/esm/insphere.js\nvar isperrboundA = (16 + 224 * epsilon4) * epsilon4;\nvar isperrboundB = (5 + 72 * epsilon4) * epsilon4;\nvar isperrboundC = (71 + 1408 * epsilon4) * epsilon4 * epsilon4;\nvar ab3 = vec(4);\nvar bc3 = vec(4);\nvar cd = vec(4);\nvar de = vec(4);\nvar ea = vec(4);\nvar ac = vec(4);\nvar bd = vec(4);\nvar ce = vec(4);\nvar da = vec(4);\nvar eb = vec(4);\nvar abc = vec(24);\nvar bcd = vec(24);\nvar cde = vec(24);\nvar dea = vec(24);\nvar eab = vec(24);\nvar abd = vec(24);\nvar bce = vec(24);\nvar cda = vec(24);\nvar deb = vec(24);\nvar eac = vec(24);\nvar adet = vec(1152);\nvar bdet = vec(1152);\nvar cdet = vec(1152);\nvar ddet = vec(1152);\nvar edet = vec(1152);\nvar abdet = vec(2304);\nvar cddet = vec(2304);\nvar cdedet = vec(3456);\nvar deter = vec(5760);\nvar _83 = vec(8);\nvar _8b2 = vec(8);\nvar _8c = vec(8);\nvar _163 = vec(16);\nvar _24 = vec(24);\nvar _482 = vec(48);\nvar _48b = vec(48);\nvar _96 = vec(96);\nvar _192 = vec(192);\nvar _384x = vec(384);\nvar _384y = vec(384);\nvar _384z = vec(384);\nvar _768 = vec(768);\nvar xdet = vec(96);\nvar ydet = vec(96);\nvar zdet = vec(96);\nvar fin4 = vec(1152);\n\n// ../../node_modules/delaunator/index.js\nvar EPSILON = Math.pow(2, -52);\nvar EDGE_STACK = new Uint32Array(512);\nvar Delaunator = class _Delaunator {\n static from(points2, getX = defaultGetX, getY = defaultGetY) {\n const n = points2.length;\n const coords = new Float64Array(n * 2);\n for (let i = 0; i < n; i++) {\n const p = points2[i];\n coords[2 * i] = getX(p);\n coords[2 * i + 1] = getY(p);\n }\n return new _Delaunator(coords);\n }\n constructor(coords) {\n const n = coords.length >> 1;\n if (n > 0 && typeof coords[0] !== \"number\") throw new Error(\"Expected coords to contain numbers.\");\n this.coords = coords;\n const maxTriangles = Math.max(2 * n - 5, 0);\n this._triangles = new Uint32Array(maxTriangles * 3);\n this._halfedges = new Int32Array(maxTriangles * 3);\n this._hashSize = Math.ceil(Math.sqrt(n));\n this._hullPrev = new Uint32Array(n);\n this._hullNext = new Uint32Array(n);\n this._hullTri = new Uint32Array(n);\n this._hullHash = new Int32Array(this._hashSize);\n this._ids = new Uint32Array(n);\n this._dists = new Float64Array(n);\n this.update();\n }\n update() {\n const { coords, _hullPrev: hullPrev, _hullNext: hullNext, _hullTri: hullTri, _hullHash: hullHash } = this;\n const n = coords.length >> 1;\n let minX = Infinity;\n let minY = Infinity;\n let maxX = -Infinity;\n let maxY2 = -Infinity;\n for (let i = 0; i < n; i++) {\n const x3 = coords[2 * i];\n const y3 = coords[2 * i + 1];\n if (x3 < minX) minX = x3;\n if (y3 < minY) minY = y3;\n if (x3 > maxX) maxX = x3;\n if (y3 > maxY2) maxY2 = y3;\n this._ids[i] = i;\n }\n const cx = (minX + maxX) / 2;\n const cy = (minY + maxY2) / 2;\n let i0, i1, i2;\n for (let i = 0, minDist = Infinity; i < n; i++) {\n const d = dist(cx, cy, coords[2 * i], coords[2 * i + 1]);\n if (d < minDist) {\n i0 = i;\n minDist = d;\n }\n }\n const i0x = coords[2 * i0];\n const i0y = coords[2 * i0 + 1];\n for (let i = 0, minDist = Infinity; i < n; i++) {\n if (i === i0) continue;\n const d = dist(i0x, i0y, coords[2 * i], coords[2 * i + 1]);\n if (d < minDist && d > 0) {\n i1 = i;\n minDist = d;\n }\n }\n let i1x = coords[2 * i1];\n let i1y = coords[2 * i1 + 1];\n let minRadius = Infinity;\n for (let i = 0; i < n; i++) {\n if (i === i0 || i === i1) continue;\n const r = circumradius(i0x, i0y, i1x, i1y, coords[2 * i], coords[2 * i + 1]);\n if (r < minRadius) {\n i2 = i;\n minRadius = r;\n }\n }\n let i2x = coords[2 * i2];\n let i2y = coords[2 * i2 + 1];\n if (minRadius === Infinity) {\n for (let i = 0; i < n; i++) {\n this._dists[i] = coords[2 * i] - coords[0] || coords[2 * i + 1] - coords[1];\n }\n quicksort(this._ids, this._dists, 0, n - 1);\n const hull3 = new Uint32Array(n);\n let j = 0;\n for (let i = 0, d0 = -Infinity; i < n; i++) {\n const id2 = this._ids[i];\n const d = this._dists[id2];\n if (d > d0) {\n hull3[j++] = id2;\n d0 = d;\n }\n }\n this.hull = hull3.subarray(0, j);\n this.triangles = new Uint32Array(0);\n this.halfedges = new Uint32Array(0);\n return;\n }\n if (orient2d(i0x, i0y, i1x, i1y, i2x, i2y) < 0) {\n const i = i1;\n const x3 = i1x;\n const y3 = i1y;\n i1 = i2;\n i1x = i2x;\n i1y = i2y;\n i2 = i;\n i2x = x3;\n i2y = y3;\n }\n const center2 = circumcenter(i0x, i0y, i1x, i1y, i2x, i2y);\n this._cx = center2.x;\n this._cy = center2.y;\n for (let i = 0; i < n; i++) {\n this._dists[i] = dist(coords[2 * i], coords[2 * i + 1], center2.x, center2.y);\n }\n quicksort(this._ids, this._dists, 0, n - 1);\n this._hullStart = i0;\n let hullSize = 3;\n hullNext[i0] = hullPrev[i2] = i1;\n hullNext[i1] = hullPrev[i0] = i2;\n hullNext[i2] = hullPrev[i1] = i0;\n hullTri[i0] = 0;\n hullTri[i1] = 1;\n hullTri[i2] = 2;\n hullHash.fill(-1);\n hullHash[this._hashKey(i0x, i0y)] = i0;\n hullHash[this._hashKey(i1x, i1y)] = i1;\n hullHash[this._hashKey(i2x, i2y)] = i2;\n this.trianglesLen = 0;\n this._addTriangle(i0, i1, i2, -1, -1, -1);\n for (let k2 = 0, xp, yp; k2 < this._ids.length; k2++) {\n const i = this._ids[k2];\n const x3 = coords[2 * i];\n const y3 = coords[2 * i + 1];\n if (k2 > 0 && Math.abs(x3 - xp) <= EPSILON && Math.abs(y3 - yp) <= EPSILON) continue;\n xp = x3;\n yp = y3;\n if (i === i0 || i === i1 || i === i2) continue;\n let start2 = 0;\n for (let j = 0, key = this._hashKey(x3, y3); j < this._hashSize; j++) {\n start2 = hullHash[(key + j) % this._hashSize];\n if (start2 !== -1 && start2 !== hullNext[start2]) break;\n }\n start2 = hullPrev[start2];\n let e = start2, q;\n while (q = hullNext[e], orient2d(x3, y3, coords[2 * e], coords[2 * e + 1], coords[2 * q], coords[2 * q + 1]) >= 0) {\n e = q;\n if (e === start2) {\n e = -1;\n break;\n }\n }\n if (e === -1) continue;\n let t = this._addTriangle(e, i, hullNext[e], -1, -1, hullTri[e]);\n hullTri[i] = this._legalize(t + 2);\n hullTri[e] = t;\n hullSize++;\n let n2 = hullNext[e];\n while (q = hullNext[n2], orient2d(x3, y3, coords[2 * n2], coords[2 * n2 + 1], coords[2 * q], coords[2 * q + 1]) < 0) {\n t = this._addTriangle(n2, i, q, hullTri[i], -1, hullTri[n2]);\n hullTri[i] = this._legalize(t + 2);\n hullNext[n2] = n2;\n hullSize--;\n n2 = q;\n }\n if (e === start2) {\n while (q = hullPrev[e], orient2d(x3, y3, coords[2 * q], coords[2 * q + 1], coords[2 * e], coords[2 * e + 1]) < 0) {\n t = this._addTriangle(q, i, e, -1, hullTri[e], hullTri[q]);\n this._legalize(t + 2);\n hullTri[q] = t;\n hullNext[e] = e;\n hullSize--;\n e = q;\n }\n }\n this._hullStart = hullPrev[i] = e;\n hullNext[e] = hullPrev[n2] = i;\n hullNext[i] = n2;\n hullHash[this._hashKey(x3, y3)] = i;\n hullHash[this._hashKey(coords[2 * e], coords[2 * e + 1])] = e;\n }\n this.hull = new Uint32Array(hullSize);\n for (let i = 0, e = this._hullStart; i < hullSize; i++) {\n this.hull[i] = e;\n e = hullNext[e];\n }\n this.triangles = this._triangles.subarray(0, this.trianglesLen);\n this.halfedges = this._halfedges.subarray(0, this.trianglesLen);\n }\n _hashKey(x3, y3) {\n return Math.floor(pseudoAngle(x3 - this._cx, y3 - this._cy) * this._hashSize) % this._hashSize;\n }\n _legalize(a2) {\n const { _triangles: triangles, _halfedges: halfedges, coords } = this;\n let i = 0;\n let ar = 0;\n while (true) {\n const b = halfedges[a2];\n const a0 = a2 - a2 % 3;\n ar = a0 + (a2 + 2) % 3;\n if (b === -1) {\n if (i === 0) break;\n a2 = EDGE_STACK[--i];\n continue;\n }\n const b0 = b - b % 3;\n const al = a0 + (a2 + 1) % 3;\n const bl = b0 + (b + 2) % 3;\n const p0 = triangles[ar];\n const pr = triangles[a2];\n const pl = triangles[al];\n const p1 = triangles[bl];\n const illegal = inCircle(\n coords[2 * p0],\n coords[2 * p0 + 1],\n coords[2 * pr],\n coords[2 * pr + 1],\n coords[2 * pl],\n coords[2 * pl + 1],\n coords[2 * p1],\n coords[2 * p1 + 1]\n );\n if (illegal) {\n triangles[a2] = p1;\n triangles[b] = p0;\n const hbl = halfedges[bl];\n if (hbl === -1) {\n let e = this._hullStart;\n do {\n if (this._hullTri[e] === bl) {\n this._hullTri[e] = a2;\n break;\n }\n e = this._hullPrev[e];\n } while (e !== this._hullStart);\n }\n this._link(a2, hbl);\n this._link(b, halfedges[ar]);\n this._link(ar, bl);\n const br = b0 + (b + 1) % 3;\n if (i < EDGE_STACK.length) {\n EDGE_STACK[i++] = br;\n }\n } else {\n if (i === 0) break;\n a2 = EDGE_STACK[--i];\n }\n }\n return ar;\n }\n _link(a2, b) {\n this._halfedges[a2] = b;\n if (b !== -1) this._halfedges[b] = a2;\n }\n // add a new triangle given vertex indices and adjacent half-edge ids\n _addTriangle(i0, i1, i2, a2, b, c4) {\n const t = this.trianglesLen;\n this._triangles[t] = i0;\n this._triangles[t + 1] = i1;\n this._triangles[t + 2] = i2;\n this._link(t, a2);\n this._link(t + 1, b);\n this._link(t + 2, c4);\n this.trianglesLen += 3;\n return t;\n }\n};\nfunction pseudoAngle(dx, dy) {\n const p = dx / (Math.abs(dx) + Math.abs(dy));\n return (dy > 0 ? 3 - p : 1 + p) / 4;\n}\nfunction dist(ax, ay, bx, by) {\n const dx = ax - bx;\n const dy = ay - by;\n return dx * dx + dy * dy;\n}\nfunction inCircle(ax, ay, bx, by, cx, cy, px, py) {\n const dx = ax - px;\n const dy = ay - py;\n const ex = bx - px;\n const ey = by - py;\n const fx = cx - px;\n const fy = cy - py;\n const ap = dx * dx + dy * dy;\n const bp = ex * ex + ey * ey;\n const cp = fx * fx + fy * fy;\n return dx * (ey * cp - bp * fy) - dy * (ex * cp - bp * fx) + ap * (ex * fy - ey * fx) < 0;\n}\nfunction circumradius(ax, ay, bx, by, cx, cy) {\n const dx = bx - ax;\n const dy = by - ay;\n const ex = cx - ax;\n const ey = cy - ay;\n const bl = dx * dx + dy * dy;\n const cl = ex * ex + ey * ey;\n const d = 0.5 / (dx * ey - dy * ex);\n const x3 = (ey * bl - dy * cl) * d;\n const y3 = (dx * cl - ex * bl) * d;\n return x3 * x3 + y3 * y3;\n}\nfunction circumcenter(ax, ay, bx, by, cx, cy) {\n const dx = bx - ax;\n const dy = by - ay;\n const ex = cx - ax;\n const ey = cy - ay;\n const bl = dx * dx + dy * dy;\n const cl = ex * ex + ey * ey;\n const d = 0.5 / (dx * ey - dy * ex);\n const x3 = ax + (ey * bl - dy * cl) * d;\n const y3 = ay + (dx * cl - ex * bl) * d;\n return { x: x3, y: y3 };\n}\nfunction quicksort(ids, dists, left2, right2) {\n if (right2 - left2 <= 20) {\n for (let i = left2 + 1; i <= right2; i++) {\n const temp = ids[i];\n const tempDist = dists[temp];\n let j = i - 1;\n while (j >= left2 && dists[ids[j]] > tempDist) ids[j + 1] = ids[j--];\n ids[j + 1] = temp;\n }\n } else {\n const median3 = left2 + right2 >> 1;\n let i = left2 + 1;\n let j = right2;\n swap2(ids, median3, i);\n if (dists[ids[left2]] > dists[ids[right2]]) swap2(ids, left2, right2);\n if (dists[ids[i]] > dists[ids[right2]]) swap2(ids, i, right2);\n if (dists[ids[left2]] > dists[ids[i]]) swap2(ids, left2, i);\n const temp = ids[i];\n const tempDist = dists[temp];\n while (true) {\n do\n i++;\n while (dists[ids[i]] < tempDist);\n do\n j--;\n while (dists[ids[j]] > tempDist);\n if (j < i) break;\n swap2(ids, i, j);\n }\n ids[left2 + 1] = ids[j];\n ids[j] = temp;\n if (right2 - i + 1 >= j - left2) {\n quicksort(ids, dists, i, right2);\n quicksort(ids, dists, left2, j - 1);\n } else {\n quicksort(ids, dists, left2, j - 1);\n quicksort(ids, dists, i, right2);\n }\n }\n}\nfunction swap2(arr, i, j) {\n const tmp = arr[i];\n arr[i] = arr[j];\n arr[j] = tmp;\n}\nfunction defaultGetX(p) {\n return p[0];\n}\nfunction defaultGetY(p) {\n return p[1];\n}\n\n// ../../node_modules/d3-delaunay/src/path.js\nvar epsilon5 = 1e-6;\nvar Path2 = class {\n constructor() {\n this._x0 = this._y0 = // start of current subpath\n this._x1 = this._y1 = null;\n this._ = \"\";\n }\n moveTo(x3, y3) {\n this._ += `M${this._x0 = this._x1 = +x3},${this._y0 = this._y1 = +y3}`;\n }\n closePath() {\n if (this._x1 !== null) {\n this._x1 = this._x0, this._y1 = this._y0;\n this._ += \"Z\";\n }\n }\n lineTo(x3, y3) {\n this._ += `L${this._x1 = +x3},${this._y1 = +y3}`;\n }\n arc(x3, y3, r) {\n x3 = +x3, y3 = +y3, r = +r;\n const x06 = x3 + r;\n const y06 = y3;\n if (r < 0) throw new Error(\"negative radius\");\n if (this._x1 === null) this._ += `M${x06},${y06}`;\n else if (Math.abs(this._x1 - x06) > epsilon5 || Math.abs(this._y1 - y06) > epsilon5) this._ += \"L\" + x06 + \",\" + y06;\n if (!r) return;\n this._ += `A${r},${r},0,1,1,${x3 - r},${y3}A${r},${r},0,1,1,${this._x1 = x06},${this._y1 = y06}`;\n }\n rect(x3, y3, w, h) {\n this._ += `M${this._x0 = this._x1 = +x3},${this._y0 = this._y1 = +y3}h${+w}v${+h}h${-w}Z`;\n }\n value() {\n return this._ || null;\n }\n};\n\n// ../../node_modules/d3-delaunay/src/polygon.js\nvar Polygon = class {\n constructor() {\n this._ = [];\n }\n moveTo(x3, y3) {\n this._.push([x3, y3]);\n }\n closePath() {\n this._.push(this._[0].slice());\n }\n lineTo(x3, y3) {\n this._.push([x3, y3]);\n }\n value() {\n return this._.length ? this._ : null;\n }\n};\n\n// ../../node_modules/d3-delaunay/src/voronoi.js\nvar Voronoi = class {\n constructor(delaunay, [xmin, ymin, xmax, ymax] = [0, 0, 960, 500]) {\n if (!((xmax = +xmax) >= (xmin = +xmin)) || !((ymax = +ymax) >= (ymin = +ymin))) throw new Error(\"invalid bounds\");\n this.delaunay = delaunay;\n this._circumcenters = new Float64Array(delaunay.points.length * 2);\n this.vectors = new Float64Array(delaunay.points.length * 2);\n this.xmax = xmax, this.xmin = xmin;\n this.ymax = ymax, this.ymin = ymin;\n this._init();\n }\n update() {\n this.delaunay.update();\n this._init();\n return this;\n }\n _init() {\n const { delaunay: { points: points2, hull: hull3, triangles }, vectors } = this;\n let bx, by;\n const circumcenters = this.circumcenters = this._circumcenters.subarray(0, triangles.length / 3 * 2);\n for (let i = 0, j = 0, n = triangles.length, x3, y3; i < n; i += 3, j += 2) {\n const t13 = triangles[i] * 2;\n const t22 = triangles[i + 1] * 2;\n const t32 = triangles[i + 2] * 2;\n const x13 = points2[t13];\n const y13 = points2[t13 + 1];\n const x22 = points2[t22];\n const y22 = points2[t22 + 1];\n const x32 = points2[t32];\n const y32 = points2[t32 + 1];\n const dx = x22 - x13;\n const dy = y22 - y13;\n const ex = x32 - x13;\n const ey = y32 - y13;\n const ab4 = (dx * ey - dy * ex) * 2;\n if (Math.abs(ab4) < 1e-9) {\n if (bx === void 0) {\n bx = by = 0;\n for (const i2 of hull3) bx += points2[i2 * 2], by += points2[i2 * 2 + 1];\n bx /= hull3.length, by /= hull3.length;\n }\n const a2 = 1e9 * Math.sign((bx - x13) * ey - (by - y13) * ex);\n x3 = (x13 + x32) / 2 - a2 * ey;\n y3 = (y13 + y32) / 2 + a2 * ex;\n } else {\n const d = 1 / ab4;\n const bl = dx * dx + dy * dy;\n const cl = ex * ex + ey * ey;\n x3 = x13 + (ey * bl - dy * cl) * d;\n y3 = y13 + (dx * cl - ex * bl) * d;\n }\n circumcenters[j] = x3;\n circumcenters[j + 1] = y3;\n }\n let h = hull3[hull3.length - 1];\n let p0, p1 = h * 4;\n let x06, x12 = points2[2 * h];\n let y06, y12 = points2[2 * h + 1];\n vectors.fill(0);\n for (let i = 0; i < hull3.length; ++i) {\n h = hull3[i];\n p0 = p1, x06 = x12, y06 = y12;\n p1 = h * 4, x12 = points2[2 * h], y12 = points2[2 * h + 1];\n vectors[p0 + 2] = vectors[p1] = y06 - y12;\n vectors[p0 + 3] = vectors[p1 + 1] = x12 - x06;\n }\n }\n render(context) {\n const buffer2 = context == null ? context = new Path2() : void 0;\n const { delaunay: { halfedges, inedges, hull: hull3 }, circumcenters, vectors } = this;\n if (hull3.length <= 1) return null;\n for (let i = 0, n = halfedges.length; i < n; ++i) {\n const j = halfedges[i];\n if (j < i) continue;\n const ti = Math.floor(i / 3) * 2;\n const tj = Math.floor(j / 3) * 2;\n const xi = circumcenters[ti];\n const yi = circumcenters[ti + 1];\n const xj = circumcenters[tj];\n const yj = circumcenters[tj + 1];\n this._renderSegment(xi, yi, xj, yj, context);\n }\n let h0, h1 = hull3[hull3.length - 1];\n for (let i = 0; i < hull3.length; ++i) {\n h0 = h1, h1 = hull3[i];\n const t = Math.floor(inedges[h1] / 3) * 2;\n const x3 = circumcenters[t];\n const y3 = circumcenters[t + 1];\n const v2 = h0 * 4;\n const p = this._project(x3, y3, vectors[v2 + 2], vectors[v2 + 3]);\n if (p) this._renderSegment(x3, y3, p[0], p[1], context);\n }\n return buffer2 && buffer2.value();\n }\n renderBounds(context) {\n const buffer2 = context == null ? context = new Path2() : void 0;\n context.rect(this.xmin, this.ymin, this.xmax - this.xmin, this.ymax - this.ymin);\n return buffer2 && buffer2.value();\n }\n renderCell(i, context) {\n const buffer2 = context == null ? context = new Path2() : void 0;\n const points2 = this._clip(i);\n if (points2 === null || !points2.length) return;\n context.moveTo(points2[0], points2[1]);\n let n = points2.length;\n while (points2[0] === points2[n - 2] && points2[1] === points2[n - 1] && n > 1) n -= 2;\n for (let i2 = 2; i2 < n; i2 += 2) {\n if (points2[i2] !== points2[i2 - 2] || points2[i2 + 1] !== points2[i2 - 1])\n context.lineTo(points2[i2], points2[i2 + 1]);\n }\n context.closePath();\n return buffer2 && buffer2.value();\n }\n *cellPolygons() {\n const { delaunay: { points: points2 } } = this;\n for (let i = 0, n = points2.length / 2; i < n; ++i) {\n const cell3 = this.cellPolygon(i);\n if (cell3) cell3.index = i, yield cell3;\n }\n }\n cellPolygon(i) {\n const polygon = new Polygon();\n this.renderCell(i, polygon);\n return polygon.value();\n }\n _renderSegment(x06, y06, x12, y12, context) {\n let S;\n const c0 = this._regioncode(x06, y06);\n const c1 = this._regioncode(x12, y12);\n if (c0 === 0 && c1 === 0) {\n context.moveTo(x06, y06);\n context.lineTo(x12, y12);\n } else if (S = this._clipSegment(x06, y06, x12, y12, c0, c1)) {\n context.moveTo(S[0], S[1]);\n context.lineTo(S[2], S[3]);\n }\n }\n contains(i, x3, y3) {\n if ((x3 = +x3, x3 !== x3) || (y3 = +y3, y3 !== y3)) return false;\n return this.delaunay._step(i, x3, y3) === i;\n }\n *neighbors(i) {\n const ci = this._clip(i);\n if (ci) for (const j of this.delaunay.neighbors(i)) {\n const cj = this._clip(j);\n if (cj) loop: for (let ai = 0, li = ci.length; ai < li; ai += 2) {\n for (let aj = 0, lj = cj.length; aj < lj; aj += 2) {\n if (ci[ai] === cj[aj] && ci[ai + 1] === cj[aj + 1] && ci[(ai + 2) % li] === cj[(aj + lj - 2) % lj] && ci[(ai + 3) % li] === cj[(aj + lj - 1) % lj]) {\n yield j;\n break loop;\n }\n }\n }\n }\n }\n _cell(i) {\n const { circumcenters, delaunay: { inedges, halfedges, triangles } } = this;\n const e0 = inedges[i];\n if (e0 === -1) return null;\n const points2 = [];\n let e = e0;\n do {\n const t = Math.floor(e / 3);\n points2.push(circumcenters[t * 2], circumcenters[t * 2 + 1]);\n e = e % 3 === 2 ? e - 2 : e + 1;\n if (triangles[e] !== i) break;\n e = halfedges[e];\n } while (e !== e0 && e !== -1);\n return points2;\n }\n _clip(i) {\n if (i === 0 && this.delaunay.hull.length === 1) {\n return [this.xmax, this.ymin, this.xmax, this.ymax, this.xmin, this.ymax, this.xmin, this.ymin];\n }\n const points2 = this._cell(i);\n if (points2 === null) return null;\n const { vectors: V } = this;\n const v2 = i * 4;\n return this._simplify(V[v2] || V[v2 + 1] ? this._clipInfinite(i, points2, V[v2], V[v2 + 1], V[v2 + 2], V[v2 + 3]) : this._clipFinite(i, points2));\n }\n _clipFinite(i, points2) {\n const n = points2.length;\n let P = null;\n let x06, y06, x12 = points2[n - 2], y12 = points2[n - 1];\n let c0, c1 = this._regioncode(x12, y12);\n let e0, e1 = 0;\n for (let j = 0; j < n; j += 2) {\n x06 = x12, y06 = y12, x12 = points2[j], y12 = points2[j + 1];\n c0 = c1, c1 = this._regioncode(x12, y12);\n if (c0 === 0 && c1 === 0) {\n e0 = e1, e1 = 0;\n if (P) P.push(x12, y12);\n else P = [x12, y12];\n } else {\n let S, sx0, sy0, sx1, sy1;\n if (c0 === 0) {\n if ((S = this._clipSegment(x06, y06, x12, y12, c0, c1)) === null) continue;\n [sx0, sy0, sx1, sy1] = S;\n } else {\n if ((S = this._clipSegment(x12, y12, x06, y06, c1, c0)) === null) continue;\n [sx1, sy1, sx0, sy0] = S;\n e0 = e1, e1 = this._edgecode(sx0, sy0);\n if (e0 && e1) this._edge(i, e0, e1, P, P.length);\n if (P) P.push(sx0, sy0);\n else P = [sx0, sy0];\n }\n e0 = e1, e1 = this._edgecode(sx1, sy1);\n if (e0 && e1) this._edge(i, e0, e1, P, P.length);\n if (P) P.push(sx1, sy1);\n else P = [sx1, sy1];\n }\n }\n if (P) {\n e0 = e1, e1 = this._edgecode(P[0], P[1]);\n if (e0 && e1) this._edge(i, e0, e1, P, P.length);\n } else if (this.contains(i, (this.xmin + this.xmax) / 2, (this.ymin + this.ymax) / 2)) {\n return [this.xmax, this.ymin, this.xmax, this.ymax, this.xmin, this.ymax, this.xmin, this.ymin];\n }\n return P;\n }\n _clipSegment(x06, y06, x12, y12, c0, c1) {\n const flip2 = c0 < c1;\n if (flip2) [x06, y06, x12, y12, c0, c1] = [x12, y12, x06, y06, c1, c0];\n while (true) {\n if (c0 === 0 && c1 === 0) return flip2 ? [x12, y12, x06, y06] : [x06, y06, x12, y12];\n if (c0 & c1) return null;\n let x3, y3, c4 = c0 || c1;\n if (c4 & 8) x3 = x06 + (x12 - x06) * (this.ymax - y06) / (y12 - y06), y3 = this.ymax;\n else if (c4 & 4) x3 = x06 + (x12 - x06) * (this.ymin - y06) / (y12 - y06), y3 = this.ymin;\n else if (c4 & 2) y3 = y06 + (y12 - y06) * (this.xmax - x06) / (x12 - x06), x3 = this.xmax;\n else y3 = y06 + (y12 - y06) * (this.xmin - x06) / (x12 - x06), x3 = this.xmin;\n if (c0) x06 = x3, y06 = y3, c0 = this._regioncode(x06, y06);\n else x12 = x3, y12 = y3, c1 = this._regioncode(x12, y12);\n }\n }\n _clipInfinite(i, points2, vx0, vy0, vxn, vyn) {\n let P = Array.from(points2), p;\n if (p = this._project(P[0], P[1], vx0, vy0)) P.unshift(p[0], p[1]);\n if (p = this._project(P[P.length - 2], P[P.length - 1], vxn, vyn)) P.push(p[0], p[1]);\n if (P = this._clipFinite(i, P)) {\n for (let j = 0, n = P.length, c0, c1 = this._edgecode(P[n - 2], P[n - 1]); j < n; j += 2) {\n c0 = c1, c1 = this._edgecode(P[j], P[j + 1]);\n if (c0 && c1) j = this._edge(i, c0, c1, P, j), n = P.length;\n }\n } else if (this.contains(i, (this.xmin + this.xmax) / 2, (this.ymin + this.ymax) / 2)) {\n P = [this.xmin, this.ymin, this.xmax, this.ymin, this.xmax, this.ymax, this.xmin, this.ymax];\n }\n return P;\n }\n _edge(i, e0, e1, P, j) {\n while (e0 !== e1) {\n let x3, y3;\n switch (e0) {\n case 5:\n e0 = 4;\n continue;\n // top-left\n case 4:\n e0 = 6, x3 = this.xmax, y3 = this.ymin;\n break;\n // top\n case 6:\n e0 = 2;\n continue;\n // top-right\n case 2:\n e0 = 10, x3 = this.xmax, y3 = this.ymax;\n break;\n // right\n case 10:\n e0 = 8;\n continue;\n // bottom-right\n case 8:\n e0 = 9, x3 = this.xmin, y3 = this.ymax;\n break;\n // bottom\n case 9:\n e0 = 1;\n continue;\n // bottom-left\n case 1:\n e0 = 5, x3 = this.xmin, y3 = this.ymin;\n break;\n }\n if ((P[j] !== x3 || P[j + 1] !== y3) && this.contains(i, x3, y3)) {\n P.splice(j, 0, x3, y3), j += 2;\n }\n }\n return j;\n }\n _project(x06, y06, vx, vy) {\n let t = Infinity, c4, x3, y3;\n if (vy < 0) {\n if (y06 <= this.ymin) return null;\n if ((c4 = (this.ymin - y06) / vy) < t) y3 = this.ymin, x3 = x06 + (t = c4) * vx;\n } else if (vy > 0) {\n if (y06 >= this.ymax) return null;\n if ((c4 = (this.ymax - y06) / vy) < t) y3 = this.ymax, x3 = x06 + (t = c4) * vx;\n }\n if (vx > 0) {\n if (x06 >= this.xmax) return null;\n if ((c4 = (this.xmax - x06) / vx) < t) x3 = this.xmax, y3 = y06 + (t = c4) * vy;\n } else if (vx < 0) {\n if (x06 <= this.xmin) return null;\n if ((c4 = (this.xmin - x06) / vx) < t) x3 = this.xmin, y3 = y06 + (t = c4) * vy;\n }\n return [x3, y3];\n }\n _edgecode(x3, y3) {\n return (x3 === this.xmin ? 1 : x3 === this.xmax ? 2 : 0) | (y3 === this.ymin ? 4 : y3 === this.ymax ? 8 : 0);\n }\n _regioncode(x3, y3) {\n return (x3 < this.xmin ? 1 : x3 > this.xmax ? 2 : 0) | (y3 < this.ymin ? 4 : y3 > this.ymax ? 8 : 0);\n }\n _simplify(P) {\n if (P && P.length > 4) {\n for (let i = 0; i < P.length; i += 2) {\n const j = (i + 2) % P.length, k2 = (i + 4) % P.length;\n if (P[i] === P[j] && P[j] === P[k2] || P[i + 1] === P[j + 1] && P[j + 1] === P[k2 + 1]) {\n P.splice(j, 2), i -= 2;\n }\n }\n if (!P.length) P = null;\n }\n return P;\n }\n};\n\n// ../../node_modules/d3-delaunay/src/delaunay.js\nvar tau2 = 2 * Math.PI;\nvar pow = Math.pow;\nfunction pointX(p) {\n return p[0];\n}\nfunction pointY(p) {\n return p[1];\n}\nfunction collinear2(d) {\n const { triangles, coords } = d;\n for (let i = 0; i < triangles.length; i += 3) {\n const a2 = 2 * triangles[i], b = 2 * triangles[i + 1], c4 = 2 * triangles[i + 2], cross3 = (coords[c4] - coords[a2]) * (coords[b + 1] - coords[a2 + 1]) - (coords[b] - coords[a2]) * (coords[c4 + 1] - coords[a2 + 1]);\n if (cross3 > 1e-10) return false;\n }\n return true;\n}\nfunction jitter(x3, y3, r) {\n return [x3 + Math.sin(x3 + y3) * r, y3 + Math.cos(x3 - y3) * r];\n}\nvar Delaunay = class _Delaunay {\n static from(points2, fx = pointX, fy = pointY, that) {\n return new _Delaunay(\"length\" in points2 ? flatArray(points2, fx, fy, that) : Float64Array.from(flatIterable(points2, fx, fy, that)));\n }\n constructor(points2) {\n this._delaunator = new Delaunator(points2);\n this.inedges = new Int32Array(points2.length / 2);\n this._hullIndex = new Int32Array(points2.length / 2);\n this.points = this._delaunator.coords;\n this._init();\n }\n update() {\n this._delaunator.update();\n this._init();\n return this;\n }\n _init() {\n const d = this._delaunator, points2 = this.points;\n if (d.hull && d.hull.length > 2 && collinear2(d)) {\n this.collinear = Int32Array.from({ length: points2.length / 2 }, (_, i) => i).sort((i, j) => points2[2 * i] - points2[2 * j] || points2[2 * i + 1] - points2[2 * j + 1]);\n const e = this.collinear[0], f = this.collinear[this.collinear.length - 1], bounds = [points2[2 * e], points2[2 * e + 1], points2[2 * f], points2[2 * f + 1]], r = 1e-8 * Math.hypot(bounds[3] - bounds[1], bounds[2] - bounds[0]);\n for (let i = 0, n = points2.length / 2; i < n; ++i) {\n const p = jitter(points2[2 * i], points2[2 * i + 1], r);\n points2[2 * i] = p[0];\n points2[2 * i + 1] = p[1];\n }\n this._delaunator = new Delaunator(points2);\n } else {\n delete this.collinear;\n }\n const halfedges = this.halfedges = this._delaunator.halfedges;\n const hull3 = this.hull = this._delaunator.hull;\n const triangles = this.triangles = this._delaunator.triangles;\n const inedges = this.inedges.fill(-1);\n const hullIndex = this._hullIndex.fill(-1);\n for (let e = 0, n = halfedges.length; e < n; ++e) {\n const p = triangles[e % 3 === 2 ? e - 2 : e + 1];\n if (halfedges[e] === -1 || inedges[p] === -1) inedges[p] = e;\n }\n for (let i = 0, n = hull3.length; i < n; ++i) {\n hullIndex[hull3[i]] = i;\n }\n if (hull3.length <= 2 && hull3.length > 0) {\n this.triangles = new Int32Array(3).fill(-1);\n this.halfedges = new Int32Array(3).fill(-1);\n this.triangles[0] = hull3[0];\n inedges[hull3[0]] = 1;\n if (hull3.length === 2) {\n inedges[hull3[1]] = 0;\n this.triangles[1] = hull3[1];\n this.triangles[2] = hull3[1];\n }\n }\n }\n voronoi(bounds) {\n return new Voronoi(this, bounds);\n }\n *neighbors(i) {\n const { inedges, hull: hull3, _hullIndex, halfedges, triangles, collinear: collinear3 } = this;\n if (collinear3) {\n const l = collinear3.indexOf(i);\n if (l > 0) yield collinear3[l - 1];\n if (l < collinear3.length - 1) yield collinear3[l + 1];\n return;\n }\n const e0 = inedges[i];\n if (e0 === -1) return;\n let e = e0, p0 = -1;\n do {\n yield p0 = triangles[e];\n e = e % 3 === 2 ? e - 2 : e + 1;\n if (triangles[e] !== i) return;\n e = halfedges[e];\n if (e === -1) {\n const p = hull3[(_hullIndex[i] + 1) % hull3.length];\n if (p !== p0) yield p;\n return;\n }\n } while (e !== e0);\n }\n find(x3, y3, i = 0) {\n if ((x3 = +x3, x3 !== x3) || (y3 = +y3, y3 !== y3)) return -1;\n const i0 = i;\n let c4;\n while ((c4 = this._step(i, x3, y3)) >= 0 && c4 !== i && c4 !== i0) i = c4;\n return c4;\n }\n _step(i, x3, y3) {\n const { inedges, hull: hull3, _hullIndex, halfedges, triangles, points: points2 } = this;\n if (inedges[i] === -1 || !points2.length) return (i + 1) % (points2.length >> 1);\n let c4 = i;\n let dc = pow(x3 - points2[i * 2], 2) + pow(y3 - points2[i * 2 + 1], 2);\n const e0 = inedges[i];\n let e = e0;\n do {\n let t = triangles[e];\n const dt = pow(x3 - points2[t * 2], 2) + pow(y3 - points2[t * 2 + 1], 2);\n if (dt < dc) dc = dt, c4 = t;\n e = e % 3 === 2 ? e - 2 : e + 1;\n if (triangles[e] !== i) break;\n e = halfedges[e];\n if (e === -1) {\n e = hull3[(_hullIndex[i] + 1) % hull3.length];\n if (e !== t) {\n if (pow(x3 - points2[e * 2], 2) + pow(y3 - points2[e * 2 + 1], 2) < dc) return e;\n }\n break;\n }\n } while (e !== e0);\n return c4;\n }\n render(context) {\n const buffer2 = context == null ? context = new Path2() : void 0;\n const { points: points2, halfedges, triangles } = this;\n for (let i = 0, n = halfedges.length; i < n; ++i) {\n const j = halfedges[i];\n if (j < i) continue;\n const ti = triangles[i] * 2;\n const tj = triangles[j] * 2;\n context.moveTo(points2[ti], points2[ti + 1]);\n context.lineTo(points2[tj], points2[tj + 1]);\n }\n this.renderHull(context);\n return buffer2 && buffer2.value();\n }\n renderPoints(context, r) {\n if (r === void 0 && (!context || typeof context.moveTo !== \"function\")) r = context, context = null;\n r = r == void 0 ? 2 : +r;\n const buffer2 = context == null ? context = new Path2() : void 0;\n const { points: points2 } = this;\n for (let i = 0, n = points2.length; i < n; i += 2) {\n const x3 = points2[i], y3 = points2[i + 1];\n context.moveTo(x3 + r, y3);\n context.arc(x3, y3, r, 0, tau2);\n }\n return buffer2 && buffer2.value();\n }\n renderHull(context) {\n const buffer2 = context == null ? context = new Path2() : void 0;\n const { hull: hull3, points: points2 } = this;\n const h = hull3[0] * 2, n = hull3.length;\n context.moveTo(points2[h], points2[h + 1]);\n for (let i = 1; i < n; ++i) {\n const h2 = 2 * hull3[i];\n context.lineTo(points2[h2], points2[h2 + 1]);\n }\n context.closePath();\n return buffer2 && buffer2.value();\n }\n hullPolygon() {\n const polygon = new Polygon();\n this.renderHull(polygon);\n return polygon.value();\n }\n renderTriangle(i, context) {\n const buffer2 = context == null ? context = new Path2() : void 0;\n const { points: points2, triangles } = this;\n const t03 = triangles[i *= 3] * 2;\n const t13 = triangles[i + 1] * 2;\n const t22 = triangles[i + 2] * 2;\n context.moveTo(points2[t03], points2[t03 + 1]);\n context.lineTo(points2[t13], points2[t13 + 1]);\n context.lineTo(points2[t22], points2[t22 + 1]);\n context.closePath();\n return buffer2 && buffer2.value();\n }\n *trianglePolygons() {\n const { triangles } = this;\n for (let i = 0, n = triangles.length / 3; i < n; ++i) {\n yield this.trianglePolygon(i);\n }\n }\n trianglePolygon(i) {\n const polygon = new Polygon();\n this.renderTriangle(i, polygon);\n return polygon.value();\n }\n};\nfunction flatArray(points2, fx, fy, that) {\n const n = points2.length;\n const array4 = new Float64Array(n * 2);\n for (let i = 0; i < n; ++i) {\n const p = points2[i];\n array4[i * 2] = fx.call(that, p, i, points2);\n array4[i * 2 + 1] = fy.call(that, p, i, points2);\n }\n return array4;\n}\nfunction* flatIterable(points2, fx, fy, that) {\n let i = 0;\n for (const p of points2) {\n yield fx.call(that, p, i, points2);\n yield fy.call(that, p, i, points2);\n ++i;\n }\n}\n\n// ../../node_modules/d3-format/src/formatDecimal.js\nfunction formatDecimal_default(x3) {\n return Math.abs(x3 = Math.round(x3)) >= 1e21 ? x3.toLocaleString(\"en\").replace(/,/g, \"\") : x3.toString(10);\n}\nfunction formatDecimalParts(x3, p) {\n if ((i = (x3 = p ? x3.toExponential(p - 1) : x3.toExponential()).indexOf(\"e\")) < 0) return null;\n var i, coefficient = x3.slice(0, i);\n return [\n coefficient.length > 1 ? coefficient[0] + coefficient.slice(2) : coefficient,\n +x3.slice(i + 1)\n ];\n}\n\n// ../../node_modules/d3-format/src/exponent.js\nfunction exponent_default(x3) {\n return x3 = formatDecimalParts(Math.abs(x3)), x3 ? x3[1] : NaN;\n}\n\n// ../../node_modules/d3-format/src/formatGroup.js\nfunction formatGroup_default(grouping, thousands) {\n return function(value, width2) {\n var i = value.length, t = [], j = 0, g = grouping[0], length4 = 0;\n while (i > 0 && g > 0) {\n if (length4 + g + 1 > width2) g = Math.max(1, width2 - length4);\n t.push(value.substring(i -= g, i + g));\n if ((length4 += g + 1) > width2) break;\n g = grouping[j = (j + 1) % grouping.length];\n }\n return t.reverse().join(thousands);\n };\n}\n\n// ../../node_modules/d3-format/src/formatNumerals.js\nfunction formatNumerals_default(numerals) {\n return function(value) {\n return value.replace(/[0-9]/g, function(i) {\n return numerals[+i];\n });\n };\n}\n\n// ../../node_modules/d3-format/src/formatSpecifier.js\nvar re = /^(?:(.)?([<>=^]))?([+\\-( ])?([$#])?(0)?(\\d+)?(,)?(\\.\\d+)?(~)?([a-z%])?$/i;\nfunction formatSpecifier(specifier) {\n if (!(match = re.exec(specifier))) throw new Error(\"invalid format: \" + specifier);\n var match;\n return new FormatSpecifier({\n fill: match[1],\n align: match[2],\n sign: match[3],\n symbol: match[4],\n zero: match[5],\n width: match[6],\n comma: match[7],\n precision: match[8] && match[8].slice(1),\n trim: match[9],\n type: match[10]\n });\n}\nformatSpecifier.prototype = FormatSpecifier.prototype;\nfunction FormatSpecifier(specifier) {\n this.fill = specifier.fill === void 0 ? \" \" : specifier.fill + \"\";\n this.align = specifier.align === void 0 ? \">\" : specifier.align + \"\";\n this.sign = specifier.sign === void 0 ? \"-\" : specifier.sign + \"\";\n this.symbol = specifier.symbol === void 0 ? \"\" : specifier.symbol + \"\";\n this.zero = !!specifier.zero;\n this.width = specifier.width === void 0 ? void 0 : +specifier.width;\n this.comma = !!specifier.comma;\n this.precision = specifier.precision === void 0 ? void 0 : +specifier.precision;\n this.trim = !!specifier.trim;\n this.type = specifier.type === void 0 ? \"\" : specifier.type + \"\";\n}\nFormatSpecifier.prototype.toString = function() {\n return this.fill + this.align + this.sign + this.symbol + (this.zero ? \"0\" : \"\") + (this.width === void 0 ? \"\" : Math.max(1, this.width | 0)) + (this.comma ? \",\" : \"\") + (this.precision === void 0 ? \"\" : \".\" + Math.max(0, this.precision | 0)) + (this.trim ? \"~\" : \"\") + this.type;\n};\n\n// ../../node_modules/d3-format/src/formatTrim.js\nfunction formatTrim_default(s2) {\n out: for (var n = s2.length, i = 1, i0 = -1, i1; i < n; ++i) {\n switch (s2[i]) {\n case \".\":\n i0 = i1 = i;\n break;\n case \"0\":\n if (i0 === 0) i0 = i;\n i1 = i;\n break;\n default:\n if (!+s2[i]) break out;\n if (i0 > 0) i0 = 0;\n break;\n }\n }\n return i0 > 0 ? s2.slice(0, i0) + s2.slice(i1 + 1) : s2;\n}\n\n// ../../node_modules/d3-format/src/formatPrefixAuto.js\nvar prefixExponent;\nfunction formatPrefixAuto_default(x3, p) {\n var d = formatDecimalParts(x3, p);\n if (!d) return x3 + \"\";\n var coefficient = d[0], exponent = d[1], i = exponent - (prefixExponent = Math.max(-8, Math.min(8, Math.floor(exponent / 3))) * 3) + 1, n = coefficient.length;\n return i === n ? coefficient : i > n ? coefficient + new Array(i - n + 1).join(\"0\") : i > 0 ? coefficient.slice(0, i) + \".\" + coefficient.slice(i) : \"0.\" + new Array(1 - i).join(\"0\") + formatDecimalParts(x3, Math.max(0, p + i - 1))[0];\n}\n\n// ../../node_modules/d3-format/src/formatRounded.js\nfunction formatRounded_default(x3, p) {\n var d = formatDecimalParts(x3, p);\n if (!d) return x3 + \"\";\n var coefficient = d[0], exponent = d[1];\n return exponent < 0 ? \"0.\" + new Array(-exponent).join(\"0\") + coefficient : coefficient.length > exponent + 1 ? coefficient.slice(0, exponent + 1) + \".\" + coefficient.slice(exponent + 1) : coefficient + new Array(exponent - coefficient.length + 2).join(\"0\");\n}\n\n// ../../node_modules/d3-format/src/formatTypes.js\nvar formatTypes_default = {\n \"%\": (x3, p) => (x3 * 100).toFixed(p),\n \"b\": (x3) => Math.round(x3).toString(2),\n \"c\": (x3) => x3 + \"\",\n \"d\": formatDecimal_default,\n \"e\": (x3, p) => x3.toExponential(p),\n \"f\": (x3, p) => x3.toFixed(p),\n \"g\": (x3, p) => x3.toPrecision(p),\n \"o\": (x3) => Math.round(x3).toString(8),\n \"p\": (x3, p) => formatRounded_default(x3 * 100, p),\n \"r\": formatRounded_default,\n \"s\": formatPrefixAuto_default,\n \"X\": (x3) => Math.round(x3).toString(16).toUpperCase(),\n \"x\": (x3) => Math.round(x3).toString(16)\n};\n\n// ../../node_modules/d3-format/src/identity.js\nfunction identity_default2(x3) {\n return x3;\n}\n\n// ../../node_modules/d3-format/src/locale.js\nvar map2 = Array.prototype.map;\nvar prefixes = [\"y\", \"z\", \"a\", \"f\", \"p\", \"n\", \"\\xB5\", \"m\", \"\", \"k\", \"M\", \"G\", \"T\", \"P\", \"E\", \"Z\", \"Y\"];\nfunction locale_default(locale3) {\n var group3 = locale3.grouping === void 0 || locale3.thousands === void 0 ? identity_default2 : formatGroup_default(map2.call(locale3.grouping, Number), locale3.thousands + \"\"), currencyPrefix = locale3.currency === void 0 ? \"\" : locale3.currency[0] + \"\", currencySuffix = locale3.currency === void 0 ? \"\" : locale3.currency[1] + \"\", decimal2 = locale3.decimal === void 0 ? \".\" : locale3.decimal + \"\", numerals = locale3.numerals === void 0 ? identity_default2 : formatNumerals_default(map2.call(locale3.numerals, String)), percent = locale3.percent === void 0 ? \"%\" : locale3.percent + \"\", minus = locale3.minus === void 0 ? \"\\u2212\" : locale3.minus + \"\", nan = locale3.nan === void 0 ? \"NaN\" : locale3.nan + \"\";\n function newFormat(specifier) {\n specifier = formatSpecifier(specifier);\n var fill = specifier.fill, align3 = specifier.align, sign3 = specifier.sign, symbol2 = specifier.symbol, zero3 = specifier.zero, width2 = specifier.width, comma = specifier.comma, precision = specifier.precision, trim = specifier.trim, type2 = specifier.type;\n if (type2 === \"n\") comma = true, type2 = \"g\";\n else if (!formatTypes_default[type2]) precision === void 0 && (precision = 12), trim = true, type2 = \"g\";\n if (zero3 || fill === \"0\" && align3 === \"=\") zero3 = true, fill = \"0\", align3 = \"=\";\n var prefix2 = symbol2 === \"$\" ? currencyPrefix : symbol2 === \"#\" && /[boxX]/.test(type2) ? \"0\" + type2.toLowerCase() : \"\", suffix2 = symbol2 === \"$\" ? currencySuffix : /[%p]/.test(type2) ? percent : \"\";\n var formatType = formatTypes_default[type2], maybeSuffix = /[defgprs%]/.test(type2);\n precision = precision === void 0 ? 6 : /[gprs]/.test(type2) ? Math.max(1, Math.min(21, precision)) : Math.max(0, Math.min(20, precision));\n function format3(value) {\n var valuePrefix = prefix2, valueSuffix = suffix2, i, n, c4;\n if (type2 === \"c\") {\n valueSuffix = formatType(value) + valueSuffix;\n value = \"\";\n } else {\n value = +value;\n var valueNegative = value < 0 || 1 / value < 0;\n value = isNaN(value) ? nan : formatType(Math.abs(value), precision);\n if (trim) value = formatTrim_default(value);\n if (valueNegative && +value === 0 && sign3 !== \"+\") valueNegative = false;\n valuePrefix = (valueNegative ? sign3 === \"(\" ? sign3 : minus : sign3 === \"-\" || sign3 === \"(\" ? \"\" : sign3) + valuePrefix;\n valueSuffix = (type2 === \"s\" ? prefixes[8 + prefixExponent / 3] : \"\") + valueSuffix + (valueNegative && sign3 === \"(\" ? \")\" : \"\");\n if (maybeSuffix) {\n i = -1, n = value.length;\n while (++i < n) {\n if (c4 = value.charCodeAt(i), 48 > c4 || c4 > 57) {\n valueSuffix = (c4 === 46 ? decimal2 + value.slice(i + 1) : value.slice(i)) + valueSuffix;\n value = value.slice(0, i);\n break;\n }\n }\n }\n }\n if (comma && !zero3) value = group3(value, Infinity);\n var length4 = valuePrefix.length + value.length + valueSuffix.length, padding2 = length4 < width2 ? new Array(width2 - length4 + 1).join(fill) : \"\";\n if (comma && zero3) value = group3(padding2 + value, padding2.length ? width2 - valueSuffix.length : Infinity), padding2 = \"\";\n switch (align3) {\n case \"<\":\n value = valuePrefix + value + valueSuffix + padding2;\n break;\n case \"=\":\n value = valuePrefix + padding2 + value + valueSuffix;\n break;\n case \"^\":\n value = padding2.slice(0, length4 = padding2.length >> 1) + valuePrefix + value + valueSuffix + padding2.slice(length4);\n break;\n default:\n value = padding2 + valuePrefix + value + valueSuffix;\n break;\n }\n return numerals(value);\n }\n format3.toString = function() {\n return specifier + \"\";\n };\n return format3;\n }\n function formatPrefix2(specifier, value) {\n var f = newFormat((specifier = formatSpecifier(specifier), specifier.type = \"f\", specifier)), e = Math.max(-8, Math.min(8, Math.floor(exponent_default(value) / 3))) * 3, k2 = Math.pow(10, -e), prefix2 = prefixes[8 + e / 3];\n return function(value2) {\n return f(k2 * value2) + prefix2;\n };\n }\n return {\n format: newFormat,\n formatPrefix: formatPrefix2\n };\n}\n\n// ../../node_modules/d3-format/src/defaultLocale.js\nvar locale;\nvar format;\nvar formatPrefix;\ndefaultLocale({\n thousands: \",\",\n grouping: [3],\n currency: [\"$\", \"\"]\n});\nfunction defaultLocale(definition) {\n locale = locale_default(definition);\n format = locale.format;\n formatPrefix = locale.formatPrefix;\n return locale;\n}\n\n// ../../node_modules/d3-format/src/precisionFixed.js\nfunction precisionFixed_default(step) {\n return Math.max(0, -exponent_default(Math.abs(step)));\n}\n\n// ../../node_modules/d3-format/src/precisionPrefix.js\nfunction precisionPrefix_default(step, value) {\n return Math.max(0, Math.max(-8, Math.min(8, Math.floor(exponent_default(value) / 3))) * 3 - exponent_default(Math.abs(step)));\n}\n\n// ../../node_modules/d3-format/src/precisionRound.js\nfunction precisionRound_default(step, max4) {\n step = Math.abs(step), max4 = Math.abs(max4) - step;\n return Math.max(0, exponent_default(max4) - exponent_default(step)) + 1;\n}\n\n// ../../node_modules/d3-geo/src/math.js\nvar epsilon6 = 1e-6;\nvar epsilon22 = 1e-12;\nvar pi2 = Math.PI;\nvar halfPi = pi2 / 2;\nvar quarterPi = pi2 / 4;\nvar tau3 = pi2 * 2;\nvar degrees3 = 180 / pi2;\nvar radians2 = pi2 / 180;\nvar abs2 = Math.abs;\nvar atan = Math.atan;\nvar atan2 = Math.atan2;\nvar cos = Math.cos;\nvar ceil = Math.ceil;\nvar exp = Math.exp;\nvar hypot = Math.hypot;\nvar log = Math.log;\nvar pow2 = Math.pow;\nvar sin = Math.sin;\nvar sign = Math.sign || function(x3) {\n return x3 > 0 ? 1 : x3 < 0 ? -1 : 0;\n};\nvar sqrt = Math.sqrt;\nvar tan = Math.tan;\nfunction acos(x3) {\n return x3 > 1 ? 0 : x3 < -1 ? pi2 : Math.acos(x3);\n}\nfunction asin(x3) {\n return x3 > 1 ? halfPi : x3 < -1 ? -halfPi : Math.asin(x3);\n}\n\n// ../../node_modules/d3-geo/src/noop.js\nfunction noop2() {\n}\n\n// ../../node_modules/d3-geo/src/stream.js\nfunction streamGeometry(geometry, stream) {\n if (geometry && streamGeometryType.hasOwnProperty(geometry.type)) {\n streamGeometryType[geometry.type](geometry, stream);\n }\n}\nvar streamObjectType = {\n Feature: function(object, stream) {\n streamGeometry(object.geometry, stream);\n },\n FeatureCollection: function(object, stream) {\n var features = object.features, i = -1, n = features.length;\n while (++i < n) streamGeometry(features[i].geometry, stream);\n }\n};\nvar streamGeometryType = {\n Sphere: function(object, stream) {\n stream.sphere();\n },\n Point: function(object, stream) {\n object = object.coordinates;\n stream.point(object[0], object[1], object[2]);\n },\n MultiPoint: function(object, stream) {\n var coordinates = object.coordinates, i = -1, n = coordinates.length;\n while (++i < n) object = coordinates[i], stream.point(object[0], object[1], object[2]);\n },\n LineString: function(object, stream) {\n streamLine(object.coordinates, stream, 0);\n },\n MultiLineString: function(object, stream) {\n var coordinates = object.coordinates, i = -1, n = coordinates.length;\n while (++i < n) streamLine(coordinates[i], stream, 0);\n },\n Polygon: function(object, stream) {\n streamPolygon(object.coordinates, stream);\n },\n MultiPolygon: function(object, stream) {\n var coordinates = object.coordinates, i = -1, n = coordinates.length;\n while (++i < n) streamPolygon(coordinates[i], stream);\n },\n GeometryCollection: function(object, stream) {\n var geometries = object.geometries, i = -1, n = geometries.length;\n while (++i < n) streamGeometry(geometries[i], stream);\n }\n};\nfunction streamLine(coordinates, stream, closed) {\n var i = -1, n = coordinates.length - closed, coordinate;\n stream.lineStart();\n while (++i < n) coordinate = coordinates[i], stream.point(coordinate[0], coordinate[1], coordinate[2]);\n stream.lineEnd();\n}\nfunction streamPolygon(coordinates, stream) {\n var i = -1, n = coordinates.length;\n stream.polygonStart();\n while (++i < n) streamLine(coordinates[i], stream, 1);\n stream.polygonEnd();\n}\nfunction stream_default(object, stream) {\n if (object && streamObjectType.hasOwnProperty(object.type)) {\n streamObjectType[object.type](object, stream);\n } else {\n streamGeometry(object, stream);\n }\n}\n\n// ../../node_modules/d3-geo/src/cartesian.js\nfunction spherical(cartesian2) {\n return [atan2(cartesian2[1], cartesian2[0]), asin(cartesian2[2])];\n}\nfunction cartesian(spherical2) {\n var lambda = spherical2[0], phi = spherical2[1], cosPhi = cos(phi);\n return [cosPhi * cos(lambda), cosPhi * sin(lambda), sin(phi)];\n}\nfunction cartesianDot(a2, b) {\n return a2[0] * b[0] + a2[1] * b[1] + a2[2] * b[2];\n}\nfunction cartesianCross(a2, b) {\n return [a2[1] * b[2] - a2[2] * b[1], a2[2] * b[0] - a2[0] * b[2], a2[0] * b[1] - a2[1] * b[0]];\n}\nfunction cartesianAddInPlace(a2, b) {\n a2[0] += b[0], a2[1] += b[1], a2[2] += b[2];\n}\nfunction cartesianScale(vector3, k2) {\n return [vector3[0] * k2, vector3[1] * k2, vector3[2] * k2];\n}\nfunction cartesianNormalizeInPlace(d) {\n var l = sqrt(d[0] * d[0] + d[1] * d[1] + d[2] * d[2]);\n d[0] /= l, d[1] /= l, d[2] /= l;\n}\n\n// ../../node_modules/d3-geo/src/centroid.js\nvar W0;\nvar W1;\nvar X0;\nvar Y0;\nvar Z0;\nvar X1;\nvar Y1;\nvar Z1;\nvar X2;\nvar Y2;\nvar Z2;\nvar lambda00;\nvar phi00;\nvar x0;\nvar y0;\nvar z0;\nvar centroidStream = {\n sphere: noop2,\n point: centroidPoint,\n lineStart: centroidLineStart,\n lineEnd: centroidLineEnd,\n polygonStart: function() {\n centroidStream.lineStart = centroidRingStart;\n centroidStream.lineEnd = centroidRingEnd;\n },\n polygonEnd: function() {\n centroidStream.lineStart = centroidLineStart;\n centroidStream.lineEnd = centroidLineEnd;\n }\n};\nfunction centroidPoint(lambda, phi) {\n lambda *= radians2, phi *= radians2;\n var cosPhi = cos(phi);\n centroidPointCartesian(cosPhi * cos(lambda), cosPhi * sin(lambda), sin(phi));\n}\nfunction centroidPointCartesian(x3, y3, z) {\n ++W0;\n X0 += (x3 - X0) / W0;\n Y0 += (y3 - Y0) / W0;\n Z0 += (z - Z0) / W0;\n}\nfunction centroidLineStart() {\n centroidStream.point = centroidLinePointFirst;\n}\nfunction centroidLinePointFirst(lambda, phi) {\n lambda *= radians2, phi *= radians2;\n var cosPhi = cos(phi);\n x0 = cosPhi * cos(lambda);\n y0 = cosPhi * sin(lambda);\n z0 = sin(phi);\n centroidStream.point = centroidLinePoint;\n centroidPointCartesian(x0, y0, z0);\n}\nfunction centroidLinePoint(lambda, phi) {\n lambda *= radians2, phi *= radians2;\n var cosPhi = cos(phi), x3 = cosPhi * cos(lambda), y3 = cosPhi * sin(lambda), z = sin(phi), w = atan2(sqrt((w = y0 * z - z0 * y3) * w + (w = z0 * x3 - x0 * z) * w + (w = x0 * y3 - y0 * x3) * w), x0 * x3 + y0 * y3 + z0 * z);\n W1 += w;\n X1 += w * (x0 + (x0 = x3));\n Y1 += w * (y0 + (y0 = y3));\n Z1 += w * (z0 + (z0 = z));\n centroidPointCartesian(x0, y0, z0);\n}\nfunction centroidLineEnd() {\n centroidStream.point = centroidPoint;\n}\nfunction centroidRingStart() {\n centroidStream.point = centroidRingPointFirst;\n}\nfunction centroidRingEnd() {\n centroidRingPoint(lambda00, phi00);\n centroidStream.point = centroidPoint;\n}\nfunction centroidRingPointFirst(lambda, phi) {\n lambda00 = lambda, phi00 = phi;\n lambda *= radians2, phi *= radians2;\n centroidStream.point = centroidRingPoint;\n var cosPhi = cos(phi);\n x0 = cosPhi * cos(lambda);\n y0 = cosPhi * sin(lambda);\n z0 = sin(phi);\n centroidPointCartesian(x0, y0, z0);\n}\nfunction centroidRingPoint(lambda, phi) {\n lambda *= radians2, phi *= radians2;\n var cosPhi = cos(phi), x3 = cosPhi * cos(lambda), y3 = cosPhi * sin(lambda), z = sin(phi), cx = y0 * z - z0 * y3, cy = z0 * x3 - x0 * z, cz = x0 * y3 - y0 * x3, m = hypot(cx, cy, cz), w = asin(m), v2 = m && -w / m;\n X2.add(v2 * cx);\n Y2.add(v2 * cy);\n Z2.add(v2 * cz);\n W1 += w;\n X1 += w * (x0 + (x0 = x3));\n Y1 += w * (y0 + (y0 = y3));\n Z1 += w * (z0 + (z0 = z));\n centroidPointCartesian(x0, y0, z0);\n}\nfunction centroid_default(object) {\n W0 = W1 = X0 = Y0 = Z0 = X1 = Y1 = Z1 = 0;\n X2 = new Adder();\n Y2 = new Adder();\n Z2 = new Adder();\n stream_default(object, centroidStream);\n var x3 = +X2, y3 = +Y2, z = +Z2, m = hypot(x3, y3, z);\n if (m < epsilon22) {\n x3 = X1, y3 = Y1, z = Z1;\n if (W1 < epsilon6) x3 = X0, y3 = Y0, z = Z0;\n m = hypot(x3, y3, z);\n if (m < epsilon22) return [NaN, NaN];\n }\n return [atan2(y3, x3) * degrees3, asin(z / m) * degrees3];\n}\n\n// ../../node_modules/d3-geo/src/compose.js\nfunction compose_default(a2, b) {\n function compose(x3, y3) {\n return x3 = a2(x3, y3), b(x3[0], x3[1]);\n }\n if (a2.invert && b.invert) compose.invert = function(x3, y3) {\n return x3 = b.invert(x3, y3), x3 && a2.invert(x3[0], x3[1]);\n };\n return compose;\n}\n\n// ../../node_modules/d3-geo/src/rotation.js\nfunction rotationIdentity(lambda, phi) {\n if (abs2(lambda) > pi2) lambda -= Math.round(lambda / tau3) * tau3;\n return [lambda, phi];\n}\nrotationIdentity.invert = rotationIdentity;\nfunction rotateRadians(deltaLambda, deltaPhi, deltaGamma) {\n return (deltaLambda %= tau3) ? deltaPhi || deltaGamma ? compose_default(rotationLambda(deltaLambda), rotationPhiGamma(deltaPhi, deltaGamma)) : rotationLambda(deltaLambda) : deltaPhi || deltaGamma ? rotationPhiGamma(deltaPhi, deltaGamma) : rotationIdentity;\n}\nfunction forwardRotationLambda(deltaLambda) {\n return function(lambda, phi) {\n lambda += deltaLambda;\n if (abs2(lambda) > pi2) lambda -= Math.round(lambda / tau3) * tau3;\n return [lambda, phi];\n };\n}\nfunction rotationLambda(deltaLambda) {\n var rotation = forwardRotationLambda(deltaLambda);\n rotation.invert = forwardRotationLambda(-deltaLambda);\n return rotation;\n}\nfunction rotationPhiGamma(deltaPhi, deltaGamma) {\n var cosDeltaPhi = cos(deltaPhi), sinDeltaPhi = sin(deltaPhi), cosDeltaGamma = cos(deltaGamma), sinDeltaGamma = sin(deltaGamma);\n function rotation(lambda, phi) {\n var cosPhi = cos(phi), x3 = cos(lambda) * cosPhi, y3 = sin(lambda) * cosPhi, z = sin(phi), k2 = z * cosDeltaPhi + x3 * sinDeltaPhi;\n return [\n atan2(y3 * cosDeltaGamma - k2 * sinDeltaGamma, x3 * cosDeltaPhi - z * sinDeltaPhi),\n asin(k2 * cosDeltaGamma + y3 * sinDeltaGamma)\n ];\n }\n rotation.invert = function(lambda, phi) {\n var cosPhi = cos(phi), x3 = cos(lambda) * cosPhi, y3 = sin(lambda) * cosPhi, z = sin(phi), k2 = z * cosDeltaGamma - y3 * sinDeltaGamma;\n return [\n atan2(y3 * cosDeltaGamma + z * sinDeltaGamma, x3 * cosDeltaPhi + k2 * sinDeltaPhi),\n asin(k2 * cosDeltaPhi - x3 * sinDeltaPhi)\n ];\n };\n return rotation;\n}\nfunction rotation_default(rotate) {\n rotate = rotateRadians(rotate[0] * radians2, rotate[1] * radians2, rotate.length > 2 ? rotate[2] * radians2 : 0);\n function forward(coordinates) {\n coordinates = rotate(coordinates[0] * radians2, coordinates[1] * radians2);\n return coordinates[0] *= degrees3, coordinates[1] *= degrees3, coordinates;\n }\n forward.invert = function(coordinates) {\n coordinates = rotate.invert(coordinates[0] * radians2, coordinates[1] * radians2);\n return coordinates[0] *= degrees3, coordinates[1] *= degrees3, coordinates;\n };\n return forward;\n}\n\n// ../../node_modules/d3-geo/src/circle.js\nfunction circleStream(stream, radius2, delta, direction, t03, t13) {\n if (!delta) return;\n var cosRadius = cos(radius2), sinRadius = sin(radius2), step = direction * delta;\n if (t03 == null) {\n t03 = radius2 + direction * tau3;\n t13 = radius2 - step / 2;\n } else {\n t03 = circleRadius(cosRadius, t03);\n t13 = circleRadius(cosRadius, t13);\n if (direction > 0 ? t03 < t13 : t03 > t13) t03 += direction * tau3;\n }\n for (var point6, t = t03; direction > 0 ? t > t13 : t < t13; t -= step) {\n point6 = spherical([cosRadius, -sinRadius * cos(t), -sinRadius * sin(t)]);\n stream.point(point6[0], point6[1]);\n }\n}\nfunction circleRadius(cosRadius, point6) {\n point6 = cartesian(point6), point6[0] -= cosRadius;\n cartesianNormalizeInPlace(point6);\n var radius2 = acos(-point6[1]);\n return ((-point6[2] < 0 ? -radius2 : radius2) + tau3 - epsilon6) % tau3;\n}\n\n// ../../node_modules/d3-geo/src/clip/buffer.js\nfunction buffer_default() {\n var lines = [], line3;\n return {\n point: function(x3, y3, m) {\n line3.push([x3, y3, m]);\n },\n lineStart: function() {\n lines.push(line3 = []);\n },\n lineEnd: noop2,\n rejoin: function() {\n if (lines.length > 1) lines.push(lines.pop().concat(lines.shift()));\n },\n result: function() {\n var result = lines;\n lines = [];\n line3 = null;\n return result;\n }\n };\n}\n\n// ../../node_modules/d3-geo/src/pointEqual.js\nfunction pointEqual_default(a2, b) {\n return abs2(a2[0] - b[0]) < epsilon6 && abs2(a2[1] - b[1]) < epsilon6;\n}\n\n// ../../node_modules/d3-geo/src/clip/rejoin.js\nfunction Intersection(point6, points2, other, entry) {\n this.x = point6;\n this.z = points2;\n this.o = other;\n this.e = entry;\n this.v = false;\n this.n = this.p = null;\n}\nfunction rejoin_default(segments, compareIntersection2, startInside, interpolate, stream) {\n var subject = [], clip = [], i, n;\n segments.forEach(function(segment) {\n if ((n2 = segment.length - 1) <= 0) return;\n var n2, p0 = segment[0], p1 = segment[n2], x3;\n if (pointEqual_default(p0, p1)) {\n if (!p0[2] && !p1[2]) {\n stream.lineStart();\n for (i = 0; i < n2; ++i) stream.point((p0 = segment[i])[0], p0[1]);\n stream.lineEnd();\n return;\n }\n p1[0] += 2 * epsilon6;\n }\n subject.push(x3 = new Intersection(p0, segment, null, true));\n clip.push(x3.o = new Intersection(p0, null, x3, false));\n subject.push(x3 = new Intersection(p1, segment, null, false));\n clip.push(x3.o = new Intersection(p1, null, x3, true));\n });\n if (!subject.length) return;\n clip.sort(compareIntersection2);\n link(subject);\n link(clip);\n for (i = 0, n = clip.length; i < n; ++i) {\n clip[i].e = startInside = !startInside;\n }\n var start2 = subject[0], points2, point6;\n while (1) {\n var current = start2, isSubject = true;\n while (current.v) if ((current = current.n) === start2) return;\n points2 = current.z;\n stream.lineStart();\n do {\n current.v = current.o.v = true;\n if (current.e) {\n if (isSubject) {\n for (i = 0, n = points2.length; i < n; ++i) stream.point((point6 = points2[i])[0], point6[1]);\n } else {\n interpolate(current.x, current.n.x, 1, stream);\n }\n current = current.n;\n } else {\n if (isSubject) {\n points2 = current.p.z;\n for (i = points2.length - 1; i >= 0; --i) stream.point((point6 = points2[i])[0], point6[1]);\n } else {\n interpolate(current.x, current.p.x, -1, stream);\n }\n current = current.p;\n }\n current = current.o;\n points2 = current.z;\n isSubject = !isSubject;\n } while (!current.v);\n stream.lineEnd();\n }\n}\nfunction link(array4) {\n if (!(n = array4.length)) return;\n var n, i = 0, a2 = array4[0], b;\n while (++i < n) {\n a2.n = b = array4[i];\n b.p = a2;\n a2 = b;\n }\n a2.n = b = array4[0];\n b.p = a2;\n}\n\n// ../../node_modules/d3-geo/src/polygonContains.js\nfunction longitude(point6) {\n return abs2(point6[0]) <= pi2 ? point6[0] : sign(point6[0]) * ((abs2(point6[0]) + pi2) % tau3 - pi2);\n}\nfunction polygonContains_default(polygon, point6) {\n var lambda = longitude(point6), phi = point6[1], sinPhi = sin(phi), normal = [sin(lambda), -cos(lambda), 0], angle = 0, winding = 0;\n var sum4 = new Adder();\n if (sinPhi === 1) phi = halfPi + epsilon6;\n else if (sinPhi === -1) phi = -halfPi - epsilon6;\n for (var i = 0, n = polygon.length; i < n; ++i) {\n if (!(m = (ring = polygon[i]).length)) continue;\n var ring, m, point0 = ring[m - 1], lambda0 = longitude(point0), phi0 = point0[1] / 2 + quarterPi, sinPhi0 = sin(phi0), cosPhi0 = cos(phi0);\n for (var j = 0; j < m; ++j, lambda0 = lambda1, sinPhi0 = sinPhi1, cosPhi0 = cosPhi1, point0 = point1) {\n var point1 = ring[j], lambda1 = longitude(point1), phi1 = point1[1] / 2 + quarterPi, sinPhi1 = sin(phi1), cosPhi1 = cos(phi1), delta = lambda1 - lambda0, sign3 = delta >= 0 ? 1 : -1, absDelta = sign3 * delta, antimeridian = absDelta > pi2, k2 = sinPhi0 * sinPhi1;\n sum4.add(atan2(k2 * sign3 * sin(absDelta), cosPhi0 * cosPhi1 + k2 * cos(absDelta)));\n angle += antimeridian ? delta + sign3 * tau3 : delta;\n if (antimeridian ^ lambda0 >= lambda ^ lambda1 >= lambda) {\n var arc = cartesianCross(cartesian(point0), cartesian(point1));\n cartesianNormalizeInPlace(arc);\n var intersection = cartesianCross(normal, arc);\n cartesianNormalizeInPlace(intersection);\n var phiArc = (antimeridian ^ delta >= 0 ? -1 : 1) * asin(intersection[2]);\n if (phi > phiArc || phi === phiArc && (arc[0] || arc[1])) {\n winding += antimeridian ^ delta >= 0 ? 1 : -1;\n }\n }\n }\n }\n return (angle < -epsilon6 || angle < epsilon6 && sum4 < -epsilon22) ^ winding & 1;\n}\n\n// ../../node_modules/d3-geo/src/clip/index.js\nfunction clip_default(pointVisible, clipLine, interpolate, start2) {\n return function(sink) {\n var line3 = clipLine(sink), ringBuffer = buffer_default(), ringSink = clipLine(ringBuffer), polygonStarted = false, polygon, segments, ring;\n var clip = {\n point: point6,\n lineStart,\n lineEnd,\n polygonStart: function() {\n clip.point = pointRing;\n clip.lineStart = ringStart;\n clip.lineEnd = ringEnd;\n segments = [];\n polygon = [];\n },\n polygonEnd: function() {\n clip.point = point6;\n clip.lineStart = lineStart;\n clip.lineEnd = lineEnd;\n segments = merge(segments);\n var startInside = polygonContains_default(polygon, start2);\n if (segments.length) {\n if (!polygonStarted) sink.polygonStart(), polygonStarted = true;\n rejoin_default(segments, compareIntersection, startInside, interpolate, sink);\n } else if (startInside) {\n if (!polygonStarted) sink.polygonStart(), polygonStarted = true;\n sink.lineStart();\n interpolate(null, null, 1, sink);\n sink.lineEnd();\n }\n if (polygonStarted) sink.polygonEnd(), polygonStarted = false;\n segments = polygon = null;\n },\n sphere: function() {\n sink.polygonStart();\n sink.lineStart();\n interpolate(null, null, 1, sink);\n sink.lineEnd();\n sink.polygonEnd();\n }\n };\n function point6(lambda, phi) {\n if (pointVisible(lambda, phi)) sink.point(lambda, phi);\n }\n function pointLine(lambda, phi) {\n line3.point(lambda, phi);\n }\n function lineStart() {\n clip.point = pointLine;\n line3.lineStart();\n }\n function lineEnd() {\n clip.point = point6;\n line3.lineEnd();\n }\n function pointRing(lambda, phi) {\n ring.push([lambda, phi]);\n ringSink.point(lambda, phi);\n }\n function ringStart() {\n ringSink.lineStart();\n ring = [];\n }\n function ringEnd() {\n pointRing(ring[0][0], ring[0][1]);\n ringSink.lineEnd();\n var clean = ringSink.clean(), ringSegments = ringBuffer.result(), i, n = ringSegments.length, m, segment, point7;\n ring.pop();\n polygon.push(ring);\n ring = null;\n if (!n) return;\n if (clean & 1) {\n segment = ringSegments[0];\n if ((m = segment.length - 1) > 0) {\n if (!polygonStarted) sink.polygonStart(), polygonStarted = true;\n sink.lineStart();\n for (i = 0; i < m; ++i) sink.point((point7 = segment[i])[0], point7[1]);\n sink.lineEnd();\n }\n return;\n }\n if (n > 1 && clean & 2) ringSegments.push(ringSegments.pop().concat(ringSegments.shift()));\n segments.push(ringSegments.filter(validSegment));\n }\n return clip;\n };\n}\nfunction validSegment(segment) {\n return segment.length > 1;\n}\nfunction compareIntersection(a2, b) {\n return ((a2 = a2.x)[0] < 0 ? a2[1] - halfPi - epsilon6 : halfPi - a2[1]) - ((b = b.x)[0] < 0 ? b[1] - halfPi - epsilon6 : halfPi - b[1]);\n}\n\n// ../../node_modules/d3-geo/src/clip/antimeridian.js\nvar antimeridian_default = clip_default(\n function() {\n return true;\n },\n clipAntimeridianLine,\n clipAntimeridianInterpolate,\n [-pi2, -halfPi]\n);\nfunction clipAntimeridianLine(stream) {\n var lambda0 = NaN, phi0 = NaN, sign0 = NaN, clean;\n return {\n lineStart: function() {\n stream.lineStart();\n clean = 1;\n },\n point: function(lambda1, phi1) {\n var sign1 = lambda1 > 0 ? pi2 : -pi2, delta = abs2(lambda1 - lambda0);\n if (abs2(delta - pi2) < epsilon6) {\n stream.point(lambda0, phi0 = (phi0 + phi1) / 2 > 0 ? halfPi : -halfPi);\n stream.point(sign0, phi0);\n stream.lineEnd();\n stream.lineStart();\n stream.point(sign1, phi0);\n stream.point(lambda1, phi0);\n clean = 0;\n } else if (sign0 !== sign1 && delta >= pi2) {\n if (abs2(lambda0 - sign0) < epsilon6) lambda0 -= sign0 * epsilon6;\n if (abs2(lambda1 - sign1) < epsilon6) lambda1 -= sign1 * epsilon6;\n phi0 = clipAntimeridianIntersect(lambda0, phi0, lambda1, phi1);\n stream.point(sign0, phi0);\n stream.lineEnd();\n stream.lineStart();\n stream.point(sign1, phi0);\n clean = 0;\n }\n stream.point(lambda0 = lambda1, phi0 = phi1);\n sign0 = sign1;\n },\n lineEnd: function() {\n stream.lineEnd();\n lambda0 = phi0 = NaN;\n },\n clean: function() {\n return 2 - clean;\n }\n };\n}\nfunction clipAntimeridianIntersect(lambda0, phi0, lambda1, phi1) {\n var cosPhi0, cosPhi1, sinLambda0Lambda1 = sin(lambda0 - lambda1);\n return abs2(sinLambda0Lambda1) > epsilon6 ? atan((sin(phi0) * (cosPhi1 = cos(phi1)) * sin(lambda1) - sin(phi1) * (cosPhi0 = cos(phi0)) * sin(lambda0)) / (cosPhi0 * cosPhi1 * sinLambda0Lambda1)) : (phi0 + phi1) / 2;\n}\nfunction clipAntimeridianInterpolate(from2, to, direction, stream) {\n var phi;\n if (from2 == null) {\n phi = direction * halfPi;\n stream.point(-pi2, phi);\n stream.point(0, phi);\n stream.point(pi2, phi);\n stream.point(pi2, 0);\n stream.point(pi2, -phi);\n stream.point(0, -phi);\n stream.point(-pi2, -phi);\n stream.point(-pi2, 0);\n stream.point(-pi2, phi);\n } else if (abs2(from2[0] - to[0]) > epsilon6) {\n var lambda = from2[0] < to[0] ? pi2 : -pi2;\n phi = direction * lambda / 2;\n stream.point(-lambda, phi);\n stream.point(0, phi);\n stream.point(lambda, phi);\n } else {\n stream.point(to[0], to[1]);\n }\n}\n\n// ../../node_modules/d3-geo/src/clip/circle.js\nfunction circle_default(radius2) {\n var cr = cos(radius2), delta = 6 * radians2, smallRadius = cr > 0, notHemisphere = abs2(cr) > epsilon6;\n function interpolate(from2, to, direction, stream) {\n circleStream(stream, radius2, delta, direction, from2, to);\n }\n function visible(lambda, phi) {\n return cos(lambda) * cos(phi) > cr;\n }\n function clipLine(stream) {\n var point0, c0, v0, v00, clean;\n return {\n lineStart: function() {\n v00 = v0 = false;\n clean = 1;\n },\n point: function(lambda, phi) {\n var point1 = [lambda, phi], point22, v2 = visible(lambda, phi), c4 = smallRadius ? v2 ? 0 : code(lambda, phi) : v2 ? code(lambda + (lambda < 0 ? pi2 : -pi2), phi) : 0;\n if (!point0 && (v00 = v0 = v2)) stream.lineStart();\n if (v2 !== v0) {\n point22 = intersect(point0, point1);\n if (!point22 || pointEqual_default(point0, point22) || pointEqual_default(point1, point22))\n point1[2] = 1;\n }\n if (v2 !== v0) {\n clean = 0;\n if (v2) {\n stream.lineStart();\n point22 = intersect(point1, point0);\n stream.point(point22[0], point22[1]);\n } else {\n point22 = intersect(point0, point1);\n stream.point(point22[0], point22[1], 2);\n stream.lineEnd();\n }\n point0 = point22;\n } else if (notHemisphere && point0 && smallRadius ^ v2) {\n var t;\n if (!(c4 & c0) && (t = intersect(point1, point0, true))) {\n clean = 0;\n if (smallRadius) {\n stream.lineStart();\n stream.point(t[0][0], t[0][1]);\n stream.point(t[1][0], t[1][1]);\n stream.lineEnd();\n } else {\n stream.point(t[1][0], t[1][1]);\n stream.lineEnd();\n stream.lineStart();\n stream.point(t[0][0], t[0][1], 3);\n }\n }\n }\n if (v2 && (!point0 || !pointEqual_default(point0, point1))) {\n stream.point(point1[0], point1[1]);\n }\n point0 = point1, v0 = v2, c0 = c4;\n },\n lineEnd: function() {\n if (v0) stream.lineEnd();\n point0 = null;\n },\n // Rejoin first and last segments if there were intersections and the first\n // and last points were visible.\n clean: function() {\n return clean | (v00 && v0) << 1;\n }\n };\n }\n function intersect(a2, b, two) {\n var pa = cartesian(a2), pb = cartesian(b);\n var n1 = [1, 0, 0], n2 = cartesianCross(pa, pb), n2n2 = cartesianDot(n2, n2), n1n2 = n2[0], determinant = n2n2 - n1n2 * n1n2;\n if (!determinant) return !two && a2;\n var c1 = cr * n2n2 / determinant, c22 = -cr * n1n2 / determinant, n1xn2 = cartesianCross(n1, n2), A5 = cartesianScale(n1, c1), B3 = cartesianScale(n2, c22);\n cartesianAddInPlace(A5, B3);\n var u4 = n1xn2, w = cartesianDot(A5, u4), uu = cartesianDot(u4, u4), t22 = w * w - uu * (cartesianDot(A5, A5) - 1);\n if (t22 < 0) return;\n var t = sqrt(t22), q = cartesianScale(u4, (-w - t) / uu);\n cartesianAddInPlace(q, A5);\n q = spherical(q);\n if (!two) return q;\n var lambda0 = a2[0], lambda1 = b[0], phi0 = a2[1], phi1 = b[1], z;\n if (lambda1 < lambda0) z = lambda0, lambda0 = lambda1, lambda1 = z;\n var delta2 = lambda1 - lambda0, polar = abs2(delta2 - pi2) < epsilon6, meridian = polar || delta2 < epsilon6;\n if (!polar && phi1 < phi0) z = phi0, phi0 = phi1, phi1 = z;\n if (meridian ? polar ? phi0 + phi1 > 0 ^ q[1] < (abs2(q[0] - lambda0) < epsilon6 ? phi0 : phi1) : phi0 <= q[1] && q[1] <= phi1 : delta2 > pi2 ^ (lambda0 <= q[0] && q[0] <= lambda1)) {\n var q1 = cartesianScale(u4, (-w + t) / uu);\n cartesianAddInPlace(q1, A5);\n return [q, spherical(q1)];\n }\n }\n function code(lambda, phi) {\n var r = smallRadius ? radius2 : pi2 - radius2, code2 = 0;\n if (lambda < -r) code2 |= 1;\n else if (lambda > r) code2 |= 2;\n if (phi < -r) code2 |= 4;\n else if (phi > r) code2 |= 8;\n return code2;\n }\n return clip_default(visible, clipLine, interpolate, smallRadius ? [0, -radius2] : [-pi2, radius2 - pi2]);\n}\n\n// ../../node_modules/d3-geo/src/clip/line.js\nfunction line_default(a2, b, x06, y06, x12, y12) {\n var ax = a2[0], ay = a2[1], bx = b[0], by = b[1], t03 = 0, t13 = 1, dx = bx - ax, dy = by - ay, r;\n r = x06 - ax;\n if (!dx && r > 0) return;\n r /= dx;\n if (dx < 0) {\n if (r < t03) return;\n if (r < t13) t13 = r;\n } else if (dx > 0) {\n if (r > t13) return;\n if (r > t03) t03 = r;\n }\n r = x12 - ax;\n if (!dx && r < 0) return;\n r /= dx;\n if (dx < 0) {\n if (r > t13) return;\n if (r > t03) t03 = r;\n } else if (dx > 0) {\n if (r < t03) return;\n if (r < t13) t13 = r;\n }\n r = y06 - ay;\n if (!dy && r > 0) return;\n r /= dy;\n if (dy < 0) {\n if (r < t03) return;\n if (r < t13) t13 = r;\n } else if (dy > 0) {\n if (r > t13) return;\n if (r > t03) t03 = r;\n }\n r = y12 - ay;\n if (!dy && r < 0) return;\n r /= dy;\n if (dy < 0) {\n if (r > t13) return;\n if (r > t03) t03 = r;\n } else if (dy > 0) {\n if (r < t03) return;\n if (r < t13) t13 = r;\n }\n if (t03 > 0) a2[0] = ax + t03 * dx, a2[1] = ay + t03 * dy;\n if (t13 < 1) b[0] = ax + t13 * dx, b[1] = ay + t13 * dy;\n return true;\n}\n\n// ../../node_modules/d3-geo/src/clip/rectangle.js\nvar clipMax = 1e9;\nvar clipMin = -clipMax;\nfunction clipRectangle(x06, y06, x12, y12) {\n function visible(x3, y3) {\n return x06 <= x3 && x3 <= x12 && y06 <= y3 && y3 <= y12;\n }\n function interpolate(from2, to, direction, stream) {\n var a2 = 0, a1 = 0;\n if (from2 == null || (a2 = corner(from2, direction)) !== (a1 = corner(to, direction)) || comparePoint(from2, to) < 0 ^ direction > 0) {\n do\n stream.point(a2 === 0 || a2 === 3 ? x06 : x12, a2 > 1 ? y12 : y06);\n while ((a2 = (a2 + direction + 4) % 4) !== a1);\n } else {\n stream.point(to[0], to[1]);\n }\n }\n function corner(p, direction) {\n return abs2(p[0] - x06) < epsilon6 ? direction > 0 ? 0 : 3 : abs2(p[0] - x12) < epsilon6 ? direction > 0 ? 2 : 1 : abs2(p[1] - y06) < epsilon6 ? direction > 0 ? 1 : 0 : direction > 0 ? 3 : 2;\n }\n function compareIntersection2(a2, b) {\n return comparePoint(a2.x, b.x);\n }\n function comparePoint(a2, b) {\n var ca3 = corner(a2, 1), cb = corner(b, 1);\n return ca3 !== cb ? ca3 - cb : ca3 === 0 ? b[1] - a2[1] : ca3 === 1 ? a2[0] - b[0] : ca3 === 2 ? a2[1] - b[1] : b[0] - a2[0];\n }\n return function(stream) {\n var activeStream = stream, bufferStream = buffer_default(), segments, polygon, ring, x__, y__, v__, x_, y_, v_, first3, clean;\n var clipStream = {\n point: point6,\n lineStart,\n lineEnd,\n polygonStart,\n polygonEnd\n };\n function point6(x3, y3) {\n if (visible(x3, y3)) activeStream.point(x3, y3);\n }\n function polygonInside() {\n var winding = 0;\n for (var i = 0, n = polygon.length; i < n; ++i) {\n for (var ring2 = polygon[i], j = 1, m = ring2.length, point7 = ring2[0], a0, a1, b0 = point7[0], b1 = point7[1]; j < m; ++j) {\n a0 = b0, a1 = b1, point7 = ring2[j], b0 = point7[0], b1 = point7[1];\n if (a1 <= y12) {\n if (b1 > y12 && (b0 - a0) * (y12 - a1) > (b1 - a1) * (x06 - a0)) ++winding;\n } else {\n if (b1 <= y12 && (b0 - a0) * (y12 - a1) < (b1 - a1) * (x06 - a0)) --winding;\n }\n }\n }\n return winding;\n }\n function polygonStart() {\n activeStream = bufferStream, segments = [], polygon = [], clean = true;\n }\n function polygonEnd() {\n var startInside = polygonInside(), cleanInside = clean && startInside, visible2 = (segments = merge(segments)).length;\n if (cleanInside || visible2) {\n stream.polygonStart();\n if (cleanInside) {\n stream.lineStart();\n interpolate(null, null, 1, stream);\n stream.lineEnd();\n }\n if (visible2) {\n rejoin_default(segments, compareIntersection2, startInside, interpolate, stream);\n }\n stream.polygonEnd();\n }\n activeStream = stream, segments = polygon = ring = null;\n }\n function lineStart() {\n clipStream.point = linePoint;\n if (polygon) polygon.push(ring = []);\n first3 = true;\n v_ = false;\n x_ = y_ = NaN;\n }\n function lineEnd() {\n if (segments) {\n linePoint(x__, y__);\n if (v__ && v_) bufferStream.rejoin();\n segments.push(bufferStream.result());\n }\n clipStream.point = point6;\n if (v_) activeStream.lineEnd();\n }\n function linePoint(x3, y3) {\n var v2 = visible(x3, y3);\n if (polygon) ring.push([x3, y3]);\n if (first3) {\n x__ = x3, y__ = y3, v__ = v2;\n first3 = false;\n if (v2) {\n activeStream.lineStart();\n activeStream.point(x3, y3);\n }\n } else {\n if (v2 && v_) activeStream.point(x3, y3);\n else {\n var a2 = [x_ = Math.max(clipMin, Math.min(clipMax, x_)), y_ = Math.max(clipMin, Math.min(clipMax, y_))], b = [x3 = Math.max(clipMin, Math.min(clipMax, x3)), y3 = Math.max(clipMin, Math.min(clipMax, y3))];\n if (line_default(a2, b, x06, y06, x12, y12)) {\n if (!v_) {\n activeStream.lineStart();\n activeStream.point(a2[0], a2[1]);\n }\n activeStream.point(b[0], b[1]);\n if (!v2) activeStream.lineEnd();\n clean = false;\n } else if (v2) {\n activeStream.lineStart();\n activeStream.point(x3, y3);\n clean = false;\n }\n }\n }\n x_ = x3, y_ = y3, v_ = v2;\n }\n return clipStream;\n };\n}\n\n// ../../node_modules/d3-geo/src/graticule.js\nfunction graticuleX(y06, y12, dy) {\n var y3 = range(y06, y12 - epsilon6, dy).concat(y12);\n return function(x3) {\n return y3.map(function(y4) {\n return [x3, y4];\n });\n };\n}\nfunction graticuleY(x06, x12, dx) {\n var x3 = range(x06, x12 - epsilon6, dx).concat(x12);\n return function(y3) {\n return x3.map(function(x4) {\n return [x4, y3];\n });\n };\n}\nfunction graticule() {\n var x12, x06, X13, X03, y12, y06, Y13, Y03, dx = 10, dy = dx, DX = 90, DY = 360, x3, y3, X3, Y3, precision = 2.5;\n function graticule4() {\n return { type: \"MultiLineString\", coordinates: lines() };\n }\n function lines() {\n return range(ceil(X03 / DX) * DX, X13, DX).map(X3).concat(range(ceil(Y03 / DY) * DY, Y13, DY).map(Y3)).concat(range(ceil(x06 / dx) * dx, x12, dx).filter(function(x4) {\n return abs2(x4 % DX) > epsilon6;\n }).map(x3)).concat(range(ceil(y06 / dy) * dy, y12, dy).filter(function(y4) {\n return abs2(y4 % DY) > epsilon6;\n }).map(y3));\n }\n graticule4.lines = function() {\n return lines().map(function(coordinates) {\n return { type: \"LineString\", coordinates };\n });\n };\n graticule4.outline = function() {\n return {\n type: \"Polygon\",\n coordinates: [\n X3(X03).concat(\n Y3(Y13).slice(1),\n X3(X13).reverse().slice(1),\n Y3(Y03).reverse().slice(1)\n )\n ]\n };\n };\n graticule4.extent = function(_) {\n if (!arguments.length) return graticule4.extentMinor();\n return graticule4.extentMajor(_).extentMinor(_);\n };\n graticule4.extentMajor = function(_) {\n if (!arguments.length) return [[X03, Y03], [X13, Y13]];\n X03 = +_[0][0], X13 = +_[1][0];\n Y03 = +_[0][1], Y13 = +_[1][1];\n if (X03 > X13) _ = X03, X03 = X13, X13 = _;\n if (Y03 > Y13) _ = Y03, Y03 = Y13, Y13 = _;\n return graticule4.precision(precision);\n };\n graticule4.extentMinor = function(_) {\n if (!arguments.length) return [[x06, y06], [x12, y12]];\n x06 = +_[0][0], x12 = +_[1][0];\n y06 = +_[0][1], y12 = +_[1][1];\n if (x06 > x12) _ = x06, x06 = x12, x12 = _;\n if (y06 > y12) _ = y06, y06 = y12, y12 = _;\n return graticule4.precision(precision);\n };\n graticule4.step = function(_) {\n if (!arguments.length) return graticule4.stepMinor();\n return graticule4.stepMajor(_).stepMinor(_);\n };\n graticule4.stepMajor = function(_) {\n if (!arguments.length) return [DX, DY];\n DX = +_[0], DY = +_[1];\n return graticule4;\n };\n graticule4.stepMinor = function(_) {\n if (!arguments.length) return [dx, dy];\n dx = +_[0], dy = +_[1];\n return graticule4;\n };\n graticule4.precision = function(_) {\n if (!arguments.length) return precision;\n precision = +_;\n x3 = graticuleX(y06, y12, 90);\n y3 = graticuleY(x06, x12, precision);\n X3 = graticuleX(Y03, Y13, 90);\n Y3 = graticuleY(X03, X13, precision);\n return graticule4;\n };\n return graticule4.extentMajor([[-180, -90 + epsilon6], [180, 90 - epsilon6]]).extentMinor([[-180, -80 - epsilon6], [180, 80 + epsilon6]]);\n}\nfunction graticule10() {\n return graticule()();\n}\n\n// ../../node_modules/d3-geo/src/identity.js\nvar identity_default3 = (x3) => x3;\n\n// ../../node_modules/d3-geo/src/path/area.js\nvar areaSum = new Adder();\nvar areaRingSum = new Adder();\nvar x00;\nvar y00;\nvar x02;\nvar y02;\nvar areaStream = {\n point: noop2,\n lineStart: noop2,\n lineEnd: noop2,\n polygonStart: function() {\n areaStream.lineStart = areaRingStart;\n areaStream.lineEnd = areaRingEnd;\n },\n polygonEnd: function() {\n areaStream.lineStart = areaStream.lineEnd = areaStream.point = noop2;\n areaSum.add(abs2(areaRingSum));\n areaRingSum = new Adder();\n },\n result: function() {\n var area3 = areaSum / 2;\n areaSum = new Adder();\n return area3;\n }\n};\nfunction areaRingStart() {\n areaStream.point = areaPointFirst;\n}\nfunction areaPointFirst(x3, y3) {\n areaStream.point = areaPoint;\n x00 = x02 = x3, y00 = y02 = y3;\n}\nfunction areaPoint(x3, y3) {\n areaRingSum.add(y02 * x3 - x02 * y3);\n x02 = x3, y02 = y3;\n}\nfunction areaRingEnd() {\n areaPoint(x00, y00);\n}\nvar area_default2 = areaStream;\n\n// ../../node_modules/d3-geo/src/path/bounds.js\nvar x03 = Infinity;\nvar y03 = x03;\nvar x1 = -x03;\nvar y1 = x1;\nvar boundsStream = {\n point: boundsPoint,\n lineStart: noop2,\n lineEnd: noop2,\n polygonStart: noop2,\n polygonEnd: noop2,\n result: function() {\n var bounds = [[x03, y03], [x1, y1]];\n x1 = y1 = -(y03 = x03 = Infinity);\n return bounds;\n }\n};\nfunction boundsPoint(x3, y3) {\n if (x3 < x03) x03 = x3;\n if (x3 > x1) x1 = x3;\n if (y3 < y03) y03 = y3;\n if (y3 > y1) y1 = y3;\n}\nvar bounds_default = boundsStream;\n\n// ../../node_modules/d3-geo/src/path/centroid.js\nvar X02 = 0;\nvar Y02 = 0;\nvar Z02 = 0;\nvar X12 = 0;\nvar Y12 = 0;\nvar Z12 = 0;\nvar X22 = 0;\nvar Y22 = 0;\nvar Z22 = 0;\nvar x002;\nvar y002;\nvar x04;\nvar y04;\nvar centroidStream2 = {\n point: centroidPoint2,\n lineStart: centroidLineStart2,\n lineEnd: centroidLineEnd2,\n polygonStart: function() {\n centroidStream2.lineStart = centroidRingStart2;\n centroidStream2.lineEnd = centroidRingEnd2;\n },\n polygonEnd: function() {\n centroidStream2.point = centroidPoint2;\n centroidStream2.lineStart = centroidLineStart2;\n centroidStream2.lineEnd = centroidLineEnd2;\n },\n result: function() {\n var centroid3 = Z22 ? [X22 / Z22, Y22 / Z22] : Z12 ? [X12 / Z12, Y12 / Z12] : Z02 ? [X02 / Z02, Y02 / Z02] : [NaN, NaN];\n X02 = Y02 = Z02 = X12 = Y12 = Z12 = X22 = Y22 = Z22 = 0;\n return centroid3;\n }\n};\nfunction centroidPoint2(x3, y3) {\n X02 += x3;\n Y02 += y3;\n ++Z02;\n}\nfunction centroidLineStart2() {\n centroidStream2.point = centroidPointFirstLine;\n}\nfunction centroidPointFirstLine(x3, y3) {\n centroidStream2.point = centroidPointLine;\n centroidPoint2(x04 = x3, y04 = y3);\n}\nfunction centroidPointLine(x3, y3) {\n var dx = x3 - x04, dy = y3 - y04, z = sqrt(dx * dx + dy * dy);\n X12 += z * (x04 + x3) / 2;\n Y12 += z * (y04 + y3) / 2;\n Z12 += z;\n centroidPoint2(x04 = x3, y04 = y3);\n}\nfunction centroidLineEnd2() {\n centroidStream2.point = centroidPoint2;\n}\nfunction centroidRingStart2() {\n centroidStream2.point = centroidPointFirstRing;\n}\nfunction centroidRingEnd2() {\n centroidPointRing(x002, y002);\n}\nfunction centroidPointFirstRing(x3, y3) {\n centroidStream2.point = centroidPointRing;\n centroidPoint2(x002 = x04 = x3, y002 = y04 = y3);\n}\nfunction centroidPointRing(x3, y3) {\n var dx = x3 - x04, dy = y3 - y04, z = sqrt(dx * dx + dy * dy);\n X12 += z * (x04 + x3) / 2;\n Y12 += z * (y04 + y3) / 2;\n Z12 += z;\n z = y04 * x3 - x04 * y3;\n X22 += z * (x04 + x3);\n Y22 += z * (y04 + y3);\n Z22 += z * 3;\n centroidPoint2(x04 = x3, y04 = y3);\n}\nvar centroid_default2 = centroidStream2;\n\n// ../../node_modules/d3-geo/src/path/context.js\nfunction PathContext(context) {\n this._context = context;\n}\nPathContext.prototype = {\n _radius: 4.5,\n pointRadius: function(_) {\n return this._radius = _, this;\n },\n polygonStart: function() {\n this._line = 0;\n },\n polygonEnd: function() {\n this._line = NaN;\n },\n lineStart: function() {\n this._point = 0;\n },\n lineEnd: function() {\n if (this._line === 0) this._context.closePath();\n this._point = NaN;\n },\n point: function(x3, y3) {\n switch (this._point) {\n case 0: {\n this._context.moveTo(x3, y3);\n this._point = 1;\n break;\n }\n case 1: {\n this._context.lineTo(x3, y3);\n break;\n }\n default: {\n this._context.moveTo(x3 + this._radius, y3);\n this._context.arc(x3, y3, this._radius, 0, tau3);\n break;\n }\n }\n },\n result: noop2\n};\n\n// ../../node_modules/d3-geo/src/path/measure.js\nvar lengthSum = new Adder();\nvar lengthRing;\nvar x003;\nvar y003;\nvar x05;\nvar y05;\nvar lengthStream = {\n point: noop2,\n lineStart: function() {\n lengthStream.point = lengthPointFirst;\n },\n lineEnd: function() {\n if (lengthRing) lengthPoint(x003, y003);\n lengthStream.point = noop2;\n },\n polygonStart: function() {\n lengthRing = true;\n },\n polygonEnd: function() {\n lengthRing = null;\n },\n result: function() {\n var length4 = +lengthSum;\n lengthSum = new Adder();\n return length4;\n }\n};\nfunction lengthPointFirst(x3, y3) {\n lengthStream.point = lengthPoint;\n x003 = x05 = x3, y003 = y05 = y3;\n}\nfunction lengthPoint(x3, y3) {\n x05 -= x3, y05 -= y3;\n lengthSum.add(sqrt(x05 * x05 + y05 * y05));\n x05 = x3, y05 = y3;\n}\nvar measure_default = lengthStream;\n\n// ../../node_modules/d3-geo/src/path/string.js\nvar cacheDigits;\nvar cacheAppend;\nvar cacheRadius;\nvar cacheCircle;\nvar PathString = class {\n constructor(digits) {\n this._append = digits == null ? append2 : appendRound2(digits);\n this._radius = 4.5;\n this._ = \"\";\n }\n pointRadius(_) {\n this._radius = +_;\n return this;\n }\n polygonStart() {\n this._line = 0;\n }\n polygonEnd() {\n this._line = NaN;\n }\n lineStart() {\n this._point = 0;\n }\n lineEnd() {\n if (this._line === 0) this._ += \"Z\";\n this._point = NaN;\n }\n point(x3, y3) {\n switch (this._point) {\n case 0: {\n this._append`M${x3},${y3}`;\n this._point = 1;\n break;\n }\n case 1: {\n this._append`L${x3},${y3}`;\n break;\n }\n default: {\n this._append`M${x3},${y3}`;\n if (this._radius !== cacheRadius || this._append !== cacheAppend) {\n const r = this._radius;\n const s2 = this._;\n this._ = \"\";\n this._append`m0,${r}a${r},${r} 0 1,1 0,${-2 * r}a${r},${r} 0 1,1 0,${2 * r}z`;\n cacheRadius = r;\n cacheAppend = this._append;\n cacheCircle = this._;\n this._ = s2;\n }\n this._ += cacheCircle;\n break;\n }\n }\n }\n result() {\n const result = this._;\n this._ = \"\";\n return result.length ? result : null;\n }\n};\nfunction append2(strings) {\n let i = 1;\n this._ += strings[0];\n for (const j = strings.length; i < j; ++i) {\n this._ += arguments[i] + strings[i];\n }\n}\nfunction appendRound2(digits) {\n const d = Math.floor(digits);\n if (!(d >= 0)) throw new RangeError(`invalid digits: ${digits}`);\n if (d > 15) return append2;\n if (d !== cacheDigits) {\n const k2 = 10 ** d;\n cacheDigits = d;\n cacheAppend = function append3(strings) {\n let i = 1;\n this._ += strings[0];\n for (const j = strings.length; i < j; ++i) {\n this._ += Math.round(arguments[i] * k2) / k2 + strings[i];\n }\n };\n }\n return cacheAppend;\n}\n\n// ../../node_modules/d3-geo/src/path/index.js\nfunction path_default(projection3, context) {\n let digits = 3, pointRadius = 4.5, projectionStream, contextStream;\n function path2(object) {\n if (object) {\n if (typeof pointRadius === \"function\") contextStream.pointRadius(+pointRadius.apply(this, arguments));\n stream_default(object, projectionStream(contextStream));\n }\n return contextStream.result();\n }\n path2.area = function(object) {\n stream_default(object, projectionStream(area_default2));\n return area_default2.result();\n };\n path2.measure = function(object) {\n stream_default(object, projectionStream(measure_default));\n return measure_default.result();\n };\n path2.bounds = function(object) {\n stream_default(object, projectionStream(bounds_default));\n return bounds_default.result();\n };\n path2.centroid = function(object) {\n stream_default(object, projectionStream(centroid_default2));\n return centroid_default2.result();\n };\n path2.projection = function(_) {\n if (!arguments.length) return projection3;\n projectionStream = _ == null ? (projection3 = null, identity_default3) : (projection3 = _).stream;\n return path2;\n };\n path2.context = function(_) {\n if (!arguments.length) return context;\n contextStream = _ == null ? (context = null, new PathString(digits)) : new PathContext(context = _);\n if (typeof pointRadius !== \"function\") contextStream.pointRadius(pointRadius);\n return path2;\n };\n path2.pointRadius = function(_) {\n if (!arguments.length) return pointRadius;\n pointRadius = typeof _ === \"function\" ? _ : (contextStream.pointRadius(+_), +_);\n return path2;\n };\n path2.digits = function(_) {\n if (!arguments.length) return digits;\n if (_ == null) digits = null;\n else {\n const d = Math.floor(_);\n if (!(d >= 0)) throw new RangeError(`invalid digits: ${_}`);\n digits = d;\n }\n if (context === null) contextStream = new PathString(digits);\n return path2;\n };\n return path2.projection(projection3).digits(digits).context(context);\n}\n\n// ../../node_modules/d3-geo/src/transform.js\nfunction transform_default(methods) {\n return {\n stream: transformer(methods)\n };\n}\nfunction transformer(methods) {\n return function(stream) {\n var s2 = new TransformStream();\n for (var key in methods) s2[key] = methods[key];\n s2.stream = stream;\n return s2;\n };\n}\nfunction TransformStream() {\n}\nTransformStream.prototype = {\n constructor: TransformStream,\n point: function(x3, y3) {\n this.stream.point(x3, y3);\n },\n sphere: function() {\n this.stream.sphere();\n },\n lineStart: function() {\n this.stream.lineStart();\n },\n lineEnd: function() {\n this.stream.lineEnd();\n },\n polygonStart: function() {\n this.stream.polygonStart();\n },\n polygonEnd: function() {\n this.stream.polygonEnd();\n }\n};\n\n// ../../node_modules/d3-geo/src/projection/fit.js\nfunction fit(projection3, fitBounds, object) {\n var clip = projection3.clipExtent && projection3.clipExtent();\n projection3.scale(150).translate([0, 0]);\n if (clip != null) projection3.clipExtent(null);\n stream_default(object, projection3.stream(bounds_default));\n fitBounds(bounds_default.result());\n if (clip != null) projection3.clipExtent(clip);\n return projection3;\n}\nfunction fitExtent(projection3, extent4, object) {\n return fit(projection3, function(b) {\n var w = extent4[1][0] - extent4[0][0], h = extent4[1][1] - extent4[0][1], k2 = Math.min(w / (b[1][0] - b[0][0]), h / (b[1][1] - b[0][1])), x3 = +extent4[0][0] + (w - k2 * (b[1][0] + b[0][0])) / 2, y3 = +extent4[0][1] + (h - k2 * (b[1][1] + b[0][1])) / 2;\n projection3.scale(150 * k2).translate([x3, y3]);\n }, object);\n}\nfunction fitSize(projection3, size, object) {\n return fitExtent(projection3, [[0, 0], size], object);\n}\nfunction fitWidth(projection3, width2, object) {\n return fit(projection3, function(b) {\n var w = +width2, k2 = w / (b[1][0] - b[0][0]), x3 = (w - k2 * (b[1][0] + b[0][0])) / 2, y3 = -k2 * b[0][1];\n projection3.scale(150 * k2).translate([x3, y3]);\n }, object);\n}\nfunction fitHeight(projection3, height2, object) {\n return fit(projection3, function(b) {\n var h = +height2, k2 = h / (b[1][1] - b[0][1]), x3 = -k2 * b[0][0], y3 = (h - k2 * (b[1][1] + b[0][1])) / 2;\n projection3.scale(150 * k2).translate([x3, y3]);\n }, object);\n}\n\n// ../../node_modules/d3-geo/src/projection/resample.js\nvar maxDepth = 16;\nvar cosMinDistance = cos(30 * radians2);\nfunction resample_default(project2, delta2) {\n return +delta2 ? resample(project2, delta2) : resampleNone(project2);\n}\nfunction resampleNone(project2) {\n return transformer({\n point: function(x3, y3) {\n x3 = project2(x3, y3);\n this.stream.point(x3[0], x3[1]);\n }\n });\n}\nfunction resample(project2, delta2) {\n function resampleLineTo(x06, y06, lambda0, a0, b0, c0, x12, y12, lambda1, a1, b1, c1, depth, stream) {\n var dx = x12 - x06, dy = y12 - y06, d2 = dx * dx + dy * dy;\n if (d2 > 4 * delta2 && depth--) {\n var a2 = a0 + a1, b = b0 + b1, c4 = c0 + c1, m = sqrt(a2 * a2 + b * b + c4 * c4), phi2 = asin(c4 /= m), lambda2 = abs2(abs2(c4) - 1) < epsilon6 || abs2(lambda0 - lambda1) < epsilon6 ? (lambda0 + lambda1) / 2 : atan2(b, a2), p = project2(lambda2, phi2), x22 = p[0], y22 = p[1], dx2 = x22 - x06, dy2 = y22 - y06, dz = dy * dx2 - dx * dy2;\n if (dz * dz / d2 > delta2 || abs2((dx * dx2 + dy * dy2) / d2 - 0.5) > 0.3 || a0 * a1 + b0 * b1 + c0 * c1 < cosMinDistance) {\n resampleLineTo(x06, y06, lambda0, a0, b0, c0, x22, y22, lambda2, a2 /= m, b /= m, c4, depth, stream);\n stream.point(x22, y22);\n resampleLineTo(x22, y22, lambda2, a2, b, c4, x12, y12, lambda1, a1, b1, c1, depth, stream);\n }\n }\n }\n return function(stream) {\n var lambda002, x004, y004, a00, b00, c00, lambda0, x06, y06, a0, b0, c0;\n var resampleStream = {\n point: point6,\n lineStart,\n lineEnd,\n polygonStart: function() {\n stream.polygonStart();\n resampleStream.lineStart = ringStart;\n },\n polygonEnd: function() {\n stream.polygonEnd();\n resampleStream.lineStart = lineStart;\n }\n };\n function point6(x3, y3) {\n x3 = project2(x3, y3);\n stream.point(x3[0], x3[1]);\n }\n function lineStart() {\n x06 = NaN;\n resampleStream.point = linePoint;\n stream.lineStart();\n }\n function linePoint(lambda, phi) {\n var c4 = cartesian([lambda, phi]), p = project2(lambda, phi);\n resampleLineTo(x06, y06, lambda0, a0, b0, c0, x06 = p[0], y06 = p[1], lambda0 = lambda, a0 = c4[0], b0 = c4[1], c0 = c4[2], maxDepth, stream);\n stream.point(x06, y06);\n }\n function lineEnd() {\n resampleStream.point = point6;\n stream.lineEnd();\n }\n function ringStart() {\n lineStart();\n resampleStream.point = ringPoint;\n resampleStream.lineEnd = ringEnd;\n }\n function ringPoint(lambda, phi) {\n linePoint(lambda002 = lambda, phi), x004 = x06, y004 = y06, a00 = a0, b00 = b0, c00 = c0;\n resampleStream.point = linePoint;\n }\n function ringEnd() {\n resampleLineTo(x06, y06, lambda0, a0, b0, c0, x004, y004, lambda002, a00, b00, c00, maxDepth, stream);\n resampleStream.lineEnd = lineEnd;\n lineEnd();\n }\n return resampleStream;\n };\n}\n\n// ../../node_modules/d3-geo/src/projection/index.js\nvar transformRadians = transformer({\n point: function(x3, y3) {\n this.stream.point(x3 * radians2, y3 * radians2);\n }\n});\nfunction transformRotate(rotate) {\n return transformer({\n point: function(x3, y3) {\n var r = rotate(x3, y3);\n return this.stream.point(r[0], r[1]);\n }\n });\n}\nfunction scaleTranslate(k2, dx, dy, sx, sy) {\n function transform3(x3, y3) {\n x3 *= sx;\n y3 *= sy;\n return [dx + k2 * x3, dy - k2 * y3];\n }\n transform3.invert = function(x3, y3) {\n return [(x3 - dx) / k2 * sx, (dy - y3) / k2 * sy];\n };\n return transform3;\n}\nfunction scaleTranslateRotate(k2, dx, dy, sx, sy, alpha) {\n if (!alpha) return scaleTranslate(k2, dx, dy, sx, sy);\n var cosAlpha = cos(alpha), sinAlpha = sin(alpha), a2 = cosAlpha * k2, b = sinAlpha * k2, ai = cosAlpha / k2, bi = sinAlpha / k2, ci = (sinAlpha * dy - cosAlpha * dx) / k2, fi = (sinAlpha * dx + cosAlpha * dy) / k2;\n function transform3(x3, y3) {\n x3 *= sx;\n y3 *= sy;\n return [a2 * x3 - b * y3 + dx, dy - b * x3 - a2 * y3];\n }\n transform3.invert = function(x3, y3) {\n return [sx * (ai * x3 - bi * y3 + ci), sy * (fi - bi * x3 - ai * y3)];\n };\n return transform3;\n}\nfunction projection(project2) {\n return projectionMutator(function() {\n return project2;\n })();\n}\nfunction projectionMutator(projectAt) {\n var project2, k2 = 150, x3 = 480, y3 = 250, lambda = 0, phi = 0, deltaLambda = 0, deltaPhi = 0, deltaGamma = 0, rotate, alpha = 0, sx = 1, sy = 1, theta = null, preclip = antimeridian_default, x06 = null, y06, x12, y12, postclip = identity_default3, delta2 = 0.5, projectResample, projectTransform, projectRotateTransform, cache, cacheStream;\n function projection3(point6) {\n return projectRotateTransform(point6[0] * radians2, point6[1] * radians2);\n }\n function invert2(point6) {\n point6 = projectRotateTransform.invert(point6[0], point6[1]);\n return point6 && [point6[0] * degrees3, point6[1] * degrees3];\n }\n projection3.stream = function(stream) {\n return cache && cacheStream === stream ? cache : cache = transformRadians(transformRotate(rotate)(preclip(projectResample(postclip(cacheStream = stream)))));\n };\n projection3.preclip = function(_) {\n return arguments.length ? (preclip = _, theta = void 0, reset()) : preclip;\n };\n projection3.postclip = function(_) {\n return arguments.length ? (postclip = _, x06 = y06 = x12 = y12 = null, reset()) : postclip;\n };\n projection3.clipAngle = function(_) {\n return arguments.length ? (preclip = +_ ? circle_default(theta = _ * radians2) : (theta = null, antimeridian_default), reset()) : theta * degrees3;\n };\n projection3.clipExtent = function(_) {\n return arguments.length ? (postclip = _ == null ? (x06 = y06 = x12 = y12 = null, identity_default3) : clipRectangle(x06 = +_[0][0], y06 = +_[0][1], x12 = +_[1][0], y12 = +_[1][1]), reset()) : x06 == null ? null : [[x06, y06], [x12, y12]];\n };\n projection3.scale = function(_) {\n return arguments.length ? (k2 = +_, recenter()) : k2;\n };\n projection3.translate = function(_) {\n return arguments.length ? (x3 = +_[0], y3 = +_[1], recenter()) : [x3, y3];\n };\n projection3.center = function(_) {\n return arguments.length ? (lambda = _[0] % 360 * radians2, phi = _[1] % 360 * radians2, recenter()) : [lambda * degrees3, phi * degrees3];\n };\n projection3.rotate = function(_) {\n return arguments.length ? (deltaLambda = _[0] % 360 * radians2, deltaPhi = _[1] % 360 * radians2, deltaGamma = _.length > 2 ? _[2] % 360 * radians2 : 0, recenter()) : [deltaLambda * degrees3, deltaPhi * degrees3, deltaGamma * degrees3];\n };\n projection3.angle = function(_) {\n return arguments.length ? (alpha = _ % 360 * radians2, recenter()) : alpha * degrees3;\n };\n projection3.reflectX = function(_) {\n return arguments.length ? (sx = _ ? -1 : 1, recenter()) : sx < 0;\n };\n projection3.reflectY = function(_) {\n return arguments.length ? (sy = _ ? -1 : 1, recenter()) : sy < 0;\n };\n projection3.precision = function(_) {\n return arguments.length ? (projectResample = resample_default(projectTransform, delta2 = _ * _), reset()) : sqrt(delta2);\n };\n projection3.fitExtent = function(extent4, object) {\n return fitExtent(projection3, extent4, object);\n };\n projection3.fitSize = function(size, object) {\n return fitSize(projection3, size, object);\n };\n projection3.fitWidth = function(width2, object) {\n return fitWidth(projection3, width2, object);\n };\n projection3.fitHeight = function(height2, object) {\n return fitHeight(projection3, height2, object);\n };\n function recenter() {\n var center2 = scaleTranslateRotate(k2, 0, 0, sx, sy, alpha).apply(null, project2(lambda, phi)), transform3 = scaleTranslateRotate(k2, x3 - center2[0], y3 - center2[1], sx, sy, alpha);\n rotate = rotateRadians(deltaLambda, deltaPhi, deltaGamma);\n projectTransform = compose_default(project2, transform3);\n projectRotateTransform = compose_default(rotate, projectTransform);\n projectResample = resample_default(projectTransform, delta2);\n return reset();\n }\n function reset() {\n cache = cacheStream = null;\n return projection3;\n }\n return function() {\n project2 = projectAt.apply(this, arguments);\n projection3.invert = project2.invert && invert2;\n return recenter();\n };\n}\n\n// ../../node_modules/d3-geo/src/projection/conic.js\nfunction conicProjection(projectAt) {\n var phi0 = 0, phi1 = pi2 / 3, m = projectionMutator(projectAt), p = m(phi0, phi1);\n p.parallels = function(_) {\n return arguments.length ? m(phi0 = _[0] * radians2, phi1 = _[1] * radians2) : [phi0 * degrees3, phi1 * degrees3];\n };\n return p;\n}\n\n// ../../node_modules/d3-geo/src/projection/cylindricalEqualArea.js\nfunction cylindricalEqualAreaRaw(phi0) {\n var cosPhi0 = cos(phi0);\n function forward(lambda, phi) {\n return [lambda * cosPhi0, sin(phi) / cosPhi0];\n }\n forward.invert = function(x3, y3) {\n return [x3 / cosPhi0, asin(y3 * cosPhi0)];\n };\n return forward;\n}\n\n// ../../node_modules/d3-geo/src/projection/conicEqualArea.js\nfunction conicEqualAreaRaw(y06, y12) {\n var sy0 = sin(y06), n = (sy0 + sin(y12)) / 2;\n if (abs2(n) < epsilon6) return cylindricalEqualAreaRaw(y06);\n var c4 = 1 + sy0 * (2 * n - sy0), r0 = sqrt(c4) / n;\n function project2(x3, y3) {\n var r = sqrt(c4 - 2 * n * sin(y3)) / n;\n return [r * sin(x3 *= n), r0 - r * cos(x3)];\n }\n project2.invert = function(x3, y3) {\n var r0y = r0 - y3, l = atan2(x3, abs2(r0y)) * sign(r0y);\n if (r0y * n < 0)\n l -= pi2 * sign(x3) * sign(r0y);\n return [l / n, asin((c4 - (x3 * x3 + r0y * r0y) * n * n) / (2 * n))];\n };\n return project2;\n}\nfunction conicEqualArea_default() {\n return conicProjection(conicEqualAreaRaw).scale(155.424).center([0, 33.6442]);\n}\n\n// ../../node_modules/d3-geo/src/projection/albers.js\nfunction albers_default() {\n return conicEqualArea_default().parallels([29.5, 45.5]).scale(1070).translate([480, 250]).rotate([96, 0]).center([-0.6, 38.7]);\n}\n\n// ../../node_modules/d3-geo/src/projection/albersUsa.js\nfunction multiplex(streams) {\n var n = streams.length;\n return {\n point: function(x3, y3) {\n var i = -1;\n while (++i < n) streams[i].point(x3, y3);\n },\n sphere: function() {\n var i = -1;\n while (++i < n) streams[i].sphere();\n },\n lineStart: function() {\n var i = -1;\n while (++i < n) streams[i].lineStart();\n },\n lineEnd: function() {\n var i = -1;\n while (++i < n) streams[i].lineEnd();\n },\n polygonStart: function() {\n var i = -1;\n while (++i < n) streams[i].polygonStart();\n },\n polygonEnd: function() {\n var i = -1;\n while (++i < n) streams[i].polygonEnd();\n }\n };\n}\nfunction albersUsa_default() {\n var cache, cacheStream, lower48 = albers_default(), lower48Point, alaska = conicEqualArea_default().rotate([154, 0]).center([-2, 58.5]).parallels([55, 65]), alaskaPoint, hawaii = conicEqualArea_default().rotate([157, 0]).center([-3, 19.9]).parallels([8, 18]), hawaiiPoint, point6, pointStream = { point: function(x3, y3) {\n point6 = [x3, y3];\n } };\n function albersUsa(coordinates) {\n var x3 = coordinates[0], y3 = coordinates[1];\n return point6 = null, (lower48Point.point(x3, y3), point6) || (alaskaPoint.point(x3, y3), point6) || (hawaiiPoint.point(x3, y3), point6);\n }\n albersUsa.invert = function(coordinates) {\n var k2 = lower48.scale(), t = lower48.translate(), x3 = (coordinates[0] - t[0]) / k2, y3 = (coordinates[1] - t[1]) / k2;\n return (y3 >= 0.12 && y3 < 0.234 && x3 >= -0.425 && x3 < -0.214 ? alaska : y3 >= 0.166 && y3 < 0.234 && x3 >= -0.214 && x3 < -0.115 ? hawaii : lower48).invert(coordinates);\n };\n albersUsa.stream = function(stream) {\n return cache && cacheStream === stream ? cache : cache = multiplex([lower48.stream(cacheStream = stream), alaska.stream(stream), hawaii.stream(stream)]);\n };\n albersUsa.precision = function(_) {\n if (!arguments.length) return lower48.precision();\n lower48.precision(_), alaska.precision(_), hawaii.precision(_);\n return reset();\n };\n albersUsa.scale = function(_) {\n if (!arguments.length) return lower48.scale();\n lower48.scale(_), alaska.scale(_ * 0.35), hawaii.scale(_);\n return albersUsa.translate(lower48.translate());\n };\n albersUsa.translate = function(_) {\n if (!arguments.length) return lower48.translate();\n var k2 = lower48.scale(), x3 = +_[0], y3 = +_[1];\n lower48Point = lower48.translate(_).clipExtent([[x3 - 0.455 * k2, y3 - 0.238 * k2], [x3 + 0.455 * k2, y3 + 0.238 * k2]]).stream(pointStream);\n alaskaPoint = alaska.translate([x3 - 0.307 * k2, y3 + 0.201 * k2]).clipExtent([[x3 - 0.425 * k2 + epsilon6, y3 + 0.12 * k2 + epsilon6], [x3 - 0.214 * k2 - epsilon6, y3 + 0.234 * k2 - epsilon6]]).stream(pointStream);\n hawaiiPoint = hawaii.translate([x3 - 0.205 * k2, y3 + 0.212 * k2]).clipExtent([[x3 - 0.214 * k2 + epsilon6, y3 + 0.166 * k2 + epsilon6], [x3 - 0.115 * k2 - epsilon6, y3 + 0.234 * k2 - epsilon6]]).stream(pointStream);\n return reset();\n };\n albersUsa.fitExtent = function(extent4, object) {\n return fitExtent(albersUsa, extent4, object);\n };\n albersUsa.fitSize = function(size, object) {\n return fitSize(albersUsa, size, object);\n };\n albersUsa.fitWidth = function(width2, object) {\n return fitWidth(albersUsa, width2, object);\n };\n albersUsa.fitHeight = function(height2, object) {\n return fitHeight(albersUsa, height2, object);\n };\n function reset() {\n cache = cacheStream = null;\n return albersUsa;\n }\n return albersUsa.scale(1070);\n}\n\n// ../../node_modules/d3-geo/src/projection/azimuthal.js\nfunction azimuthalRaw(scale3) {\n return function(x3, y3) {\n var cx = cos(x3), cy = cos(y3), k2 = scale3(cx * cy);\n if (k2 === Infinity) return [2, 0];\n return [\n k2 * cy * sin(x3),\n k2 * sin(y3)\n ];\n };\n}\nfunction azimuthalInvert(angle) {\n return function(x3, y3) {\n var z = sqrt(x3 * x3 + y3 * y3), c4 = angle(z), sc = sin(c4), cc2 = cos(c4);\n return [\n atan2(x3 * sc, z * cc2),\n asin(z && y3 * sc / z)\n ];\n };\n}\n\n// ../../node_modules/d3-geo/src/projection/azimuthalEqualArea.js\nvar azimuthalEqualAreaRaw = azimuthalRaw(function(cxcy) {\n return sqrt(2 / (1 + cxcy));\n});\nazimuthalEqualAreaRaw.invert = azimuthalInvert(function(z) {\n return 2 * asin(z / 2);\n});\nfunction azimuthalEqualArea_default() {\n return projection(azimuthalEqualAreaRaw).scale(124.75).clipAngle(180 - 1e-3);\n}\n\n// ../../node_modules/d3-geo/src/projection/azimuthalEquidistant.js\nvar azimuthalEquidistantRaw = azimuthalRaw(function(c4) {\n return (c4 = acos(c4)) && c4 / sin(c4);\n});\nazimuthalEquidistantRaw.invert = azimuthalInvert(function(z) {\n return z;\n});\nfunction azimuthalEquidistant_default() {\n return projection(azimuthalEquidistantRaw).scale(79.4188).clipAngle(180 - 1e-3);\n}\n\n// ../../node_modules/d3-geo/src/projection/mercator.js\nfunction mercatorRaw(lambda, phi) {\n return [lambda, log(tan((halfPi + phi) / 2))];\n}\nmercatorRaw.invert = function(x3, y3) {\n return [x3, 2 * atan(exp(y3)) - halfPi];\n};\nfunction mercator_default() {\n return mercatorProjection(mercatorRaw).scale(961 / tau3);\n}\nfunction mercatorProjection(project2) {\n var m = projection(project2), center2 = m.center, scale3 = m.scale, translate = m.translate, clipExtent = m.clipExtent, x06 = null, y06, x12, y12;\n m.scale = function(_) {\n return arguments.length ? (scale3(_), reclip()) : scale3();\n };\n m.translate = function(_) {\n return arguments.length ? (translate(_), reclip()) : translate();\n };\n m.center = function(_) {\n return arguments.length ? (center2(_), reclip()) : center2();\n };\n m.clipExtent = function(_) {\n return arguments.length ? (_ == null ? x06 = y06 = x12 = y12 = null : (x06 = +_[0][0], y06 = +_[0][1], x12 = +_[1][0], y12 = +_[1][1]), reclip()) : x06 == null ? null : [[x06, y06], [x12, y12]];\n };\n function reclip() {\n var k2 = pi2 * scale3(), t = m(rotation_default(m.rotate()).invert([0, 0]));\n return clipExtent(x06 == null ? [[t[0] - k2, t[1] - k2], [t[0] + k2, t[1] + k2]] : project2 === mercatorRaw ? [[Math.max(t[0] - k2, x06), y06], [Math.min(t[0] + k2, x12), y12]] : [[x06, Math.max(t[1] - k2, y06)], [x12, Math.min(t[1] + k2, y12)]]);\n }\n return reclip();\n}\n\n// ../../node_modules/d3-geo/src/projection/conicConformal.js\nfunction tany(y3) {\n return tan((halfPi + y3) / 2);\n}\nfunction conicConformalRaw(y06, y12) {\n var cy0 = cos(y06), n = y06 === y12 ? sin(y06) : log(cy0 / cos(y12)) / log(tany(y12) / tany(y06)), f = cy0 * pow2(tany(y06), n) / n;\n if (!n) return mercatorRaw;\n function project2(x3, y3) {\n if (f > 0) {\n if (y3 < -halfPi + epsilon6) y3 = -halfPi + epsilon6;\n } else {\n if (y3 > halfPi - epsilon6) y3 = halfPi - epsilon6;\n }\n var r = f / pow2(tany(y3), n);\n return [r * sin(n * x3), f - r * cos(n * x3)];\n }\n project2.invert = function(x3, y3) {\n var fy = f - y3, r = sign(n) * sqrt(x3 * x3 + fy * fy), l = atan2(x3, abs2(fy)) * sign(fy);\n if (fy * n < 0)\n l -= pi2 * sign(x3) * sign(fy);\n return [l / n, 2 * atan(pow2(f / r, 1 / n)) - halfPi];\n };\n return project2;\n}\nfunction conicConformal_default() {\n return conicProjection(conicConformalRaw).scale(109.5).parallels([30, 30]);\n}\n\n// ../../node_modules/d3-geo/src/projection/equirectangular.js\nfunction equirectangularRaw(lambda, phi) {\n return [lambda, phi];\n}\nequirectangularRaw.invert = equirectangularRaw;\nfunction equirectangular_default() {\n return projection(equirectangularRaw).scale(152.63);\n}\n\n// ../../node_modules/d3-geo/src/projection/conicEquidistant.js\nfunction conicEquidistantRaw(y06, y12) {\n var cy0 = cos(y06), n = y06 === y12 ? sin(y06) : (cy0 - cos(y12)) / (y12 - y06), g = cy0 / n + y06;\n if (abs2(n) < epsilon6) return equirectangularRaw;\n function project2(x3, y3) {\n var gy = g - y3, nx = n * x3;\n return [gy * sin(nx), g - gy * cos(nx)];\n }\n project2.invert = function(x3, y3) {\n var gy = g - y3, l = atan2(x3, abs2(gy)) * sign(gy);\n if (gy * n < 0)\n l -= pi2 * sign(x3) * sign(gy);\n return [l / n, g - sign(n) * sqrt(x3 * x3 + gy * gy)];\n };\n return project2;\n}\nfunction conicEquidistant_default() {\n return conicProjection(conicEquidistantRaw).scale(131.154).center([0, 13.9389]);\n}\n\n// ../../node_modules/d3-geo/src/projection/equalEarth.js\nvar A1 = 1.340264;\nvar A2 = -0.081106;\nvar A3 = 893e-6;\nvar A4 = 3796e-6;\nvar M = sqrt(3) / 2;\nvar iterations = 12;\nfunction equalEarthRaw(lambda, phi) {\n var l = asin(M * sin(phi)), l2 = l * l, l6 = l2 * l2 * l2;\n return [\n lambda * cos(l) / (M * (A1 + 3 * A2 * l2 + l6 * (7 * A3 + 9 * A4 * l2))),\n l * (A1 + A2 * l2 + l6 * (A3 + A4 * l2))\n ];\n}\nequalEarthRaw.invert = function(x3, y3) {\n var l = y3, l2 = l * l, l6 = l2 * l2 * l2;\n for (var i = 0, delta, fy, fpy; i < iterations; ++i) {\n fy = l * (A1 + A2 * l2 + l6 * (A3 + A4 * l2)) - y3;\n fpy = A1 + 3 * A2 * l2 + l6 * (7 * A3 + 9 * A4 * l2);\n l -= delta = fy / fpy, l2 = l * l, l6 = l2 * l2 * l2;\n if (abs2(delta) < epsilon22) break;\n }\n return [\n M * x3 * (A1 + 3 * A2 * l2 + l6 * (7 * A3 + 9 * A4 * l2)) / cos(l),\n asin(sin(l) / M)\n ];\n};\nfunction equalEarth_default() {\n return projection(equalEarthRaw).scale(177.158);\n}\n\n// ../../node_modules/d3-geo/src/projection/gnomonic.js\nfunction gnomonicRaw(x3, y3) {\n var cy = cos(y3), k2 = cos(x3) * cy;\n return [cy * sin(x3) / k2, sin(y3) / k2];\n}\ngnomonicRaw.invert = azimuthalInvert(atan);\nfunction gnomonic_default() {\n return projection(gnomonicRaw).scale(144.049).clipAngle(60);\n}\n\n// ../../node_modules/d3-geo/src/projection/orthographic.js\nfunction orthographicRaw(x3, y3) {\n return [cos(y3) * sin(x3), sin(y3)];\n}\northographicRaw.invert = azimuthalInvert(asin);\nfunction orthographic_default() {\n return projection(orthographicRaw).scale(249.5).clipAngle(90 + epsilon6);\n}\n\n// ../../node_modules/d3-geo/src/projection/stereographic.js\nfunction stereographicRaw(x3, y3) {\n var cy = cos(y3), k2 = 1 + cos(x3) * cy;\n return [cy * sin(x3) / k2, sin(y3) / k2];\n}\nstereographicRaw.invert = azimuthalInvert(function(z) {\n return 2 * atan(z);\n});\nfunction stereographic_default() {\n return projection(stereographicRaw).scale(250).clipAngle(142);\n}\n\n// ../../node_modules/d3-geo/src/projection/transverseMercator.js\nfunction transverseMercatorRaw(lambda, phi) {\n return [log(tan((halfPi + phi) / 2)), -lambda];\n}\ntransverseMercatorRaw.invert = function(x3, y3) {\n return [-y3, 2 * atan(exp(x3)) - halfPi];\n};\nfunction transverseMercator_default() {\n var m = mercatorProjection(transverseMercatorRaw), center2 = m.center, rotate = m.rotate;\n m.center = function(_) {\n return arguments.length ? center2([-_[1], _[0]]) : (_ = center2(), [_[1], -_[0]]);\n };\n m.rotate = function(_) {\n return arguments.length ? rotate([_[0], _[1], _.length > 2 ? _[2] + 90 : 90]) : (_ = rotate(), [_[0], _[1], _[2] - 90]);\n };\n return rotate([0, 0, 90]).scale(159.155);\n}\n\n// ../../node_modules/d3-hierarchy/src/cluster.js\nfunction defaultSeparation(a2, b) {\n return a2.parent === b.parent ? 1 : 2;\n}\nfunction meanX(children2) {\n return children2.reduce(meanXReduce, 0) / children2.length;\n}\nfunction meanXReduce(x3, c4) {\n return x3 + c4.x;\n}\nfunction maxY(children2) {\n return 1 + children2.reduce(maxYReduce, 0);\n}\nfunction maxYReduce(y3, c4) {\n return Math.max(y3, c4.y);\n}\nfunction leafLeft(node) {\n var children2;\n while (children2 = node.children) node = children2[0];\n return node;\n}\nfunction leafRight(node) {\n var children2;\n while (children2 = node.children) node = children2[children2.length - 1];\n return node;\n}\nfunction cluster_default() {\n var separation = defaultSeparation, dx = 1, dy = 1, nodeSize = false;\n function cluster2(root2) {\n var previousNode, x3 = 0;\n root2.eachAfter(function(node) {\n var children2 = node.children;\n if (children2) {\n node.x = meanX(children2);\n node.y = maxY(children2);\n } else {\n node.x = previousNode ? x3 += separation(node, previousNode) : 0;\n node.y = 0;\n previousNode = node;\n }\n });\n var left2 = leafLeft(root2), right2 = leafRight(root2), x06 = left2.x - separation(left2, right2) / 2, x12 = right2.x + separation(right2, left2) / 2;\n return root2.eachAfter(nodeSize ? function(node) {\n node.x = (node.x - root2.x) * dx;\n node.y = (root2.y - node.y) * dy;\n } : function(node) {\n node.x = (node.x - x06) / (x12 - x06) * dx;\n node.y = (1 - (root2.y ? node.y / root2.y : 1)) * dy;\n });\n }\n cluster2.separation = function(x3) {\n return arguments.length ? (separation = x3, cluster2) : separation;\n };\n cluster2.size = function(x3) {\n return arguments.length ? (nodeSize = false, dx = +x3[0], dy = +x3[1], cluster2) : nodeSize ? null : [dx, dy];\n };\n cluster2.nodeSize = function(x3) {\n return arguments.length ? (nodeSize = true, dx = +x3[0], dy = +x3[1], cluster2) : nodeSize ? [dx, dy] : null;\n };\n return cluster2;\n}\n\n// ../../node_modules/d3-hierarchy/src/hierarchy/count.js\nfunction count3(node) {\n var sum4 = 0, children2 = node.children, i = children2 && children2.length;\n if (!i) sum4 = 1;\n else while (--i >= 0) sum4 += children2[i].value;\n node.value = sum4;\n}\nfunction count_default() {\n return this.eachAfter(count3);\n}\n\n// ../../node_modules/d3-hierarchy/src/hierarchy/each.js\nfunction each_default2(callback, that) {\n let index2 = -1;\n for (const node of this) {\n callback.call(that, node, ++index2, this);\n }\n return this;\n}\n\n// ../../node_modules/d3-hierarchy/src/hierarchy/eachBefore.js\nfunction eachBefore_default(callback, that) {\n var node = this, nodes = [node], children2, i, index2 = -1;\n while (node = nodes.pop()) {\n callback.call(that, node, ++index2, this);\n if (children2 = node.children) {\n for (i = children2.length - 1; i >= 0; --i) {\n nodes.push(children2[i]);\n }\n }\n }\n return this;\n}\n\n// ../../node_modules/d3-hierarchy/src/hierarchy/eachAfter.js\nfunction eachAfter_default(callback, that) {\n var node = this, nodes = [node], next = [], children2, i, n, index2 = -1;\n while (node = nodes.pop()) {\n next.push(node);\n if (children2 = node.children) {\n for (i = 0, n = children2.length; i < n; ++i) {\n nodes.push(children2[i]);\n }\n }\n }\n while (node = next.pop()) {\n callback.call(that, node, ++index2, this);\n }\n return this;\n}\n\n// ../../node_modules/d3-hierarchy/src/hierarchy/find.js\nfunction find_default(callback, that) {\n let index2 = -1;\n for (const node of this) {\n if (callback.call(that, node, ++index2, this)) {\n return node;\n }\n }\n}\n\n// ../../node_modules/d3-hierarchy/src/hierarchy/sum.js\nfunction sum_default(value) {\n return this.eachAfter(function(node) {\n var sum4 = +value(node.data) || 0, children2 = node.children, i = children2 && children2.length;\n while (--i >= 0) sum4 += children2[i].value;\n node.value = sum4;\n });\n}\n\n// ../../node_modules/d3-hierarchy/src/hierarchy/sort.js\nfunction sort_default2(compare) {\n return this.eachBefore(function(node) {\n if (node.children) {\n node.children.sort(compare);\n }\n });\n}\n\n// ../../node_modules/d3-hierarchy/src/hierarchy/path.js\nfunction path_default2(end) {\n var start2 = this, ancestor = leastCommonAncestor(start2, end), nodes = [start2];\n while (start2 !== ancestor) {\n start2 = start2.parent;\n nodes.push(start2);\n }\n var k2 = nodes.length;\n while (end !== ancestor) {\n nodes.splice(k2, 0, end);\n end = end.parent;\n }\n return nodes;\n}\nfunction leastCommonAncestor(a2, b) {\n if (a2 === b) return a2;\n var aNodes = a2.ancestors(), bNodes = b.ancestors(), c4 = null;\n a2 = aNodes.pop();\n b = bNodes.pop();\n while (a2 === b) {\n c4 = a2;\n a2 = aNodes.pop();\n b = bNodes.pop();\n }\n return c4;\n}\n\n// ../../node_modules/d3-hierarchy/src/hierarchy/ancestors.js\nfunction ancestors_default() {\n var node = this, nodes = [node];\n while (node = node.parent) {\n nodes.push(node);\n }\n return nodes;\n}\n\n// ../../node_modules/d3-hierarchy/src/hierarchy/descendants.js\nfunction descendants_default() {\n return Array.from(this);\n}\n\n// ../../node_modules/d3-hierarchy/src/hierarchy/leaves.js\nfunction leaves_default() {\n var leaves = [];\n this.eachBefore(function(node) {\n if (!node.children) {\n leaves.push(node);\n }\n });\n return leaves;\n}\n\n// ../../node_modules/d3-hierarchy/src/hierarchy/links.js\nfunction links_default() {\n var root2 = this, links = [];\n root2.each(function(node) {\n if (node !== root2) {\n links.push({ source: node.parent, target: node });\n }\n });\n return links;\n}\n\n// ../../node_modules/d3-hierarchy/src/hierarchy/iterator.js\nfunction* iterator_default2() {\n var node = this, current, next = [node], children2, i, n;\n do {\n current = next.reverse(), next = [];\n while (node = current.pop()) {\n yield node;\n if (children2 = node.children) {\n for (i = 0, n = children2.length; i < n; ++i) {\n next.push(children2[i]);\n }\n }\n }\n } while (next.length);\n}\n\n// ../../node_modules/d3-hierarchy/src/hierarchy/index.js\nfunction hierarchy(data, children2) {\n if (data instanceof Map) {\n data = [void 0, data];\n if (children2 === void 0) children2 = mapChildren;\n } else if (children2 === void 0) {\n children2 = objectChildren;\n }\n var root2 = new Node(data), node, nodes = [root2], child, childs, i, n;\n while (node = nodes.pop()) {\n if ((childs = children2(node.data)) && (n = (childs = Array.from(childs)).length)) {\n node.children = childs;\n for (i = n - 1; i >= 0; --i) {\n nodes.push(child = childs[i] = new Node(childs[i]));\n child.parent = node;\n child.depth = node.depth + 1;\n }\n }\n }\n return root2.eachBefore(computeHeight);\n}\nfunction node_copy() {\n return hierarchy(this).eachBefore(copyData);\n}\nfunction objectChildren(d) {\n return d.children;\n}\nfunction mapChildren(d) {\n return Array.isArray(d) ? d[1] : null;\n}\nfunction copyData(node) {\n if (node.data.value !== void 0) node.value = node.data.value;\n node.data = node.data.data;\n}\nfunction computeHeight(node) {\n var height2 = 0;\n do\n node.height = height2;\n while ((node = node.parent) && node.height < ++height2);\n}\nfunction Node(data) {\n this.data = data;\n this.depth = this.height = 0;\n this.parent = null;\n}\nNode.prototype = hierarchy.prototype = {\n constructor: Node,\n count: count_default,\n each: each_default2,\n eachAfter: eachAfter_default,\n eachBefore: eachBefore_default,\n find: find_default,\n sum: sum_default,\n sort: sort_default2,\n path: path_default2,\n ancestors: ancestors_default,\n descendants: descendants_default,\n leaves: leaves_default,\n links: links_default,\n copy: node_copy,\n [Symbol.iterator]: iterator_default2\n};\n\n// ../../node_modules/d3-hierarchy/src/accessors.js\nfunction optional(f) {\n return f == null ? null : required(f);\n}\nfunction required(f) {\n if (typeof f !== \"function\") throw new Error();\n return f;\n}\n\n// ../../node_modules/d3-hierarchy/src/stratify.js\nvar preroot = { depth: -1 };\nvar ambiguous = {};\nvar imputed = {};\nfunction defaultId(d) {\n return d.id;\n}\nfunction defaultParentId(d) {\n return d.parentId;\n}\nfunction stratify_default() {\n var id2 = defaultId, parentId = defaultParentId, path2;\n function stratify(data) {\n var nodes = Array.from(data), currentId = id2, currentParentId = parentId, n, d, i, root2, parent, node, nodeId, nodeKey, nodeByKey = /* @__PURE__ */ new Map();\n if (path2 != null) {\n const I = nodes.map((d2, i2) => normalize(path2(d2, i2, data)));\n const P = I.map(parentof);\n const S = new Set(I).add(\"\");\n for (const i2 of P) {\n if (!S.has(i2)) {\n S.add(i2);\n I.push(i2);\n P.push(parentof(i2));\n nodes.push(imputed);\n }\n }\n currentId = (_, i2) => I[i2];\n currentParentId = (_, i2) => P[i2];\n }\n for (i = 0, n = nodes.length; i < n; ++i) {\n d = nodes[i], node = nodes[i] = new Node(d);\n if ((nodeId = currentId(d, i, data)) != null && (nodeId += \"\")) {\n nodeKey = node.id = nodeId;\n nodeByKey.set(nodeKey, nodeByKey.has(nodeKey) ? ambiguous : node);\n }\n if ((nodeId = currentParentId(d, i, data)) != null && (nodeId += \"\")) {\n node.parent = nodeId;\n }\n }\n for (i = 0; i < n; ++i) {\n node = nodes[i];\n if (nodeId = node.parent) {\n parent = nodeByKey.get(nodeId);\n if (!parent) throw new Error(\"missing: \" + nodeId);\n if (parent === ambiguous) throw new Error(\"ambiguous: \" + nodeId);\n if (parent.children) parent.children.push(node);\n else parent.children = [node];\n node.parent = parent;\n } else {\n if (root2) throw new Error(\"multiple roots\");\n root2 = node;\n }\n }\n if (!root2) throw new Error(\"no root\");\n if (path2 != null) {\n while (root2.data === imputed && root2.children.length === 1) {\n root2 = root2.children[0], --n;\n }\n for (let i2 = nodes.length - 1; i2 >= 0; --i2) {\n node = nodes[i2];\n if (node.data !== imputed) break;\n node.data = null;\n }\n }\n root2.parent = preroot;\n root2.eachBefore(function(node2) {\n node2.depth = node2.parent.depth + 1;\n --n;\n }).eachBefore(computeHeight);\n root2.parent = null;\n if (n > 0) throw new Error(\"cycle\");\n return root2;\n }\n stratify.id = function(x3) {\n return arguments.length ? (id2 = optional(x3), stratify) : id2;\n };\n stratify.parentId = function(x3) {\n return arguments.length ? (parentId = optional(x3), stratify) : parentId;\n };\n stratify.path = function(x3) {\n return arguments.length ? (path2 = optional(x3), stratify) : path2;\n };\n return stratify;\n}\nfunction normalize(path2) {\n path2 = `${path2}`;\n let i = path2.length;\n if (slash(path2, i - 1) && !slash(path2, i - 2)) path2 = path2.slice(0, -1);\n return path2[0] === \"/\" ? path2 : `/${path2}`;\n}\nfunction parentof(path2) {\n let i = path2.length;\n if (i < 2) return \"\";\n while (--i > 1) if (slash(path2, i)) break;\n return path2.slice(0, i);\n}\nfunction slash(path2, i) {\n if (path2[i] === \"/\") {\n let k2 = 0;\n while (i > 0 && path2[--i] === \"\\\\\") ++k2;\n if ((k2 & 1) === 0) return true;\n }\n return false;\n}\n\n// ../../node_modules/d3-hierarchy/src/tree.js\nfunction defaultSeparation2(a2, b) {\n return a2.parent === b.parent ? 1 : 2;\n}\nfunction nextLeft(v2) {\n var children2 = v2.children;\n return children2 ? children2[0] : v2.t;\n}\nfunction nextRight(v2) {\n var children2 = v2.children;\n return children2 ? children2[children2.length - 1] : v2.t;\n}\nfunction moveSubtree(wm, wp, shift) {\n var change = shift / (wp.i - wm.i);\n wp.c -= change;\n wp.s += shift;\n wm.c += change;\n wp.z += shift;\n wp.m += shift;\n}\nfunction executeShifts(v2) {\n var shift = 0, change = 0, children2 = v2.children, i = children2.length, w;\n while (--i >= 0) {\n w = children2[i];\n w.z += shift;\n w.m += shift;\n shift += w.s + (change += w.c);\n }\n}\nfunction nextAncestor(vim, v2, ancestor) {\n return vim.a.parent === v2.parent ? vim.a : ancestor;\n}\nfunction TreeNode(node, i) {\n this._ = node;\n this.parent = null;\n this.children = null;\n this.A = null;\n this.a = this;\n this.z = 0;\n this.m = 0;\n this.c = 0;\n this.s = 0;\n this.t = null;\n this.i = i;\n}\nTreeNode.prototype = Object.create(Node.prototype);\nfunction treeRoot(root2) {\n var tree2 = new TreeNode(root2, 0), node, nodes = [tree2], child, children2, i, n;\n while (node = nodes.pop()) {\n if (children2 = node._.children) {\n node.children = new Array(n = children2.length);\n for (i = n - 1; i >= 0; --i) {\n nodes.push(child = node.children[i] = new TreeNode(children2[i], i));\n child.parent = node;\n }\n }\n }\n (tree2.parent = new TreeNode(null, 0)).children = [tree2];\n return tree2;\n}\nfunction tree_default() {\n var separation = defaultSeparation2, dx = 1, dy = 1, nodeSize = null;\n function tree2(root2) {\n var t = treeRoot(root2);\n t.eachAfter(firstWalk), t.parent.m = -t.z;\n t.eachBefore(secondWalk);\n if (nodeSize) root2.eachBefore(sizeNode);\n else {\n var left2 = root2, right2 = root2, bottom2 = root2;\n root2.eachBefore(function(node) {\n if (node.x < left2.x) left2 = node;\n if (node.x > right2.x) right2 = node;\n if (node.depth > bottom2.depth) bottom2 = node;\n });\n var s2 = left2 === right2 ? 1 : separation(left2, right2) / 2, tx = s2 - left2.x, kx2 = dx / (right2.x + s2 + tx), ky2 = dy / (bottom2.depth || 1);\n root2.eachBefore(function(node) {\n node.x = (node.x + tx) * kx2;\n node.y = node.depth * ky2;\n });\n }\n return root2;\n }\n function firstWalk(v2) {\n var children2 = v2.children, siblings = v2.parent.children, w = v2.i ? siblings[v2.i - 1] : null;\n if (children2) {\n executeShifts(v2);\n var midpoint = (children2[0].z + children2[children2.length - 1].z) / 2;\n if (w) {\n v2.z = w.z + separation(v2._, w._);\n v2.m = v2.z - midpoint;\n } else {\n v2.z = midpoint;\n }\n } else if (w) {\n v2.z = w.z + separation(v2._, w._);\n }\n v2.parent.A = apportion(v2, w, v2.parent.A || siblings[0]);\n }\n function secondWalk(v2) {\n v2._.x = v2.z + v2.parent.m;\n v2.m += v2.parent.m;\n }\n function apportion(v2, w, ancestor) {\n if (w) {\n var vip = v2, vop = v2, vim = w, vom = vip.parent.children[0], sip = vip.m, sop = vop.m, sim = vim.m, som = vom.m, shift;\n while (vim = nextRight(vim), vip = nextLeft(vip), vim && vip) {\n vom = nextLeft(vom);\n vop = nextRight(vop);\n vop.a = v2;\n shift = vim.z + sim - vip.z - sip + separation(vim._, vip._);\n if (shift > 0) {\n moveSubtree(nextAncestor(vim, v2, ancestor), v2, shift);\n sip += shift;\n sop += shift;\n }\n sim += vim.m;\n sip += vip.m;\n som += vom.m;\n sop += vop.m;\n }\n if (vim && !nextRight(vop)) {\n vop.t = vim;\n vop.m += sim - sop;\n }\n if (vip && !nextLeft(vom)) {\n vom.t = vip;\n vom.m += sip - som;\n ancestor = v2;\n }\n }\n return ancestor;\n }\n function sizeNode(node) {\n node.x *= dx;\n node.y = node.depth * dy;\n }\n tree2.separation = function(x3) {\n return arguments.length ? (separation = x3, tree2) : separation;\n };\n tree2.size = function(x3) {\n return arguments.length ? (nodeSize = false, dx = +x3[0], dy = +x3[1], tree2) : nodeSize ? null : [dx, dy];\n };\n tree2.nodeSize = function(x3) {\n return arguments.length ? (nodeSize = true, dx = +x3[0], dy = +x3[1], tree2) : nodeSize ? [dx, dy] : null;\n };\n return tree2;\n}\n\n// ../../node_modules/d3-random/src/lcg.js\nvar mul = 1664525;\nvar inc = 1013904223;\nvar eps = 1 / 4294967296;\nfunction lcg(seed = Math.random()) {\n let state = (0 <= seed && seed < 1 ? seed / eps : Math.abs(seed)) | 0;\n return () => (state = mul * state + inc | 0, eps * (state >>> 0));\n}\n\n// ../../node_modules/d3-scale/src/init.js\nfunction initRange(domain, range3) {\n switch (arguments.length) {\n case 0:\n break;\n case 1:\n this.range(domain);\n break;\n default:\n this.range(range3).domain(domain);\n break;\n }\n return this;\n}\nfunction initInterpolator(domain, interpolator) {\n switch (arguments.length) {\n case 0:\n break;\n case 1: {\n if (typeof domain === \"function\") this.interpolator(domain);\n else this.range(domain);\n break;\n }\n default: {\n this.domain(domain);\n if (typeof interpolator === \"function\") this.interpolator(interpolator);\n else this.range(interpolator);\n break;\n }\n }\n return this;\n}\n\n// ../../node_modules/d3-scale/src/ordinal.js\nvar implicit = Symbol(\"implicit\");\nfunction ordinal() {\n var index2 = new InternMap(), domain = [], range3 = [], unknown = implicit;\n function scale3(d) {\n let i = index2.get(d);\n if (i === void 0) {\n if (unknown !== implicit) return unknown;\n index2.set(d, i = domain.push(d) - 1);\n }\n return range3[i % range3.length];\n }\n scale3.domain = function(_) {\n if (!arguments.length) return domain.slice();\n domain = [], index2 = new InternMap();\n for (const value of _) {\n if (index2.has(value)) continue;\n index2.set(value, domain.push(value) - 1);\n }\n return scale3;\n };\n scale3.range = function(_) {\n return arguments.length ? (range3 = Array.from(_), scale3) : range3.slice();\n };\n scale3.unknown = function(_) {\n return arguments.length ? (unknown = _, scale3) : unknown;\n };\n scale3.copy = function() {\n return ordinal(domain, range3).unknown(unknown);\n };\n initRange.apply(scale3, arguments);\n return scale3;\n}\n\n// ../../node_modules/d3-scale/src/band.js\nfunction band() {\n var scale3 = ordinal().unknown(void 0), domain = scale3.domain, ordinalRange2 = scale3.range, r0 = 0, r1 = 1, step, bandwidth, round2 = false, paddingInner = 0, paddingOuter = 0, align3 = 0.5;\n delete scale3.unknown;\n function rescale() {\n var n = domain().length, reverse3 = r1 < r0, start2 = reverse3 ? r1 : r0, stop = reverse3 ? r0 : r1;\n step = (stop - start2) / Math.max(1, n - paddingInner + paddingOuter * 2);\n if (round2) step = Math.floor(step);\n start2 += (stop - start2 - step * (n - paddingInner)) * align3;\n bandwidth = step * (1 - paddingInner);\n if (round2) start2 = Math.round(start2), bandwidth = Math.round(bandwidth);\n var values2 = range(n).map(function(i) {\n return start2 + step * i;\n });\n return ordinalRange2(reverse3 ? values2.reverse() : values2);\n }\n scale3.domain = function(_) {\n return arguments.length ? (domain(_), rescale()) : domain();\n };\n scale3.range = function(_) {\n return arguments.length ? ([r0, r1] = _, r0 = +r0, r1 = +r1, rescale()) : [r0, r1];\n };\n scale3.rangeRound = function(_) {\n return [r0, r1] = _, r0 = +r0, r1 = +r1, round2 = true, rescale();\n };\n scale3.bandwidth = function() {\n return bandwidth;\n };\n scale3.step = function() {\n return step;\n };\n scale3.round = function(_) {\n return arguments.length ? (round2 = !!_, rescale()) : round2;\n };\n scale3.padding = function(_) {\n return arguments.length ? (paddingInner = Math.min(1, paddingOuter = +_), rescale()) : paddingInner;\n };\n scale3.paddingInner = function(_) {\n return arguments.length ? (paddingInner = Math.min(1, _), rescale()) : paddingInner;\n };\n scale3.paddingOuter = function(_) {\n return arguments.length ? (paddingOuter = +_, rescale()) : paddingOuter;\n };\n scale3.align = function(_) {\n return arguments.length ? (align3 = Math.max(0, Math.min(1, _)), rescale()) : align3;\n };\n scale3.copy = function() {\n return band(domain(), [r0, r1]).round(round2).paddingInner(paddingInner).paddingOuter(paddingOuter).align(align3);\n };\n return initRange.apply(rescale(), arguments);\n}\nfunction pointish(scale3) {\n var copy4 = scale3.copy;\n scale3.padding = scale3.paddingOuter;\n delete scale3.paddingInner;\n delete scale3.paddingOuter;\n scale3.copy = function() {\n return pointish(copy4());\n };\n return scale3;\n}\nfunction point() {\n return pointish(band.apply(null, arguments).paddingInner(1));\n}\n\n// ../../node_modules/d3-scale/src/constant.js\nfunction constants(x3) {\n return function() {\n return x3;\n };\n}\n\n// ../../node_modules/d3-scale/src/number.js\nfunction number3(x3) {\n return +x3;\n}\n\n// ../../node_modules/d3-scale/src/continuous.js\nvar unit = [0, 1];\nfunction identity4(x3) {\n return x3;\n}\nfunction normalize2(a2, b) {\n return (b -= a2 = +a2) ? function(x3) {\n return (x3 - a2) / b;\n } : constants(isNaN(b) ? NaN : 0.5);\n}\nfunction clamper(a2, b) {\n var t;\n if (a2 > b) t = a2, a2 = b, b = t;\n return function(x3) {\n return Math.max(a2, Math.min(b, x3));\n };\n}\nfunction bimap(domain, range3, interpolate) {\n var d0 = domain[0], d1 = domain[1], r0 = range3[0], r1 = range3[1];\n if (d1 < d0) d0 = normalize2(d1, d0), r0 = interpolate(r1, r0);\n else d0 = normalize2(d0, d1), r0 = interpolate(r0, r1);\n return function(x3) {\n return r0(d0(x3));\n };\n}\nfunction polymap(domain, range3, interpolate) {\n var j = Math.min(domain.length, range3.length) - 1, d = new Array(j), r = new Array(j), i = -1;\n if (domain[j] < domain[0]) {\n domain = domain.slice().reverse();\n range3 = range3.slice().reverse();\n }\n while (++i < j) {\n d[i] = normalize2(domain[i], domain[i + 1]);\n r[i] = interpolate(range3[i], range3[i + 1]);\n }\n return function(x3) {\n var i2 = bisect_default(domain, x3, 1, j) - 1;\n return r[i2](d[i2](x3));\n };\n}\nfunction copy(source, target) {\n return target.domain(source.domain()).range(source.range()).interpolate(source.interpolate()).clamp(source.clamp()).unknown(source.unknown());\n}\nfunction transformer2() {\n var domain = unit, range3 = unit, interpolate = value_default, transform3, untransform, unknown, clamp = identity4, piecewise2, output, input3;\n function rescale() {\n var n = Math.min(domain.length, range3.length);\n if (clamp !== identity4) clamp = clamper(domain[0], domain[n - 1]);\n piecewise2 = n > 2 ? polymap : bimap;\n output = input3 = null;\n return scale3;\n }\n function scale3(x3) {\n return x3 == null || isNaN(x3 = +x3) ? unknown : (output || (output = piecewise2(domain.map(transform3), range3, interpolate)))(transform3(clamp(x3)));\n }\n scale3.invert = function(y3) {\n return clamp(untransform((input3 || (input3 = piecewise2(range3, domain.map(transform3), number_default)))(y3)));\n };\n scale3.domain = function(_) {\n return arguments.length ? (domain = Array.from(_, number3), rescale()) : domain.slice();\n };\n scale3.range = function(_) {\n return arguments.length ? (range3 = Array.from(_), rescale()) : range3.slice();\n };\n scale3.rangeRound = function(_) {\n return range3 = Array.from(_), interpolate = round_default, rescale();\n };\n scale3.clamp = function(_) {\n return arguments.length ? (clamp = _ ? true : identity4, rescale()) : clamp !== identity4;\n };\n scale3.interpolate = function(_) {\n return arguments.length ? (interpolate = _, rescale()) : interpolate;\n };\n scale3.unknown = function(_) {\n return arguments.length ? (unknown = _, scale3) : unknown;\n };\n return function(t, u4) {\n transform3 = t, untransform = u4;\n return rescale();\n };\n}\nfunction continuous() {\n return transformer2()(identity4, identity4);\n}\n\n// ../../node_modules/d3-scale/src/tickFormat.js\nfunction tickFormat(start2, stop, count4, specifier) {\n var step = tickStep(start2, stop, count4), precision;\n specifier = formatSpecifier(specifier == null ? \",f\" : specifier);\n switch (specifier.type) {\n case \"s\": {\n var value = Math.max(Math.abs(start2), Math.abs(stop));\n if (specifier.precision == null && !isNaN(precision = precisionPrefix_default(step, value))) specifier.precision = precision;\n return formatPrefix(specifier, value);\n }\n case \"\":\n case \"e\":\n case \"g\":\n case \"p\":\n case \"r\": {\n if (specifier.precision == null && !isNaN(precision = precisionRound_default(step, Math.max(Math.abs(start2), Math.abs(stop))))) specifier.precision = precision - (specifier.type === \"e\");\n break;\n }\n case \"f\":\n case \"%\": {\n if (specifier.precision == null && !isNaN(precision = precisionFixed_default(step))) specifier.precision = precision - (specifier.type === \"%\") * 2;\n break;\n }\n }\n return format(specifier);\n}\n\n// ../../node_modules/d3-scale/src/linear.js\nfunction linearish(scale3) {\n var domain = scale3.domain;\n scale3.ticks = function(count4) {\n var d = domain();\n return ticks(d[0], d[d.length - 1], count4 == null ? 10 : count4);\n };\n scale3.tickFormat = function(count4, specifier) {\n var d = domain();\n return tickFormat(d[0], d[d.length - 1], count4 == null ? 10 : count4, specifier);\n };\n scale3.nice = function(count4) {\n if (count4 == null) count4 = 10;\n var d = domain();\n var i0 = 0;\n var i1 = d.length - 1;\n var start2 = d[i0];\n var stop = d[i1];\n var prestep;\n var step;\n var maxIter = 10;\n if (stop < start2) {\n step = start2, start2 = stop, stop = step;\n step = i0, i0 = i1, i1 = step;\n }\n while (maxIter-- > 0) {\n step = tickIncrement(start2, stop, count4);\n if (step === prestep) {\n d[i0] = start2;\n d[i1] = stop;\n return domain(d);\n } else if (step > 0) {\n start2 = Math.floor(start2 / step) * step;\n stop = Math.ceil(stop / step) * step;\n } else if (step < 0) {\n start2 = Math.ceil(start2 * step) / step;\n stop = Math.floor(stop * step) / step;\n } else {\n break;\n }\n prestep = step;\n }\n return scale3;\n };\n return scale3;\n}\nfunction linear2() {\n var scale3 = continuous();\n scale3.copy = function() {\n return copy(scale3, linear2());\n };\n initRange.apply(scale3, arguments);\n return linearish(scale3);\n}\n\n// ../../node_modules/d3-scale/src/identity.js\nfunction identity5(domain) {\n var unknown;\n function scale3(x3) {\n return x3 == null || isNaN(x3 = +x3) ? unknown : x3;\n }\n scale3.invert = scale3;\n scale3.domain = scale3.range = function(_) {\n return arguments.length ? (domain = Array.from(_, number3), scale3) : domain.slice();\n };\n scale3.unknown = function(_) {\n return arguments.length ? (unknown = _, scale3) : unknown;\n };\n scale3.copy = function() {\n return identity5(domain).unknown(unknown);\n };\n domain = arguments.length ? Array.from(domain, number3) : [0, 1];\n return linearish(scale3);\n}\n\n// ../../node_modules/d3-scale/src/nice.js\nfunction nice2(domain, interval3) {\n domain = domain.slice();\n var i0 = 0, i1 = domain.length - 1, x06 = domain[i0], x12 = domain[i1], t;\n if (x12 < x06) {\n t = i0, i0 = i1, i1 = t;\n t = x06, x06 = x12, x12 = t;\n }\n domain[i0] = interval3.floor(x06);\n domain[i1] = interval3.ceil(x12);\n return domain;\n}\n\n// ../../node_modules/d3-scale/src/log.js\nfunction transformLog(x3) {\n return Math.log(x3);\n}\nfunction transformExp(x3) {\n return Math.exp(x3);\n}\nfunction transformLogn(x3) {\n return -Math.log(-x3);\n}\nfunction transformExpn(x3) {\n return -Math.exp(-x3);\n}\nfunction pow10(x3) {\n return isFinite(x3) ? +(\"1e\" + x3) : x3 < 0 ? 0 : x3;\n}\nfunction powp(base) {\n return base === 10 ? pow10 : base === Math.E ? Math.exp : (x3) => Math.pow(base, x3);\n}\nfunction logp(base) {\n return base === Math.E ? Math.log : base === 10 && Math.log10 || base === 2 && Math.log2 || (base = Math.log(base), (x3) => Math.log(x3) / base);\n}\nfunction reflect(f) {\n return (x3, k2) => -f(-x3, k2);\n}\nfunction loggish(transform3) {\n const scale3 = transform3(transformLog, transformExp);\n const domain = scale3.domain;\n let base = 10;\n let logs;\n let pows;\n function rescale() {\n logs = logp(base), pows = powp(base);\n if (domain()[0] < 0) {\n logs = reflect(logs), pows = reflect(pows);\n transform3(transformLogn, transformExpn);\n } else {\n transform3(transformLog, transformExp);\n }\n return scale3;\n }\n scale3.base = function(_) {\n return arguments.length ? (base = +_, rescale()) : base;\n };\n scale3.domain = function(_) {\n return arguments.length ? (domain(_), rescale()) : domain();\n };\n scale3.ticks = (count4) => {\n const d = domain();\n let u4 = d[0];\n let v2 = d[d.length - 1];\n const r = v2 < u4;\n if (r) [u4, v2] = [v2, u4];\n let i = logs(u4);\n let j = logs(v2);\n let k2;\n let t;\n const n = count4 == null ? 10 : +count4;\n let z = [];\n if (!(base % 1) && j - i < n) {\n i = Math.floor(i), j = Math.ceil(j);\n if (u4 > 0) for (; i <= j; ++i) {\n for (k2 = 1; k2 < base; ++k2) {\n t = i < 0 ? k2 / pows(-i) : k2 * pows(i);\n if (t < u4) continue;\n if (t > v2) break;\n z.push(t);\n }\n }\n else for (; i <= j; ++i) {\n for (k2 = base - 1; k2 >= 1; --k2) {\n t = i > 0 ? k2 / pows(-i) : k2 * pows(i);\n if (t < u4) continue;\n if (t > v2) break;\n z.push(t);\n }\n }\n if (z.length * 2 < n) z = ticks(u4, v2, n);\n } else {\n z = ticks(i, j, Math.min(j - i, n)).map(pows);\n }\n return r ? z.reverse() : z;\n };\n scale3.tickFormat = (count4, specifier) => {\n if (count4 == null) count4 = 10;\n if (specifier == null) specifier = base === 10 ? \"s\" : \",\";\n if (typeof specifier !== \"function\") {\n if (!(base % 1) && (specifier = formatSpecifier(specifier)).precision == null) specifier.trim = true;\n specifier = format(specifier);\n }\n if (count4 === Infinity) return specifier;\n const k2 = Math.max(1, base * count4 / scale3.ticks().length);\n return (d) => {\n let i = d / pows(Math.round(logs(d)));\n if (i * base < base - 0.5) i *= base;\n return i <= k2 ? specifier(d) : \"\";\n };\n };\n scale3.nice = () => {\n return domain(nice2(domain(), {\n floor: (x3) => pows(Math.floor(logs(x3))),\n ceil: (x3) => pows(Math.ceil(logs(x3)))\n }));\n };\n return scale3;\n}\nfunction log2() {\n const scale3 = loggish(transformer2()).domain([1, 10]);\n scale3.copy = () => copy(scale3, log2()).base(scale3.base());\n initRange.apply(scale3, arguments);\n return scale3;\n}\n\n// ../../node_modules/d3-scale/src/symlog.js\nfunction transformSymlog(c4) {\n return function(x3) {\n return Math.sign(x3) * Math.log1p(Math.abs(x3 / c4));\n };\n}\nfunction transformSymexp(c4) {\n return function(x3) {\n return Math.sign(x3) * Math.expm1(Math.abs(x3)) * c4;\n };\n}\nfunction symlogish(transform3) {\n var c4 = 1, scale3 = transform3(transformSymlog(c4), transformSymexp(c4));\n scale3.constant = function(_) {\n return arguments.length ? transform3(transformSymlog(c4 = +_), transformSymexp(c4)) : c4;\n };\n return linearish(scale3);\n}\nfunction symlog() {\n var scale3 = symlogish(transformer2());\n scale3.copy = function() {\n return copy(scale3, symlog()).constant(scale3.constant());\n };\n return initRange.apply(scale3, arguments);\n}\n\n// ../../node_modules/d3-scale/src/pow.js\nfunction transformPow(exponent) {\n return function(x3) {\n return x3 < 0 ? -Math.pow(-x3, exponent) : Math.pow(x3, exponent);\n };\n}\nfunction transformSqrt(x3) {\n return x3 < 0 ? -Math.sqrt(-x3) : Math.sqrt(x3);\n}\nfunction transformSquare(x3) {\n return x3 < 0 ? -x3 * x3 : x3 * x3;\n}\nfunction powish(transform3) {\n var scale3 = transform3(identity4, identity4), exponent = 1;\n function rescale() {\n return exponent === 1 ? transform3(identity4, identity4) : exponent === 0.5 ? transform3(transformSqrt, transformSquare) : transform3(transformPow(exponent), transformPow(1 / exponent));\n }\n scale3.exponent = function(_) {\n return arguments.length ? (exponent = +_, rescale()) : exponent;\n };\n return linearish(scale3);\n}\nfunction pow3() {\n var scale3 = powish(transformer2());\n scale3.copy = function() {\n return copy(scale3, pow3()).exponent(scale3.exponent());\n };\n initRange.apply(scale3, arguments);\n return scale3;\n}\n\n// ../../node_modules/d3-scale/src/quantile.js\nfunction quantile3() {\n var domain = [], range3 = [], thresholds = [], unknown;\n function rescale() {\n var i = 0, n = Math.max(1, range3.length);\n thresholds = new Array(n - 1);\n while (++i < n) thresholds[i - 1] = quantileSorted(domain, i / n);\n return scale3;\n }\n function scale3(x3) {\n return x3 == null || isNaN(x3 = +x3) ? unknown : range3[bisect_default(thresholds, x3)];\n }\n scale3.invertExtent = function(y3) {\n var i = range3.indexOf(y3);\n return i < 0 ? [NaN, NaN] : [\n i > 0 ? thresholds[i - 1] : domain[0],\n i < thresholds.length ? thresholds[i] : domain[domain.length - 1]\n ];\n };\n scale3.domain = function(_) {\n if (!arguments.length) return domain.slice();\n domain = [];\n for (let d of _) if (d != null && !isNaN(d = +d)) domain.push(d);\n domain.sort(ascending);\n return rescale();\n };\n scale3.range = function(_) {\n return arguments.length ? (range3 = Array.from(_), rescale()) : range3.slice();\n };\n scale3.unknown = function(_) {\n return arguments.length ? (unknown = _, scale3) : unknown;\n };\n scale3.quantiles = function() {\n return thresholds.slice();\n };\n scale3.copy = function() {\n return quantile3().domain(domain).range(range3).unknown(unknown);\n };\n return initRange.apply(scale3, arguments);\n}\n\n// ../../node_modules/d3-scale/src/threshold.js\nfunction threshold() {\n var domain = [0.5], range3 = [0, 1], unknown, n = 1;\n function scale3(x3) {\n return x3 != null && x3 <= x3 ? range3[bisect_default(domain, x3, 0, n)] : unknown;\n }\n scale3.domain = function(_) {\n return arguments.length ? (domain = Array.from(_), n = Math.min(domain.length, range3.length - 1), scale3) : domain.slice();\n };\n scale3.range = function(_) {\n return arguments.length ? (range3 = Array.from(_), n = Math.min(domain.length, range3.length - 1), scale3) : range3.slice();\n };\n scale3.invertExtent = function(y3) {\n var i = range3.indexOf(y3);\n return [domain[i - 1], domain[i]];\n };\n scale3.unknown = function(_) {\n return arguments.length ? (unknown = _, scale3) : unknown;\n };\n scale3.copy = function() {\n return threshold().domain(domain).range(range3).unknown(unknown);\n };\n return initRange.apply(scale3, arguments);\n}\n\n// ../../node_modules/d3-time/src/interval.js\nvar t02 = /* @__PURE__ */ new Date();\nvar t12 = /* @__PURE__ */ new Date();\nfunction timeInterval(floori, offseti, count4, field3) {\n function interval3(date3) {\n return floori(date3 = arguments.length === 0 ? /* @__PURE__ */ new Date() : /* @__PURE__ */ new Date(+date3)), date3;\n }\n interval3.floor = (date3) => {\n return floori(date3 = /* @__PURE__ */ new Date(+date3)), date3;\n };\n interval3.ceil = (date3) => {\n return floori(date3 = new Date(date3 - 1)), offseti(date3, 1), floori(date3), date3;\n };\n interval3.round = (date3) => {\n const d0 = interval3(date3), d1 = interval3.ceil(date3);\n return date3 - d0 < d1 - date3 ? d0 : d1;\n };\n interval3.offset = (date3, step) => {\n return offseti(date3 = /* @__PURE__ */ new Date(+date3), step == null ? 1 : Math.floor(step)), date3;\n };\n interval3.range = (start2, stop, step) => {\n const range3 = [];\n start2 = interval3.ceil(start2);\n step = step == null ? 1 : Math.floor(step);\n if (!(start2 < stop) || !(step > 0)) return range3;\n let previous;\n do\n range3.push(previous = /* @__PURE__ */ new Date(+start2)), offseti(start2, step), floori(start2);\n while (previous < start2 && start2 < stop);\n return range3;\n };\n interval3.filter = (test) => {\n return timeInterval((date3) => {\n if (date3 >= date3) while (floori(date3), !test(date3)) date3.setTime(date3 - 1);\n }, (date3, step) => {\n if (date3 >= date3) {\n if (step < 0) while (++step <= 0) {\n while (offseti(date3, -1), !test(date3)) {\n }\n }\n else while (--step >= 0) {\n while (offseti(date3, 1), !test(date3)) {\n }\n }\n }\n });\n };\n if (count4) {\n interval3.count = (start2, end) => {\n t02.setTime(+start2), t12.setTime(+end);\n floori(t02), floori(t12);\n return Math.floor(count4(t02, t12));\n };\n interval3.every = (step) => {\n step = Math.floor(step);\n return !isFinite(step) || !(step > 0) ? null : !(step > 1) ? interval3 : interval3.filter(field3 ? (d) => field3(d) % step === 0 : (d) => interval3.count(0, d) % step === 0);\n };\n }\n return interval3;\n}\n\n// ../../node_modules/d3-time/src/millisecond.js\nvar millisecond = timeInterval(() => {\n}, (date3, step) => {\n date3.setTime(+date3 + step);\n}, (start2, end) => {\n return end - start2;\n});\nmillisecond.every = (k2) => {\n k2 = Math.floor(k2);\n if (!isFinite(k2) || !(k2 > 0)) return null;\n if (!(k2 > 1)) return millisecond;\n return timeInterval((date3) => {\n date3.setTime(Math.floor(date3 / k2) * k2);\n }, (date3, step) => {\n date3.setTime(+date3 + step * k2);\n }, (start2, end) => {\n return (end - start2) / k2;\n });\n};\nvar milliseconds = millisecond.range;\n\n// ../../node_modules/d3-time/src/duration.js\nvar durationSecond = 1e3;\nvar durationMinute = durationSecond * 60;\nvar durationHour = durationMinute * 60;\nvar durationDay = durationHour * 24;\nvar durationWeek = durationDay * 7;\nvar durationMonth = durationDay * 30;\nvar durationYear = durationDay * 365;\n\n// ../../node_modules/d3-time/src/second.js\nvar second = timeInterval((date3) => {\n date3.setTime(date3 - date3.getMilliseconds());\n}, (date3, step) => {\n date3.setTime(+date3 + step * durationSecond);\n}, (start2, end) => {\n return (end - start2) / durationSecond;\n}, (date3) => {\n return date3.getUTCSeconds();\n});\nvar seconds = second.range;\n\n// ../../node_modules/d3-time/src/minute.js\nvar timeMinute = timeInterval((date3) => {\n date3.setTime(date3 - date3.getMilliseconds() - date3.getSeconds() * durationSecond);\n}, (date3, step) => {\n date3.setTime(+date3 + step * durationMinute);\n}, (start2, end) => {\n return (end - start2) / durationMinute;\n}, (date3) => {\n return date3.getMinutes();\n});\nvar timeMinutes = timeMinute.range;\nvar utcMinute = timeInterval((date3) => {\n date3.setUTCSeconds(0, 0);\n}, (date3, step) => {\n date3.setTime(+date3 + step * durationMinute);\n}, (start2, end) => {\n return (end - start2) / durationMinute;\n}, (date3) => {\n return date3.getUTCMinutes();\n});\nvar utcMinutes = utcMinute.range;\n\n// ../../node_modules/d3-time/src/hour.js\nvar timeHour = timeInterval((date3) => {\n date3.setTime(date3 - date3.getMilliseconds() - date3.getSeconds() * durationSecond - date3.getMinutes() * durationMinute);\n}, (date3, step) => {\n date3.setTime(+date3 + step * durationHour);\n}, (start2, end) => {\n return (end - start2) / durationHour;\n}, (date3) => {\n return date3.getHours();\n});\nvar timeHours = timeHour.range;\nvar utcHour = timeInterval((date3) => {\n date3.setUTCMinutes(0, 0, 0);\n}, (date3, step) => {\n date3.setTime(+date3 + step * durationHour);\n}, (start2, end) => {\n return (end - start2) / durationHour;\n}, (date3) => {\n return date3.getUTCHours();\n});\nvar utcHours = utcHour.range;\n\n// ../../node_modules/d3-time/src/day.js\nvar timeDay = timeInterval(\n (date3) => date3.setHours(0, 0, 0, 0),\n (date3, step) => date3.setDate(date3.getDate() + step),\n (start2, end) => (end - start2 - (end.getTimezoneOffset() - start2.getTimezoneOffset()) * durationMinute) / durationDay,\n (date3) => date3.getDate() - 1\n);\nvar timeDays = timeDay.range;\nvar utcDay = timeInterval((date3) => {\n date3.setUTCHours(0, 0, 0, 0);\n}, (date3, step) => {\n date3.setUTCDate(date3.getUTCDate() + step);\n}, (start2, end) => {\n return (end - start2) / durationDay;\n}, (date3) => {\n return date3.getUTCDate() - 1;\n});\nvar utcDays = utcDay.range;\nvar unixDay = timeInterval((date3) => {\n date3.setUTCHours(0, 0, 0, 0);\n}, (date3, step) => {\n date3.setUTCDate(date3.getUTCDate() + step);\n}, (start2, end) => {\n return (end - start2) / durationDay;\n}, (date3) => {\n return Math.floor(date3 / durationDay);\n});\nvar unixDays = unixDay.range;\n\n// ../../node_modules/d3-time/src/week.js\nfunction timeWeekday(i) {\n return timeInterval((date3) => {\n date3.setDate(date3.getDate() - (date3.getDay() + 7 - i) % 7);\n date3.setHours(0, 0, 0, 0);\n }, (date3, step) => {\n date3.setDate(date3.getDate() + step * 7);\n }, (start2, end) => {\n return (end - start2 - (end.getTimezoneOffset() - start2.getTimezoneOffset()) * durationMinute) / durationWeek;\n });\n}\nvar timeSunday = timeWeekday(0);\nvar timeMonday = timeWeekday(1);\nvar timeTuesday = timeWeekday(2);\nvar timeWednesday = timeWeekday(3);\nvar timeThursday = timeWeekday(4);\nvar timeFriday = timeWeekday(5);\nvar timeSaturday = timeWeekday(6);\nvar timeSundays = timeSunday.range;\nvar timeMondays = timeMonday.range;\nvar timeTuesdays = timeTuesday.range;\nvar timeWednesdays = timeWednesday.range;\nvar timeThursdays = timeThursday.range;\nvar timeFridays = timeFriday.range;\nvar timeSaturdays = timeSaturday.range;\nfunction utcWeekday(i) {\n return timeInterval((date3) => {\n date3.setUTCDate(date3.getUTCDate() - (date3.getUTCDay() + 7 - i) % 7);\n date3.setUTCHours(0, 0, 0, 0);\n }, (date3, step) => {\n date3.setUTCDate(date3.getUTCDate() + step * 7);\n }, (start2, end) => {\n return (end - start2) / durationWeek;\n });\n}\nvar utcSunday = utcWeekday(0);\nvar utcMonday = utcWeekday(1);\nvar utcTuesday = utcWeekday(2);\nvar utcWednesday = utcWeekday(3);\nvar utcThursday = utcWeekday(4);\nvar utcFriday = utcWeekday(5);\nvar utcSaturday = utcWeekday(6);\nvar utcSundays = utcSunday.range;\nvar utcMondays = utcMonday.range;\nvar utcTuesdays = utcTuesday.range;\nvar utcWednesdays = utcWednesday.range;\nvar utcThursdays = utcThursday.range;\nvar utcFridays = utcFriday.range;\nvar utcSaturdays = utcSaturday.range;\n\n// ../../node_modules/d3-time/src/month.js\nvar timeMonth = timeInterval((date3) => {\n date3.setDate(1);\n date3.setHours(0, 0, 0, 0);\n}, (date3, step) => {\n date3.setMonth(date3.getMonth() + step);\n}, (start2, end) => {\n return end.getMonth() - start2.getMonth() + (end.getFullYear() - start2.getFullYear()) * 12;\n}, (date3) => {\n return date3.getMonth();\n});\nvar timeMonths = timeMonth.range;\nvar utcMonth = timeInterval((date3) => {\n date3.setUTCDate(1);\n date3.setUTCHours(0, 0, 0, 0);\n}, (date3, step) => {\n date3.setUTCMonth(date3.getUTCMonth() + step);\n}, (start2, end) => {\n return end.getUTCMonth() - start2.getUTCMonth() + (end.getUTCFullYear() - start2.getUTCFullYear()) * 12;\n}, (date3) => {\n return date3.getUTCMonth();\n});\nvar utcMonths = utcMonth.range;\n\n// ../../node_modules/d3-time/src/year.js\nvar timeYear = timeInterval((date3) => {\n date3.setMonth(0, 1);\n date3.setHours(0, 0, 0, 0);\n}, (date3, step) => {\n date3.setFullYear(date3.getFullYear() + step);\n}, (start2, end) => {\n return end.getFullYear() - start2.getFullYear();\n}, (date3) => {\n return date3.getFullYear();\n});\ntimeYear.every = (k2) => {\n return !isFinite(k2 = Math.floor(k2)) || !(k2 > 0) ? null : timeInterval((date3) => {\n date3.setFullYear(Math.floor(date3.getFullYear() / k2) * k2);\n date3.setMonth(0, 1);\n date3.setHours(0, 0, 0, 0);\n }, (date3, step) => {\n date3.setFullYear(date3.getFullYear() + step * k2);\n });\n};\nvar timeYears = timeYear.range;\nvar utcYear = timeInterval((date3) => {\n date3.setUTCMonth(0, 1);\n date3.setUTCHours(0, 0, 0, 0);\n}, (date3, step) => {\n date3.setUTCFullYear(date3.getUTCFullYear() + step);\n}, (start2, end) => {\n return end.getUTCFullYear() - start2.getUTCFullYear();\n}, (date3) => {\n return date3.getUTCFullYear();\n});\nutcYear.every = (k2) => {\n return !isFinite(k2 = Math.floor(k2)) || !(k2 > 0) ? null : timeInterval((date3) => {\n date3.setUTCFullYear(Math.floor(date3.getUTCFullYear() / k2) * k2);\n date3.setUTCMonth(0, 1);\n date3.setUTCHours(0, 0, 0, 0);\n }, (date3, step) => {\n date3.setUTCFullYear(date3.getUTCFullYear() + step * k2);\n });\n};\nvar utcYears = utcYear.range;\n\n// ../../node_modules/d3-time/src/ticks.js\nfunction ticker(year, month, week, day, hour, minute) {\n const tickIntervals2 = [\n [second, 1, durationSecond],\n [second, 5, 5 * durationSecond],\n [second, 15, 15 * durationSecond],\n [second, 30, 30 * durationSecond],\n [minute, 1, durationMinute],\n [minute, 5, 5 * durationMinute],\n [minute, 15, 15 * durationMinute],\n [minute, 30, 30 * durationMinute],\n [hour, 1, durationHour],\n [hour, 3, 3 * durationHour],\n [hour, 6, 6 * durationHour],\n [hour, 12, 12 * durationHour],\n [day, 1, durationDay],\n [day, 2, 2 * durationDay],\n [week, 1, durationWeek],\n [month, 1, durationMonth],\n [month, 3, 3 * durationMonth],\n [year, 1, durationYear]\n ];\n function ticks2(start2, stop, count4) {\n const reverse3 = stop < start2;\n if (reverse3) [start2, stop] = [stop, start2];\n const interval3 = count4 && typeof count4.range === \"function\" ? count4 : tickInterval(start2, stop, count4);\n const ticks3 = interval3 ? interval3.range(start2, +stop + 1) : [];\n return reverse3 ? ticks3.reverse() : ticks3;\n }\n function tickInterval(start2, stop, count4) {\n const target = Math.abs(stop - start2) / count4;\n const i = bisector(([, , step2]) => step2).right(tickIntervals2, target);\n if (i === tickIntervals2.length) return year.every(tickStep(start2 / durationYear, stop / durationYear, count4));\n if (i === 0) return millisecond.every(Math.max(tickStep(start2, stop, count4), 1));\n const [t, step] = tickIntervals2[target / tickIntervals2[i - 1][2] < tickIntervals2[i][2] / target ? i - 1 : i];\n return t.every(step);\n }\n return [ticks2, tickInterval];\n}\nvar [utcTicks, utcTickInterval] = ticker(utcYear, utcMonth, utcSunday, unixDay, utcHour, utcMinute);\nvar [timeTicks, timeTickInterval] = ticker(timeYear, timeMonth, timeSunday, timeDay, timeHour, timeMinute);\n\n// ../../node_modules/d3-time-format/src/locale.js\nfunction localDate(d) {\n if (0 <= d.y && d.y < 100) {\n var date3 = new Date(-1, d.m, d.d, d.H, d.M, d.S, d.L);\n date3.setFullYear(d.y);\n return date3;\n }\n return new Date(d.y, d.m, d.d, d.H, d.M, d.S, d.L);\n}\nfunction utcDate(d) {\n if (0 <= d.y && d.y < 100) {\n var date3 = new Date(Date.UTC(-1, d.m, d.d, d.H, d.M, d.S, d.L));\n date3.setUTCFullYear(d.y);\n return date3;\n }\n return new Date(Date.UTC(d.y, d.m, d.d, d.H, d.M, d.S, d.L));\n}\nfunction newDate(y3, m, d) {\n return { y: y3, m, d, H: 0, M: 0, S: 0, L: 0 };\n}\nfunction formatLocale(locale3) {\n var locale_dateTime = locale3.dateTime, locale_date = locale3.date, locale_time = locale3.time, locale_periods = locale3.periods, locale_weekdays = locale3.days, locale_shortWeekdays = locale3.shortDays, locale_months = locale3.months, locale_shortMonths = locale3.shortMonths;\n var periodRe = formatRe(locale_periods), periodLookup = formatLookup(locale_periods), weekdayRe = formatRe(locale_weekdays), weekdayLookup = formatLookup(locale_weekdays), shortWeekdayRe = formatRe(locale_shortWeekdays), shortWeekdayLookup = formatLookup(locale_shortWeekdays), monthRe = formatRe(locale_months), monthLookup = formatLookup(locale_months), shortMonthRe = formatRe(locale_shortMonths), shortMonthLookup = formatLookup(locale_shortMonths);\n var formats = {\n \"a\": formatShortWeekday,\n \"A\": formatWeekday2,\n \"b\": formatShortMonth,\n \"B\": formatMonth2,\n \"c\": null,\n \"d\": formatDayOfMonth,\n \"e\": formatDayOfMonth,\n \"f\": formatMicroseconds,\n \"g\": formatYearISO,\n \"G\": formatFullYearISO,\n \"H\": formatHour24,\n \"I\": formatHour12,\n \"j\": formatDayOfYear,\n \"L\": formatMilliseconds,\n \"m\": formatMonthNumber,\n \"M\": formatMinutes,\n \"p\": formatPeriod,\n \"q\": formatQuarter,\n \"Q\": formatUnixTimestamp,\n \"s\": formatUnixTimestampSeconds,\n \"S\": formatSeconds,\n \"u\": formatWeekdayNumberMonday,\n \"U\": formatWeekNumberSunday,\n \"V\": formatWeekNumberISO,\n \"w\": formatWeekdayNumberSunday,\n \"W\": formatWeekNumberMonday,\n \"x\": null,\n \"X\": null,\n \"y\": formatYear,\n \"Y\": formatFullYear,\n \"Z\": formatZone,\n \"%\": formatLiteralPercent\n };\n var utcFormats = {\n \"a\": formatUTCShortWeekday,\n \"A\": formatUTCWeekday,\n \"b\": formatUTCShortMonth,\n \"B\": formatUTCMonth,\n \"c\": null,\n \"d\": formatUTCDayOfMonth,\n \"e\": formatUTCDayOfMonth,\n \"f\": formatUTCMicroseconds,\n \"g\": formatUTCYearISO,\n \"G\": formatUTCFullYearISO,\n \"H\": formatUTCHour24,\n \"I\": formatUTCHour12,\n \"j\": formatUTCDayOfYear,\n \"L\": formatUTCMilliseconds,\n \"m\": formatUTCMonthNumber,\n \"M\": formatUTCMinutes,\n \"p\": formatUTCPeriod,\n \"q\": formatUTCQuarter,\n \"Q\": formatUnixTimestamp,\n \"s\": formatUnixTimestampSeconds,\n \"S\": formatUTCSeconds,\n \"u\": formatUTCWeekdayNumberMonday,\n \"U\": formatUTCWeekNumberSunday,\n \"V\": formatUTCWeekNumberISO,\n \"w\": formatUTCWeekdayNumberSunday,\n \"W\": formatUTCWeekNumberMonday,\n \"x\": null,\n \"X\": null,\n \"y\": formatUTCYear,\n \"Y\": formatUTCFullYear,\n \"Z\": formatUTCZone,\n \"%\": formatLiteralPercent\n };\n var parses = {\n \"a\": parseShortWeekday,\n \"A\": parseWeekday,\n \"b\": parseShortMonth,\n \"B\": parseMonth,\n \"c\": parseLocaleDateTime,\n \"d\": parseDayOfMonth,\n \"e\": parseDayOfMonth,\n \"f\": parseMicroseconds,\n \"g\": parseYear,\n \"G\": parseFullYear,\n \"H\": parseHour24,\n \"I\": parseHour24,\n \"j\": parseDayOfYear,\n \"L\": parseMilliseconds,\n \"m\": parseMonthNumber,\n \"M\": parseMinutes,\n \"p\": parsePeriod,\n \"q\": parseQuarter,\n \"Q\": parseUnixTimestamp,\n \"s\": parseUnixTimestampSeconds,\n \"S\": parseSeconds,\n \"u\": parseWeekdayNumberMonday,\n \"U\": parseWeekNumberSunday,\n \"V\": parseWeekNumberISO,\n \"w\": parseWeekdayNumberSunday,\n \"W\": parseWeekNumberMonday,\n \"x\": parseLocaleDate,\n \"X\": parseLocaleTime,\n \"y\": parseYear,\n \"Y\": parseFullYear,\n \"Z\": parseZone,\n \"%\": parseLiteralPercent\n };\n formats.x = newFormat(locale_date, formats);\n formats.X = newFormat(locale_time, formats);\n formats.c = newFormat(locale_dateTime, formats);\n utcFormats.x = newFormat(locale_date, utcFormats);\n utcFormats.X = newFormat(locale_time, utcFormats);\n utcFormats.c = newFormat(locale_dateTime, utcFormats);\n function newFormat(specifier, formats2) {\n return function(date3) {\n var string2 = [], i = -1, j = 0, n = specifier.length, c4, pad3, format3;\n if (!(date3 instanceof Date)) date3 = /* @__PURE__ */ new Date(+date3);\n while (++i < n) {\n if (specifier.charCodeAt(i) === 37) {\n string2.push(specifier.slice(j, i));\n if ((pad3 = pads[c4 = specifier.charAt(++i)]) != null) c4 = specifier.charAt(++i);\n else pad3 = c4 === \"e\" ? \" \" : \"0\";\n if (format3 = formats2[c4]) c4 = format3(date3, pad3);\n string2.push(c4);\n j = i + 1;\n }\n }\n string2.push(specifier.slice(j, i));\n return string2.join(\"\");\n };\n }\n function newParse(specifier, Z) {\n return function(string2) {\n var d = newDate(1900, void 0, 1), i = parseSpecifier(d, specifier, string2 += \"\", 0), week, day;\n if (i != string2.length) return null;\n if (\"Q\" in d) return new Date(d.Q);\n if (\"s\" in d) return new Date(d.s * 1e3 + (\"L\" in d ? d.L : 0));\n if (Z && !(\"Z\" in d)) d.Z = 0;\n if (\"p\" in d) d.H = d.H % 12 + d.p * 12;\n if (d.m === void 0) d.m = \"q\" in d ? d.q : 0;\n if (\"V\" in d) {\n if (d.V < 1 || d.V > 53) return null;\n if (!(\"w\" in d)) d.w = 1;\n if (\"Z\" in d) {\n week = utcDate(newDate(d.y, 0, 1)), day = week.getUTCDay();\n week = day > 4 || day === 0 ? utcMonday.ceil(week) : utcMonday(week);\n week = utcDay.offset(week, (d.V - 1) * 7);\n d.y = week.getUTCFullYear();\n d.m = week.getUTCMonth();\n d.d = week.getUTCDate() + (d.w + 6) % 7;\n } else {\n week = localDate(newDate(d.y, 0, 1)), day = week.getDay();\n week = day > 4 || day === 0 ? timeMonday.ceil(week) : timeMonday(week);\n week = timeDay.offset(week, (d.V - 1) * 7);\n d.y = week.getFullYear();\n d.m = week.getMonth();\n d.d = week.getDate() + (d.w + 6) % 7;\n }\n } else if (\"W\" in d || \"U\" in d) {\n if (!(\"w\" in d)) d.w = \"u\" in d ? d.u % 7 : \"W\" in d ? 1 : 0;\n day = \"Z\" in d ? utcDate(newDate(d.y, 0, 1)).getUTCDay() : localDate(newDate(d.y, 0, 1)).getDay();\n d.m = 0;\n d.d = \"W\" in d ? (d.w + 6) % 7 + d.W * 7 - (day + 5) % 7 : d.w + d.U * 7 - (day + 6) % 7;\n }\n if (\"Z\" in d) {\n d.H += d.Z / 100 | 0;\n d.M += d.Z % 100;\n return utcDate(d);\n }\n return localDate(d);\n };\n }\n function parseSpecifier(d, specifier, string2, j) {\n var i = 0, n = specifier.length, m = string2.length, c4, parse2;\n while (i < n) {\n if (j >= m) return -1;\n c4 = specifier.charCodeAt(i++);\n if (c4 === 37) {\n c4 = specifier.charAt(i++);\n parse2 = parses[c4 in pads ? specifier.charAt(i++) : c4];\n if (!parse2 || (j = parse2(d, string2, j)) < 0) return -1;\n } else if (c4 != string2.charCodeAt(j++)) {\n return -1;\n }\n }\n return j;\n }\n function parsePeriod(d, string2, i) {\n var n = periodRe.exec(string2.slice(i));\n return n ? (d.p = periodLookup.get(n[0].toLowerCase()), i + n[0].length) : -1;\n }\n function parseShortWeekday(d, string2, i) {\n var n = shortWeekdayRe.exec(string2.slice(i));\n return n ? (d.w = shortWeekdayLookup.get(n[0].toLowerCase()), i + n[0].length) : -1;\n }\n function parseWeekday(d, string2, i) {\n var n = weekdayRe.exec(string2.slice(i));\n return n ? (d.w = weekdayLookup.get(n[0].toLowerCase()), i + n[0].length) : -1;\n }\n function parseShortMonth(d, string2, i) {\n var n = shortMonthRe.exec(string2.slice(i));\n return n ? (d.m = shortMonthLookup.get(n[0].toLowerCase()), i + n[0].length) : -1;\n }\n function parseMonth(d, string2, i) {\n var n = monthRe.exec(string2.slice(i));\n return n ? (d.m = monthLookup.get(n[0].toLowerCase()), i + n[0].length) : -1;\n }\n function parseLocaleDateTime(d, string2, i) {\n return parseSpecifier(d, locale_dateTime, string2, i);\n }\n function parseLocaleDate(d, string2, i) {\n return parseSpecifier(d, locale_date, string2, i);\n }\n function parseLocaleTime(d, string2, i) {\n return parseSpecifier(d, locale_time, string2, i);\n }\n function formatShortWeekday(d) {\n return locale_shortWeekdays[d.getDay()];\n }\n function formatWeekday2(d) {\n return locale_weekdays[d.getDay()];\n }\n function formatShortMonth(d) {\n return locale_shortMonths[d.getMonth()];\n }\n function formatMonth2(d) {\n return locale_months[d.getMonth()];\n }\n function formatPeriod(d) {\n return locale_periods[+(d.getHours() >= 12)];\n }\n function formatQuarter(d) {\n return 1 + ~~(d.getMonth() / 3);\n }\n function formatUTCShortWeekday(d) {\n return locale_shortWeekdays[d.getUTCDay()];\n }\n function formatUTCWeekday(d) {\n return locale_weekdays[d.getUTCDay()];\n }\n function formatUTCShortMonth(d) {\n return locale_shortMonths[d.getUTCMonth()];\n }\n function formatUTCMonth(d) {\n return locale_months[d.getUTCMonth()];\n }\n function formatUTCPeriod(d) {\n return locale_periods[+(d.getUTCHours() >= 12)];\n }\n function formatUTCQuarter(d) {\n return 1 + ~~(d.getUTCMonth() / 3);\n }\n return {\n format: function(specifier) {\n var f = newFormat(specifier += \"\", formats);\n f.toString = function() {\n return specifier;\n };\n return f;\n },\n parse: function(specifier) {\n var p = newParse(specifier += \"\", false);\n p.toString = function() {\n return specifier;\n };\n return p;\n },\n utcFormat: function(specifier) {\n var f = newFormat(specifier += \"\", utcFormats);\n f.toString = function() {\n return specifier;\n };\n return f;\n },\n utcParse: function(specifier) {\n var p = newParse(specifier += \"\", true);\n p.toString = function() {\n return specifier;\n };\n return p;\n }\n };\n}\nvar pads = { \"-\": \"\", \"_\": \" \", \"0\": \"0\" };\nvar numberRe = /^\\s*\\d+/;\nvar percentRe = /^%/;\nvar requoteRe = /[\\\\^$*+?|[\\]().{}]/g;\nfunction pad(value, fill, width2) {\n var sign3 = value < 0 ? \"-\" : \"\", string2 = (sign3 ? -value : value) + \"\", length4 = string2.length;\n return sign3 + (length4 < width2 ? new Array(width2 - length4 + 1).join(fill) + string2 : string2);\n}\nfunction requote(s2) {\n return s2.replace(requoteRe, \"\\\\$&\");\n}\nfunction formatRe(names) {\n return new RegExp(\"^(?:\" + names.map(requote).join(\"|\") + \")\", \"i\");\n}\nfunction formatLookup(names) {\n return new Map(names.map((name2, i) => [name2.toLowerCase(), i]));\n}\nfunction parseWeekdayNumberSunday(d, string2, i) {\n var n = numberRe.exec(string2.slice(i, i + 1));\n return n ? (d.w = +n[0], i + n[0].length) : -1;\n}\nfunction parseWeekdayNumberMonday(d, string2, i) {\n var n = numberRe.exec(string2.slice(i, i + 1));\n return n ? (d.u = +n[0], i + n[0].length) : -1;\n}\nfunction parseWeekNumberSunday(d, string2, i) {\n var n = numberRe.exec(string2.slice(i, i + 2));\n return n ? (d.U = +n[0], i + n[0].length) : -1;\n}\nfunction parseWeekNumberISO(d, string2, i) {\n var n = numberRe.exec(string2.slice(i, i + 2));\n return n ? (d.V = +n[0], i + n[0].length) : -1;\n}\nfunction parseWeekNumberMonday(d, string2, i) {\n var n = numberRe.exec(string2.slice(i, i + 2));\n return n ? (d.W = +n[0], i + n[0].length) : -1;\n}\nfunction parseFullYear(d, string2, i) {\n var n = numberRe.exec(string2.slice(i, i + 4));\n return n ? (d.y = +n[0], i + n[0].length) : -1;\n}\nfunction parseYear(d, string2, i) {\n var n = numberRe.exec(string2.slice(i, i + 2));\n return n ? (d.y = +n[0] + (+n[0] > 68 ? 1900 : 2e3), i + n[0].length) : -1;\n}\nfunction parseZone(d, string2, i) {\n var n = /^(Z)|([+-]\\d\\d)(?::?(\\d\\d))?/.exec(string2.slice(i, i + 6));\n return n ? (d.Z = n[1] ? 0 : -(n[2] + (n[3] || \"00\")), i + n[0].length) : -1;\n}\nfunction parseQuarter(d, string2, i) {\n var n = numberRe.exec(string2.slice(i, i + 1));\n return n ? (d.q = n[0] * 3 - 3, i + n[0].length) : -1;\n}\nfunction parseMonthNumber(d, string2, i) {\n var n = numberRe.exec(string2.slice(i, i + 2));\n return n ? (d.m = n[0] - 1, i + n[0].length) : -1;\n}\nfunction parseDayOfMonth(d, string2, i) {\n var n = numberRe.exec(string2.slice(i, i + 2));\n return n ? (d.d = +n[0], i + n[0].length) : -1;\n}\nfunction parseDayOfYear(d, string2, i) {\n var n = numberRe.exec(string2.slice(i, i + 3));\n return n ? (d.m = 0, d.d = +n[0], i + n[0].length) : -1;\n}\nfunction parseHour24(d, string2, i) {\n var n = numberRe.exec(string2.slice(i, i + 2));\n return n ? (d.H = +n[0], i + n[0].length) : -1;\n}\nfunction parseMinutes(d, string2, i) {\n var n = numberRe.exec(string2.slice(i, i + 2));\n return n ? (d.M = +n[0], i + n[0].length) : -1;\n}\nfunction parseSeconds(d, string2, i) {\n var n = numberRe.exec(string2.slice(i, i + 2));\n return n ? (d.S = +n[0], i + n[0].length) : -1;\n}\nfunction parseMilliseconds(d, string2, i) {\n var n = numberRe.exec(string2.slice(i, i + 3));\n return n ? (d.L = +n[0], i + n[0].length) : -1;\n}\nfunction parseMicroseconds(d, string2, i) {\n var n = numberRe.exec(string2.slice(i, i + 6));\n return n ? (d.L = Math.floor(n[0] / 1e3), i + n[0].length) : -1;\n}\nfunction parseLiteralPercent(d, string2, i) {\n var n = percentRe.exec(string2.slice(i, i + 1));\n return n ? i + n[0].length : -1;\n}\nfunction parseUnixTimestamp(d, string2, i) {\n var n = numberRe.exec(string2.slice(i));\n return n ? (d.Q = +n[0], i + n[0].length) : -1;\n}\nfunction parseUnixTimestampSeconds(d, string2, i) {\n var n = numberRe.exec(string2.slice(i));\n return n ? (d.s = +n[0], i + n[0].length) : -1;\n}\nfunction formatDayOfMonth(d, p) {\n return pad(d.getDate(), p, 2);\n}\nfunction formatHour24(d, p) {\n return pad(d.getHours(), p, 2);\n}\nfunction formatHour12(d, p) {\n return pad(d.getHours() % 12 || 12, p, 2);\n}\nfunction formatDayOfYear(d, p) {\n return pad(1 + timeDay.count(timeYear(d), d), p, 3);\n}\nfunction formatMilliseconds(d, p) {\n return pad(d.getMilliseconds(), p, 3);\n}\nfunction formatMicroseconds(d, p) {\n return formatMilliseconds(d, p) + \"000\";\n}\nfunction formatMonthNumber(d, p) {\n return pad(d.getMonth() + 1, p, 2);\n}\nfunction formatMinutes(d, p) {\n return pad(d.getMinutes(), p, 2);\n}\nfunction formatSeconds(d, p) {\n return pad(d.getSeconds(), p, 2);\n}\nfunction formatWeekdayNumberMonday(d) {\n var day = d.getDay();\n return day === 0 ? 7 : day;\n}\nfunction formatWeekNumberSunday(d, p) {\n return pad(timeSunday.count(timeYear(d) - 1, d), p, 2);\n}\nfunction dISO(d) {\n var day = d.getDay();\n return day >= 4 || day === 0 ? timeThursday(d) : timeThursday.ceil(d);\n}\nfunction formatWeekNumberISO(d, p) {\n d = dISO(d);\n return pad(timeThursday.count(timeYear(d), d) + (timeYear(d).getDay() === 4), p, 2);\n}\nfunction formatWeekdayNumberSunday(d) {\n return d.getDay();\n}\nfunction formatWeekNumberMonday(d, p) {\n return pad(timeMonday.count(timeYear(d) - 1, d), p, 2);\n}\nfunction formatYear(d, p) {\n return pad(d.getFullYear() % 100, p, 2);\n}\nfunction formatYearISO(d, p) {\n d = dISO(d);\n return pad(d.getFullYear() % 100, p, 2);\n}\nfunction formatFullYear(d, p) {\n return pad(d.getFullYear() % 1e4, p, 4);\n}\nfunction formatFullYearISO(d, p) {\n var day = d.getDay();\n d = day >= 4 || day === 0 ? timeThursday(d) : timeThursday.ceil(d);\n return pad(d.getFullYear() % 1e4, p, 4);\n}\nfunction formatZone(d) {\n var z = d.getTimezoneOffset();\n return (z > 0 ? \"-\" : (z *= -1, \"+\")) + pad(z / 60 | 0, \"0\", 2) + pad(z % 60, \"0\", 2);\n}\nfunction formatUTCDayOfMonth(d, p) {\n return pad(d.getUTCDate(), p, 2);\n}\nfunction formatUTCHour24(d, p) {\n return pad(d.getUTCHours(), p, 2);\n}\nfunction formatUTCHour12(d, p) {\n return pad(d.getUTCHours() % 12 || 12, p, 2);\n}\nfunction formatUTCDayOfYear(d, p) {\n return pad(1 + utcDay.count(utcYear(d), d), p, 3);\n}\nfunction formatUTCMilliseconds(d, p) {\n return pad(d.getUTCMilliseconds(), p, 3);\n}\nfunction formatUTCMicroseconds(d, p) {\n return formatUTCMilliseconds(d, p) + \"000\";\n}\nfunction formatUTCMonthNumber(d, p) {\n return pad(d.getUTCMonth() + 1, p, 2);\n}\nfunction formatUTCMinutes(d, p) {\n return pad(d.getUTCMinutes(), p, 2);\n}\nfunction formatUTCSeconds(d, p) {\n return pad(d.getUTCSeconds(), p, 2);\n}\nfunction formatUTCWeekdayNumberMonday(d) {\n var dow = d.getUTCDay();\n return dow === 0 ? 7 : dow;\n}\nfunction formatUTCWeekNumberSunday(d, p) {\n return pad(utcSunday.count(utcYear(d) - 1, d), p, 2);\n}\nfunction UTCdISO(d) {\n var day = d.getUTCDay();\n return day >= 4 || day === 0 ? utcThursday(d) : utcThursday.ceil(d);\n}\nfunction formatUTCWeekNumberISO(d, p) {\n d = UTCdISO(d);\n return pad(utcThursday.count(utcYear(d), d) + (utcYear(d).getUTCDay() === 4), p, 2);\n}\nfunction formatUTCWeekdayNumberSunday(d) {\n return d.getUTCDay();\n}\nfunction formatUTCWeekNumberMonday(d, p) {\n return pad(utcMonday.count(utcYear(d) - 1, d), p, 2);\n}\nfunction formatUTCYear(d, p) {\n return pad(d.getUTCFullYear() % 100, p, 2);\n}\nfunction formatUTCYearISO(d, p) {\n d = UTCdISO(d);\n return pad(d.getUTCFullYear() % 100, p, 2);\n}\nfunction formatUTCFullYear(d, p) {\n return pad(d.getUTCFullYear() % 1e4, p, 4);\n}\nfunction formatUTCFullYearISO(d, p) {\n var day = d.getUTCDay();\n d = day >= 4 || day === 0 ? utcThursday(d) : utcThursday.ceil(d);\n return pad(d.getUTCFullYear() % 1e4, p, 4);\n}\nfunction formatUTCZone() {\n return \"+0000\";\n}\nfunction formatLiteralPercent() {\n return \"%\";\n}\nfunction formatUnixTimestamp(d) {\n return +d;\n}\nfunction formatUnixTimestampSeconds(d) {\n return Math.floor(+d / 1e3);\n}\n\n// ../../node_modules/d3-time-format/src/defaultLocale.js\nvar locale2;\nvar timeFormat;\nvar timeParse;\nvar utcFormat;\nvar utcParse;\ndefaultLocale2({\n dateTime: \"%x, %X\",\n date: \"%-m/%-d/%Y\",\n time: \"%-I:%M:%S %p\",\n periods: [\"AM\", \"PM\"],\n days: [\"Sunday\", \"Monday\", \"Tuesday\", \"Wednesday\", \"Thursday\", \"Friday\", \"Saturday\"],\n shortDays: [\"Sun\", \"Mon\", \"Tue\", \"Wed\", \"Thu\", \"Fri\", \"Sat\"],\n months: [\"January\", \"February\", \"March\", \"April\", \"May\", \"June\", \"July\", \"August\", \"September\", \"October\", \"November\", \"December\"],\n shortMonths: [\"Jan\", \"Feb\", \"Mar\", \"Apr\", \"May\", \"Jun\", \"Jul\", \"Aug\", \"Sep\", \"Oct\", \"Nov\", \"Dec\"]\n});\nfunction defaultLocale2(definition) {\n locale2 = formatLocale(definition);\n timeFormat = locale2.format;\n timeParse = locale2.parse;\n utcFormat = locale2.utcFormat;\n utcParse = locale2.utcParse;\n return locale2;\n}\n\n// ../../node_modules/d3-scale/src/time.js\nfunction date2(t) {\n return new Date(t);\n}\nfunction number4(t) {\n return t instanceof Date ? +t : +/* @__PURE__ */ new Date(+t);\n}\nfunction calendar(ticks2, tickInterval, year, month, week, day, hour, minute, second3, format3) {\n var scale3 = continuous(), invert2 = scale3.invert, domain = scale3.domain;\n var formatMillisecond = format3(\".%L\"), formatSecond = format3(\":%S\"), formatMinute = format3(\"%I:%M\"), formatHour = format3(\"%I %p\"), formatDay = format3(\"%a %d\"), formatWeek = format3(\"%b %d\"), formatMonth2 = format3(\"%B\"), formatYear3 = format3(\"%Y\");\n function tickFormat2(date3) {\n return (second3(date3) < date3 ? formatMillisecond : minute(date3) < date3 ? formatSecond : hour(date3) < date3 ? formatMinute : day(date3) < date3 ? formatHour : month(date3) < date3 ? week(date3) < date3 ? formatDay : formatWeek : year(date3) < date3 ? formatMonth2 : formatYear3)(date3);\n }\n scale3.invert = function(y3) {\n return new Date(invert2(y3));\n };\n scale3.domain = function(_) {\n return arguments.length ? domain(Array.from(_, number4)) : domain().map(date2);\n };\n scale3.ticks = function(interval3) {\n var d = domain();\n return ticks2(d[0], d[d.length - 1], interval3 == null ? 10 : interval3);\n };\n scale3.tickFormat = function(count4, specifier) {\n return specifier == null ? tickFormat2 : format3(specifier);\n };\n scale3.nice = function(interval3) {\n var d = domain();\n if (!interval3 || typeof interval3.range !== \"function\") interval3 = tickInterval(d[0], d[d.length - 1], interval3 == null ? 10 : interval3);\n return interval3 ? domain(nice2(d, interval3)) : scale3;\n };\n scale3.copy = function() {\n return copy(scale3, calendar(ticks2, tickInterval, year, month, week, day, hour, minute, second3, format3));\n };\n return scale3;\n}\nfunction time2() {\n return initRange.apply(calendar(timeTicks, timeTickInterval, timeYear, timeMonth, timeSunday, timeDay, timeHour, timeMinute, second, timeFormat).domain([new Date(2e3, 0, 1), new Date(2e3, 0, 2)]), arguments);\n}\n\n// ../../node_modules/d3-scale/src/utcTime.js\nfunction utcTime() {\n return initRange.apply(calendar(utcTicks, utcTickInterval, utcYear, utcMonth, utcSunday, utcDay, utcHour, utcMinute, second, utcFormat).domain([Date.UTC(2e3, 0, 1), Date.UTC(2e3, 0, 2)]), arguments);\n}\n\n// ../../node_modules/d3-scale/src/sequential.js\nfunction copy2(source, target) {\n return target.domain(source.domain()).interpolator(source.interpolator()).clamp(source.clamp()).unknown(source.unknown());\n}\n\n// ../../node_modules/d3-scale/src/diverging.js\nfunction transformer3() {\n var x06 = 0, x12 = 0.5, x22 = 1, s2 = 1, t03, t13, t22, k10, k21, interpolator = identity4, transform3, clamp = false, unknown;\n function scale3(x3) {\n return isNaN(x3 = +x3) ? unknown : (x3 = 0.5 + ((x3 = +transform3(x3)) - t13) * (s2 * x3 < s2 * t13 ? k10 : k21), interpolator(clamp ? Math.max(0, Math.min(1, x3)) : x3));\n }\n scale3.domain = function(_) {\n return arguments.length ? ([x06, x12, x22] = _, t03 = transform3(x06 = +x06), t13 = transform3(x12 = +x12), t22 = transform3(x22 = +x22), k10 = t03 === t13 ? 0 : 0.5 / (t13 - t03), k21 = t13 === t22 ? 0 : 0.5 / (t22 - t13), s2 = t13 < t03 ? -1 : 1, scale3) : [x06, x12, x22];\n };\n scale3.clamp = function(_) {\n return arguments.length ? (clamp = !!_, scale3) : clamp;\n };\n scale3.interpolator = function(_) {\n return arguments.length ? (interpolator = _, scale3) : interpolator;\n };\n function range3(interpolate) {\n return function(_) {\n var r0, r1, r2;\n return arguments.length ? ([r0, r1, r2] = _, interpolator = piecewise(interpolate, [r0, r1, r2]), scale3) : [interpolator(0), interpolator(0.5), interpolator(1)];\n };\n }\n scale3.range = range3(value_default);\n scale3.rangeRound = range3(round_default);\n scale3.unknown = function(_) {\n return arguments.length ? (unknown = _, scale3) : unknown;\n };\n return function(t) {\n transform3 = t, t03 = t(x06), t13 = t(x12), t22 = t(x22), k10 = t03 === t13 ? 0 : 0.5 / (t13 - t03), k21 = t13 === t22 ? 0 : 0.5 / (t22 - t13), s2 = t13 < t03 ? -1 : 1;\n return scale3;\n };\n}\nfunction diverging() {\n var scale3 = linearish(transformer3()(identity4));\n scale3.copy = function() {\n return copy2(scale3, diverging());\n };\n return initInterpolator.apply(scale3, arguments);\n}\nfunction divergingLog() {\n var scale3 = loggish(transformer3()).domain([0.1, 1, 10]);\n scale3.copy = function() {\n return copy2(scale3, divergingLog()).base(scale3.base());\n };\n return initInterpolator.apply(scale3, arguments);\n}\nfunction divergingSymlog() {\n var scale3 = symlogish(transformer3());\n scale3.copy = function() {\n return copy2(scale3, divergingSymlog()).constant(scale3.constant());\n };\n return initInterpolator.apply(scale3, arguments);\n}\nfunction divergingPow() {\n var scale3 = powish(transformer3());\n scale3.copy = function() {\n return copy2(scale3, divergingPow()).exponent(scale3.exponent());\n };\n return initInterpolator.apply(scale3, arguments);\n}\n\n// ../../node_modules/d3-scale-chromatic/src/colors.js\nfunction colors_default(specifier) {\n var n = specifier.length / 6 | 0, colors = new Array(n), i = 0;\n while (i < n) colors[i] = \"#\" + specifier.slice(i * 6, ++i * 6);\n return colors;\n}\n\n// ../../node_modules/d3-scale-chromatic/src/categorical/category10.js\nvar category10_default = colors_default(\"1f77b4ff7f0e2ca02cd627289467bd8c564be377c27f7f7fbcbd2217becf\");\n\n// ../../node_modules/d3-scale-chromatic/src/categorical/Accent.js\nvar Accent_default = colors_default(\"7fc97fbeaed4fdc086ffff99386cb0f0027fbf5b17666666\");\n\n// ../../node_modules/d3-scale-chromatic/src/categorical/Dark2.js\nvar Dark2_default = colors_default(\"1b9e77d95f027570b3e7298a66a61ee6ab02a6761d666666\");\n\n// ../../node_modules/d3-scale-chromatic/src/categorical/observable10.js\nvar observable10_default = colors_default(\"4269d0efb118ff725c6cc5b03ca951ff8ab7a463f297bbf59c6b4e9498a0\");\n\n// ../../node_modules/d3-scale-chromatic/src/categorical/Paired.js\nvar Paired_default = colors_default(\"a6cee31f78b4b2df8a33a02cfb9a99e31a1cfdbf6fff7f00cab2d66a3d9affff99b15928\");\n\n// ../../node_modules/d3-scale-chromatic/src/categorical/Pastel1.js\nvar Pastel1_default = colors_default(\"fbb4aeb3cde3ccebc5decbe4fed9a6ffffcce5d8bdfddaecf2f2f2\");\n\n// ../../node_modules/d3-scale-chromatic/src/categorical/Pastel2.js\nvar Pastel2_default = colors_default(\"b3e2cdfdcdaccbd5e8f4cae4e6f5c9fff2aef1e2cccccccc\");\n\n// ../../node_modules/d3-scale-chromatic/src/categorical/Set1.js\nvar Set1_default = colors_default(\"e41a1c377eb84daf4a984ea3ff7f00ffff33a65628f781bf999999\");\n\n// ../../node_modules/d3-scale-chromatic/src/categorical/Set2.js\nvar Set2_default = colors_default(\"66c2a5fc8d628da0cbe78ac3a6d854ffd92fe5c494b3b3b3\");\n\n// ../../node_modules/d3-scale-chromatic/src/categorical/Set3.js\nvar Set3_default = colors_default(\"8dd3c7ffffb3bebadafb807280b1d3fdb462b3de69fccde5d9d9d9bc80bdccebc5ffed6f\");\n\n// ../../node_modules/d3-scale-chromatic/src/categorical/Tableau10.js\nvar Tableau10_default = colors_default(\"4e79a7f28e2ce1575976b7b259a14fedc949af7aa1ff9da79c755fbab0ab\");\n\n// ../../node_modules/d3-scale-chromatic/src/ramp.js\nvar ramp_default = (scheme28) => rgbBasis(scheme28[scheme28.length - 1]);\n\n// ../../node_modules/d3-scale-chromatic/src/diverging/BrBG.js\nvar scheme = new Array(3).concat(\n \"d8b365f5f5f55ab4ac\",\n \"a6611adfc27d80cdc1018571\",\n \"a6611adfc27df5f5f580cdc1018571\",\n \"8c510ad8b365f6e8c3c7eae55ab4ac01665e\",\n \"8c510ad8b365f6e8c3f5f5f5c7eae55ab4ac01665e\",\n \"8c510abf812ddfc27df6e8c3c7eae580cdc135978f01665e\",\n \"8c510abf812ddfc27df6e8c3f5f5f5c7eae580cdc135978f01665e\",\n \"5430058c510abf812ddfc27df6e8c3c7eae580cdc135978f01665e003c30\",\n \"5430058c510abf812ddfc27df6e8c3f5f5f5c7eae580cdc135978f01665e003c30\"\n).map(colors_default);\nvar BrBG_default = ramp_default(scheme);\n\n// ../../node_modules/d3-scale-chromatic/src/diverging/PRGn.js\nvar scheme2 = new Array(3).concat(\n \"af8dc3f7f7f77fbf7b\",\n \"7b3294c2a5cfa6dba0008837\",\n \"7b3294c2a5cff7f7f7a6dba0008837\",\n \"762a83af8dc3e7d4e8d9f0d37fbf7b1b7837\",\n \"762a83af8dc3e7d4e8f7f7f7d9f0d37fbf7b1b7837\",\n \"762a839970abc2a5cfe7d4e8d9f0d3a6dba05aae611b7837\",\n \"762a839970abc2a5cfe7d4e8f7f7f7d9f0d3a6dba05aae611b7837\",\n \"40004b762a839970abc2a5cfe7d4e8d9f0d3a6dba05aae611b783700441b\",\n \"40004b762a839970abc2a5cfe7d4e8f7f7f7d9f0d3a6dba05aae611b783700441b\"\n).map(colors_default);\nvar PRGn_default = ramp_default(scheme2);\n\n// ../../node_modules/d3-scale-chromatic/src/diverging/PiYG.js\nvar scheme3 = new Array(3).concat(\n \"e9a3c9f7f7f7a1d76a\",\n \"d01c8bf1b6dab8e1864dac26\",\n \"d01c8bf1b6daf7f7f7b8e1864dac26\",\n \"c51b7de9a3c9fde0efe6f5d0a1d76a4d9221\",\n \"c51b7de9a3c9fde0eff7f7f7e6f5d0a1d76a4d9221\",\n \"c51b7dde77aef1b6dafde0efe6f5d0b8e1867fbc414d9221\",\n \"c51b7dde77aef1b6dafde0eff7f7f7e6f5d0b8e1867fbc414d9221\",\n \"8e0152c51b7dde77aef1b6dafde0efe6f5d0b8e1867fbc414d9221276419\",\n \"8e0152c51b7dde77aef1b6dafde0eff7f7f7e6f5d0b8e1867fbc414d9221276419\"\n).map(colors_default);\nvar PiYG_default = ramp_default(scheme3);\n\n// ../../node_modules/d3-scale-chromatic/src/diverging/PuOr.js\nvar scheme4 = new Array(3).concat(\n \"998ec3f7f7f7f1a340\",\n \"5e3c99b2abd2fdb863e66101\",\n \"5e3c99b2abd2f7f7f7fdb863e66101\",\n \"542788998ec3d8daebfee0b6f1a340b35806\",\n \"542788998ec3d8daebf7f7f7fee0b6f1a340b35806\",\n \"5427888073acb2abd2d8daebfee0b6fdb863e08214b35806\",\n \"5427888073acb2abd2d8daebf7f7f7fee0b6fdb863e08214b35806\",\n \"2d004b5427888073acb2abd2d8daebfee0b6fdb863e08214b358067f3b08\",\n \"2d004b5427888073acb2abd2d8daebf7f7f7fee0b6fdb863e08214b358067f3b08\"\n).map(colors_default);\nvar PuOr_default = ramp_default(scheme4);\n\n// ../../node_modules/d3-scale-chromatic/src/diverging/RdBu.js\nvar scheme5 = new Array(3).concat(\n \"ef8a62f7f7f767a9cf\",\n \"ca0020f4a58292c5de0571b0\",\n \"ca0020f4a582f7f7f792c5de0571b0\",\n \"b2182bef8a62fddbc7d1e5f067a9cf2166ac\",\n \"b2182bef8a62fddbc7f7f7f7d1e5f067a9cf2166ac\",\n \"b2182bd6604df4a582fddbc7d1e5f092c5de4393c32166ac\",\n \"b2182bd6604df4a582fddbc7f7f7f7d1e5f092c5de4393c32166ac\",\n \"67001fb2182bd6604df4a582fddbc7d1e5f092c5de4393c32166ac053061\",\n \"67001fb2182bd6604df4a582fddbc7f7f7f7d1e5f092c5de4393c32166ac053061\"\n).map(colors_default);\nvar RdBu_default = ramp_default(scheme5);\n\n// ../../node_modules/d3-scale-chromatic/src/diverging/RdGy.js\nvar scheme6 = new Array(3).concat(\n \"ef8a62ffffff999999\",\n \"ca0020f4a582bababa404040\",\n \"ca0020f4a582ffffffbababa404040\",\n \"b2182bef8a62fddbc7e0e0e09999994d4d4d\",\n \"b2182bef8a62fddbc7ffffffe0e0e09999994d4d4d\",\n \"b2182bd6604df4a582fddbc7e0e0e0bababa8787874d4d4d\",\n \"b2182bd6604df4a582fddbc7ffffffe0e0e0bababa8787874d4d4d\",\n \"67001fb2182bd6604df4a582fddbc7e0e0e0bababa8787874d4d4d1a1a1a\",\n \"67001fb2182bd6604df4a582fddbc7ffffffe0e0e0bababa8787874d4d4d1a1a1a\"\n).map(colors_default);\nvar RdGy_default = ramp_default(scheme6);\n\n// ../../node_modules/d3-scale-chromatic/src/diverging/RdYlBu.js\nvar scheme7 = new Array(3).concat(\n \"fc8d59ffffbf91bfdb\",\n \"d7191cfdae61abd9e92c7bb6\",\n \"d7191cfdae61ffffbfabd9e92c7bb6\",\n \"d73027fc8d59fee090e0f3f891bfdb4575b4\",\n \"d73027fc8d59fee090ffffbfe0f3f891bfdb4575b4\",\n \"d73027f46d43fdae61fee090e0f3f8abd9e974add14575b4\",\n \"d73027f46d43fdae61fee090ffffbfe0f3f8abd9e974add14575b4\",\n \"a50026d73027f46d43fdae61fee090e0f3f8abd9e974add14575b4313695\",\n \"a50026d73027f46d43fdae61fee090ffffbfe0f3f8abd9e974add14575b4313695\"\n).map(colors_default);\nvar RdYlBu_default = ramp_default(scheme7);\n\n// ../../node_modules/d3-scale-chromatic/src/diverging/RdYlGn.js\nvar scheme8 = new Array(3).concat(\n \"fc8d59ffffbf91cf60\",\n \"d7191cfdae61a6d96a1a9641\",\n \"d7191cfdae61ffffbfa6d96a1a9641\",\n \"d73027fc8d59fee08bd9ef8b91cf601a9850\",\n \"d73027fc8d59fee08bffffbfd9ef8b91cf601a9850\",\n \"d73027f46d43fdae61fee08bd9ef8ba6d96a66bd631a9850\",\n \"d73027f46d43fdae61fee08bffffbfd9ef8ba6d96a66bd631a9850\",\n \"a50026d73027f46d43fdae61fee08bd9ef8ba6d96a66bd631a9850006837\",\n \"a50026d73027f46d43fdae61fee08bffffbfd9ef8ba6d96a66bd631a9850006837\"\n).map(colors_default);\nvar RdYlGn_default = ramp_default(scheme8);\n\n// ../../node_modules/d3-scale-chromatic/src/diverging/Spectral.js\nvar scheme9 = new Array(3).concat(\n \"fc8d59ffffbf99d594\",\n \"d7191cfdae61abdda42b83ba\",\n \"d7191cfdae61ffffbfabdda42b83ba\",\n \"d53e4ffc8d59fee08be6f59899d5943288bd\",\n \"d53e4ffc8d59fee08bffffbfe6f59899d5943288bd\",\n \"d53e4ff46d43fdae61fee08be6f598abdda466c2a53288bd\",\n \"d53e4ff46d43fdae61fee08bffffbfe6f598abdda466c2a53288bd\",\n \"9e0142d53e4ff46d43fdae61fee08be6f598abdda466c2a53288bd5e4fa2\",\n \"9e0142d53e4ff46d43fdae61fee08bffffbfe6f598abdda466c2a53288bd5e4fa2\"\n).map(colors_default);\nvar Spectral_default = ramp_default(scheme9);\n\n// ../../node_modules/d3-scale-chromatic/src/sequential-multi/BuGn.js\nvar scheme10 = new Array(3).concat(\n \"e5f5f999d8c92ca25f\",\n \"edf8fbb2e2e266c2a4238b45\",\n \"edf8fbb2e2e266c2a42ca25f006d2c\",\n \"edf8fbccece699d8c966c2a42ca25f006d2c\",\n \"edf8fbccece699d8c966c2a441ae76238b45005824\",\n \"f7fcfde5f5f9ccece699d8c966c2a441ae76238b45005824\",\n \"f7fcfde5f5f9ccece699d8c966c2a441ae76238b45006d2c00441b\"\n).map(colors_default);\nvar BuGn_default = ramp_default(scheme10);\n\n// ../../node_modules/d3-scale-chromatic/src/sequential-multi/BuPu.js\nvar scheme11 = new Array(3).concat(\n \"e0ecf49ebcda8856a7\",\n \"edf8fbb3cde38c96c688419d\",\n \"edf8fbb3cde38c96c68856a7810f7c\",\n \"edf8fbbfd3e69ebcda8c96c68856a7810f7c\",\n \"edf8fbbfd3e69ebcda8c96c68c6bb188419d6e016b\",\n \"f7fcfde0ecf4bfd3e69ebcda8c96c68c6bb188419d6e016b\",\n \"f7fcfde0ecf4bfd3e69ebcda8c96c68c6bb188419d810f7c4d004b\"\n).map(colors_default);\nvar BuPu_default = ramp_default(scheme11);\n\n// ../../node_modules/d3-scale-chromatic/src/sequential-multi/GnBu.js\nvar scheme12 = new Array(3).concat(\n \"e0f3dba8ddb543a2ca\",\n \"f0f9e8bae4bc7bccc42b8cbe\",\n \"f0f9e8bae4bc7bccc443a2ca0868ac\",\n \"f0f9e8ccebc5a8ddb57bccc443a2ca0868ac\",\n \"f0f9e8ccebc5a8ddb57bccc44eb3d32b8cbe08589e\",\n \"f7fcf0e0f3dbccebc5a8ddb57bccc44eb3d32b8cbe08589e\",\n \"f7fcf0e0f3dbccebc5a8ddb57bccc44eb3d32b8cbe0868ac084081\"\n).map(colors_default);\nvar GnBu_default = ramp_default(scheme12);\n\n// ../../node_modules/d3-scale-chromatic/src/sequential-multi/OrRd.js\nvar scheme13 = new Array(3).concat(\n \"fee8c8fdbb84e34a33\",\n \"fef0d9fdcc8afc8d59d7301f\",\n \"fef0d9fdcc8afc8d59e34a33b30000\",\n \"fef0d9fdd49efdbb84fc8d59e34a33b30000\",\n \"fef0d9fdd49efdbb84fc8d59ef6548d7301f990000\",\n \"fff7ecfee8c8fdd49efdbb84fc8d59ef6548d7301f990000\",\n \"fff7ecfee8c8fdd49efdbb84fc8d59ef6548d7301fb300007f0000\"\n).map(colors_default);\nvar OrRd_default = ramp_default(scheme13);\n\n// ../../node_modules/d3-scale-chromatic/src/sequential-multi/PuBuGn.js\nvar scheme14 = new Array(3).concat(\n \"ece2f0a6bddb1c9099\",\n \"f6eff7bdc9e167a9cf02818a\",\n \"f6eff7bdc9e167a9cf1c9099016c59\",\n \"f6eff7d0d1e6a6bddb67a9cf1c9099016c59\",\n \"f6eff7d0d1e6a6bddb67a9cf3690c002818a016450\",\n \"fff7fbece2f0d0d1e6a6bddb67a9cf3690c002818a016450\",\n \"fff7fbece2f0d0d1e6a6bddb67a9cf3690c002818a016c59014636\"\n).map(colors_default);\nvar PuBuGn_default = ramp_default(scheme14);\n\n// ../../node_modules/d3-scale-chromatic/src/sequential-multi/PuBu.js\nvar scheme15 = new Array(3).concat(\n \"ece7f2a6bddb2b8cbe\",\n \"f1eef6bdc9e174a9cf0570b0\",\n \"f1eef6bdc9e174a9cf2b8cbe045a8d\",\n \"f1eef6d0d1e6a6bddb74a9cf2b8cbe045a8d\",\n \"f1eef6d0d1e6a6bddb74a9cf3690c00570b0034e7b\",\n \"fff7fbece7f2d0d1e6a6bddb74a9cf3690c00570b0034e7b\",\n \"fff7fbece7f2d0d1e6a6bddb74a9cf3690c00570b0045a8d023858\"\n).map(colors_default);\nvar PuBu_default = ramp_default(scheme15);\n\n// ../../node_modules/d3-scale-chromatic/src/sequential-multi/PuRd.js\nvar scheme16 = new Array(3).concat(\n \"e7e1efc994c7dd1c77\",\n \"f1eef6d7b5d8df65b0ce1256\",\n \"f1eef6d7b5d8df65b0dd1c77980043\",\n \"f1eef6d4b9dac994c7df65b0dd1c77980043\",\n \"f1eef6d4b9dac994c7df65b0e7298ace125691003f\",\n \"f7f4f9e7e1efd4b9dac994c7df65b0e7298ace125691003f\",\n \"f7f4f9e7e1efd4b9dac994c7df65b0e7298ace125698004367001f\"\n).map(colors_default);\nvar PuRd_default = ramp_default(scheme16);\n\n// ../../node_modules/d3-scale-chromatic/src/sequential-multi/RdPu.js\nvar scheme17 = new Array(3).concat(\n \"fde0ddfa9fb5c51b8a\",\n \"feebe2fbb4b9f768a1ae017e\",\n \"feebe2fbb4b9f768a1c51b8a7a0177\",\n \"feebe2fcc5c0fa9fb5f768a1c51b8a7a0177\",\n \"feebe2fcc5c0fa9fb5f768a1dd3497ae017e7a0177\",\n \"fff7f3fde0ddfcc5c0fa9fb5f768a1dd3497ae017e7a0177\",\n \"fff7f3fde0ddfcc5c0fa9fb5f768a1dd3497ae017e7a017749006a\"\n).map(colors_default);\nvar RdPu_default = ramp_default(scheme17);\n\n// ../../node_modules/d3-scale-chromatic/src/sequential-multi/YlGnBu.js\nvar scheme18 = new Array(3).concat(\n \"edf8b17fcdbb2c7fb8\",\n \"ffffcca1dab441b6c4225ea8\",\n \"ffffcca1dab441b6c42c7fb8253494\",\n \"ffffccc7e9b47fcdbb41b6c42c7fb8253494\",\n \"ffffccc7e9b47fcdbb41b6c41d91c0225ea80c2c84\",\n \"ffffd9edf8b1c7e9b47fcdbb41b6c41d91c0225ea80c2c84\",\n \"ffffd9edf8b1c7e9b47fcdbb41b6c41d91c0225ea8253494081d58\"\n).map(colors_default);\nvar YlGnBu_default = ramp_default(scheme18);\n\n// ../../node_modules/d3-scale-chromatic/src/sequential-multi/YlGn.js\nvar scheme19 = new Array(3).concat(\n \"f7fcb9addd8e31a354\",\n \"ffffccc2e69978c679238443\",\n \"ffffccc2e69978c67931a354006837\",\n \"ffffccd9f0a3addd8e78c67931a354006837\",\n \"ffffccd9f0a3addd8e78c67941ab5d238443005a32\",\n \"ffffe5f7fcb9d9f0a3addd8e78c67941ab5d238443005a32\",\n \"ffffe5f7fcb9d9f0a3addd8e78c67941ab5d238443006837004529\"\n).map(colors_default);\nvar YlGn_default = ramp_default(scheme19);\n\n// ../../node_modules/d3-scale-chromatic/src/sequential-multi/YlOrBr.js\nvar scheme20 = new Array(3).concat(\n \"fff7bcfec44fd95f0e\",\n \"ffffd4fed98efe9929cc4c02\",\n \"ffffd4fed98efe9929d95f0e993404\",\n \"ffffd4fee391fec44ffe9929d95f0e993404\",\n \"ffffd4fee391fec44ffe9929ec7014cc4c028c2d04\",\n \"ffffe5fff7bcfee391fec44ffe9929ec7014cc4c028c2d04\",\n \"ffffe5fff7bcfee391fec44ffe9929ec7014cc4c02993404662506\"\n).map(colors_default);\nvar YlOrBr_default = ramp_default(scheme20);\n\n// ../../node_modules/d3-scale-chromatic/src/sequential-multi/YlOrRd.js\nvar scheme21 = new Array(3).concat(\n \"ffeda0feb24cf03b20\",\n \"ffffb2fecc5cfd8d3ce31a1c\",\n \"ffffb2fecc5cfd8d3cf03b20bd0026\",\n \"ffffb2fed976feb24cfd8d3cf03b20bd0026\",\n \"ffffb2fed976feb24cfd8d3cfc4e2ae31a1cb10026\",\n \"ffffccffeda0fed976feb24cfd8d3cfc4e2ae31a1cb10026\",\n \"ffffccffeda0fed976feb24cfd8d3cfc4e2ae31a1cbd0026800026\"\n).map(colors_default);\nvar YlOrRd_default = ramp_default(scheme21);\n\n// ../../node_modules/d3-scale-chromatic/src/sequential-single/Blues.js\nvar scheme22 = new Array(3).concat(\n \"deebf79ecae13182bd\",\n \"eff3ffbdd7e76baed62171b5\",\n \"eff3ffbdd7e76baed63182bd08519c\",\n \"eff3ffc6dbef9ecae16baed63182bd08519c\",\n \"eff3ffc6dbef9ecae16baed64292c62171b5084594\",\n \"f7fbffdeebf7c6dbef9ecae16baed64292c62171b5084594\",\n \"f7fbffdeebf7c6dbef9ecae16baed64292c62171b508519c08306b\"\n).map(colors_default);\nvar Blues_default = ramp_default(scheme22);\n\n// ../../node_modules/d3-scale-chromatic/src/sequential-single/Greens.js\nvar scheme23 = new Array(3).concat(\n \"e5f5e0a1d99b31a354\",\n \"edf8e9bae4b374c476238b45\",\n \"edf8e9bae4b374c47631a354006d2c\",\n \"edf8e9c7e9c0a1d99b74c47631a354006d2c\",\n \"edf8e9c7e9c0a1d99b74c47641ab5d238b45005a32\",\n \"f7fcf5e5f5e0c7e9c0a1d99b74c47641ab5d238b45005a32\",\n \"f7fcf5e5f5e0c7e9c0a1d99b74c47641ab5d238b45006d2c00441b\"\n).map(colors_default);\nvar Greens_default = ramp_default(scheme23);\n\n// ../../node_modules/d3-scale-chromatic/src/sequential-single/Greys.js\nvar scheme24 = new Array(3).concat(\n \"f0f0f0bdbdbd636363\",\n \"f7f7f7cccccc969696525252\",\n \"f7f7f7cccccc969696636363252525\",\n \"f7f7f7d9d9d9bdbdbd969696636363252525\",\n \"f7f7f7d9d9d9bdbdbd969696737373525252252525\",\n \"fffffff0f0f0d9d9d9bdbdbd969696737373525252252525\",\n \"fffffff0f0f0d9d9d9bdbdbd969696737373525252252525000000\"\n).map(colors_default);\nvar Greys_default = ramp_default(scheme24);\n\n// ../../node_modules/d3-scale-chromatic/src/sequential-single/Purples.js\nvar scheme25 = new Array(3).concat(\n \"efedf5bcbddc756bb1\",\n \"f2f0f7cbc9e29e9ac86a51a3\",\n \"f2f0f7cbc9e29e9ac8756bb154278f\",\n \"f2f0f7dadaebbcbddc9e9ac8756bb154278f\",\n \"f2f0f7dadaebbcbddc9e9ac8807dba6a51a34a1486\",\n \"fcfbfdefedf5dadaebbcbddc9e9ac8807dba6a51a34a1486\",\n \"fcfbfdefedf5dadaebbcbddc9e9ac8807dba6a51a354278f3f007d\"\n).map(colors_default);\nvar Purples_default = ramp_default(scheme25);\n\n// ../../node_modules/d3-scale-chromatic/src/sequential-single/Reds.js\nvar scheme26 = new Array(3).concat(\n \"fee0d2fc9272de2d26\",\n \"fee5d9fcae91fb6a4acb181d\",\n \"fee5d9fcae91fb6a4ade2d26a50f15\",\n \"fee5d9fcbba1fc9272fb6a4ade2d26a50f15\",\n \"fee5d9fcbba1fc9272fb6a4aef3b2ccb181d99000d\",\n \"fff5f0fee0d2fcbba1fc9272fb6a4aef3b2ccb181d99000d\",\n \"fff5f0fee0d2fcbba1fc9272fb6a4aef3b2ccb181da50f1567000d\"\n).map(colors_default);\nvar Reds_default = ramp_default(scheme26);\n\n// ../../node_modules/d3-scale-chromatic/src/sequential-single/Oranges.js\nvar scheme27 = new Array(3).concat(\n \"fee6cefdae6be6550d\",\n \"feeddefdbe85fd8d3cd94701\",\n \"feeddefdbe85fd8d3ce6550da63603\",\n \"feeddefdd0a2fdae6bfd8d3ce6550da63603\",\n \"feeddefdd0a2fdae6bfd8d3cf16913d948018c2d04\",\n \"fff5ebfee6cefdd0a2fdae6bfd8d3cf16913d948018c2d04\",\n \"fff5ebfee6cefdd0a2fdae6bfd8d3cf16913d94801a636037f2704\"\n).map(colors_default);\nvar Oranges_default = ramp_default(scheme27);\n\n// ../../node_modules/d3-scale-chromatic/src/sequential-multi/cividis.js\nfunction cividis_default(t) {\n t = Math.max(0, Math.min(1, t));\n return \"rgb(\" + Math.max(0, Math.min(255, Math.round(-4.54 - t * (35.34 - t * (2381.73 - t * (6402.7 - t * (7024.72 - t * 2710.57))))))) + \", \" + Math.max(0, Math.min(255, Math.round(32.49 + t * (170.73 + t * (52.82 - t * (131.46 - t * (176.58 - t * 67.37))))))) + \", \" + Math.max(0, Math.min(255, Math.round(81.24 + t * (442.36 - t * (2482.43 - t * (6167.24 - t * (6614.94 - t * 2475.67))))))) + \")\";\n}\n\n// ../../node_modules/d3-scale-chromatic/src/sequential-multi/cubehelix.js\nvar cubehelix_default2 = cubehelixLong(cubehelix(300, 0.5, 0), cubehelix(-240, 0.5, 1));\n\n// ../../node_modules/d3-scale-chromatic/src/sequential-multi/rainbow.js\nvar warm = cubehelixLong(cubehelix(-100, 0.75, 0.35), cubehelix(80, 1.5, 0.8));\nvar cool = cubehelixLong(cubehelix(260, 0.75, 0.35), cubehelix(80, 1.5, 0.8));\nvar c = cubehelix();\nfunction rainbow_default(t) {\n if (t < 0 || t > 1) t -= Math.floor(t);\n var ts = Math.abs(t - 0.5);\n c.h = 360 * t - 100;\n c.s = 1.5 - 1.5 * ts;\n c.l = 0.8 - 0.9 * ts;\n return c + \"\";\n}\n\n// ../../node_modules/d3-scale-chromatic/src/sequential-multi/sinebow.js\nvar c2 = rgb();\nvar pi_1_3 = Math.PI / 3;\nvar pi_2_3 = Math.PI * 2 / 3;\nfunction sinebow_default(t) {\n var x3;\n t = (0.5 - t) * Math.PI;\n c2.r = 255 * (x3 = Math.sin(t)) * x3;\n c2.g = 255 * (x3 = Math.sin(t + pi_1_3)) * x3;\n c2.b = 255 * (x3 = Math.sin(t + pi_2_3)) * x3;\n return c2 + \"\";\n}\n\n// ../../node_modules/d3-scale-chromatic/src/sequential-multi/turbo.js\nfunction turbo_default(t) {\n t = Math.max(0, Math.min(1, t));\n return \"rgb(\" + Math.max(0, Math.min(255, Math.round(34.61 + t * (1172.33 - t * (10793.56 - t * (33300.12 - t * (38394.49 - t * 14825.05))))))) + \", \" + Math.max(0, Math.min(255, Math.round(23.31 + t * (557.33 + t * (1225.33 - t * (3574.96 - t * (1073.77 + t * 707.56))))))) + \", \" + Math.max(0, Math.min(255, Math.round(27.2 + t * (3211.1 - t * (15327.97 - t * (27814 - t * (22569.18 - t * 6838.66))))))) + \")\";\n}\n\n// ../../node_modules/d3-scale-chromatic/src/sequential-multi/viridis.js\nfunction ramp(range3) {\n var n = range3.length;\n return function(t) {\n return range3[Math.max(0, Math.min(n - 1, Math.floor(t * n)))];\n };\n}\nvar viridis_default = ramp(colors_default(\"44015444025645045745055946075a46085c460a5d460b5e470d60470e6147106347116447136548146748166848176948186a481a6c481b6d481c6e481d6f481f70482071482173482374482475482576482677482878482979472a7a472c7a472d7b472e7c472f7d46307e46327e46337f463480453581453781453882443983443a83443b84433d84433e85423f854240864241864142874144874045884046883f47883f48893e49893e4a893e4c8a3d4d8a3d4e8a3c4f8a3c508b3b518b3b528b3a538b3a548c39558c39568c38588c38598c375a8c375b8d365c8d365d8d355e8d355f8d34608d34618d33628d33638d32648e32658e31668e31678e31688e30698e306a8e2f6b8e2f6c8e2e6d8e2e6e8e2e6f8e2d708e2d718e2c718e2c728e2c738e2b748e2b758e2a768e2a778e2a788e29798e297a8e297b8e287c8e287d8e277e8e277f8e27808e26818e26828e26828e25838e25848e25858e24868e24878e23888e23898e238a8d228b8d228c8d228d8d218e8d218f8d21908d21918c20928c20928c20938c1f948c1f958b1f968b1f978b1f988b1f998a1f9a8a1e9b8a1e9c891e9d891f9e891f9f881fa0881fa1881fa1871fa28720a38620a48621a58521a68522a78522a88423a98324aa8325ab8225ac8226ad8127ad8128ae8029af7f2ab07f2cb17e2db27d2eb37c2fb47c31b57b32b67a34b67935b77937b87838b9773aba763bbb753dbc743fbc7340bd7242be7144bf7046c06f48c16e4ac16d4cc26c4ec36b50c46a52c56954c56856c66758c7655ac8645cc8635ec96260ca6063cb5f65cb5e67cc5c69cd5b6ccd5a6ece5870cf5773d05675d05477d1537ad1517cd2507fd34e81d34d84d44b86d54989d5488bd6468ed64590d74393d74195d84098d83e9bd93c9dd93ba0da39a2da37a5db36a8db34aadc32addc30b0dd2fb2dd2db5de2bb8de29bade28bddf26c0df25c2df23c5e021c8e020cae11fcde11dd0e11cd2e21bd5e21ad8e219dae319dde318dfe318e2e418e5e419e7e419eae51aece51befe51cf1e51df4e61ef6e620f8e621fbe723fde725\"));\nvar magma = ramp(colors_default(\"00000401000501010601010802010902020b02020d03030f03031204041405041606051806051a07061c08071e0907200a08220b09240c09260d0a290e0b2b100b2d110c2f120d31130d34140e36150e38160f3b180f3d19103f1a10421c10441d11471e114920114b21114e22115024125325125527125829115a2a115c2c115f2d11612f116331116533106734106936106b38106c390f6e3b0f703d0f713f0f72400f74420f75440f764510774710784910784a10794c117a4e117b4f127b51127c52137c54137d56147d57157e59157e5a167e5c167f5d177f5f187f601880621980641a80651a80671b80681c816a1c816b1d816d1d816e1e81701f81721f817320817521817621817822817922827b23827c23827e24828025828125818326818426818627818827818928818b29818c29818e2a81902a81912b81932b80942c80962c80982d80992d809b2e7f9c2e7f9e2f7fa02f7fa1307ea3307ea5317ea6317da8327daa337dab337cad347cae347bb0357bb2357bb3367ab5367ab73779b83779ba3878bc3978bd3977bf3a77c03a76c23b75c43c75c53c74c73d73c83e73ca3e72cc3f71cd4071cf4070d0416fd2426fd3436ed5446dd6456cd8456cd9466bdb476adc4869de4968df4a68e04c67e24d66e34e65e44f64e55064e75263e85362e95462ea5661eb5760ec5860ed5a5fee5b5eef5d5ef05f5ef1605df2625df2645cf3655cf4675cf4695cf56b5cf66c5cf66e5cf7705cf7725cf8745cf8765cf9785df9795df97b5dfa7d5efa7f5efa815ffb835ffb8560fb8761fc8961fc8a62fc8c63fc8e64fc9065fd9266fd9467fd9668fd9869fd9a6afd9b6bfe9d6cfe9f6dfea16efea36ffea571fea772fea973feaa74feac76feae77feb078feb27afeb47bfeb67cfeb77efeb97ffebb81febd82febf84fec185fec287fec488fec68afec88cfeca8dfecc8ffecd90fecf92fed194fed395fed597fed799fed89afdda9cfddc9efddea0fde0a1fde2a3fde3a5fde5a7fde7a9fde9aafdebacfcecaefceeb0fcf0b2fcf2b4fcf4b6fcf6b8fcf7b9fcf9bbfcfbbdfcfdbf\"));\nvar inferno = ramp(colors_default(\"00000401000501010601010802010a02020c02020e03021004031204031405041706041907051b08051d09061f0a07220b07240c08260d08290e092b10092d110a30120a32140b34150b37160b39180c3c190c3e1b0c411c0c431e0c451f0c48210c4a230c4c240c4f260c51280b53290b552b0b572d0b592f0a5b310a5c320a5e340a5f3609613809623909633b09643d09653e0966400a67420a68440a68450a69470b6a490b6a4a0c6b4c0c6b4d0d6c4f0d6c510e6c520e6d540f6d550f6d57106e59106e5a116e5c126e5d126e5f136e61136e62146e64156e65156e67166e69166e6a176e6c186e6d186e6f196e71196e721a6e741a6e751b6e771c6d781c6d7a1d6d7c1d6d7d1e6d7f1e6c801f6c82206c84206b85216b87216b88226a8a226a8c23698d23698f24699025689225689326679526679727669827669a28659b29649d29649f2a63a02a63a22b62a32c61a52c60a62d60a82e5fa92e5eab2f5ead305dae305cb0315bb1325ab3325ab43359b63458b73557b93556ba3655bc3754bd3853bf3952c03a51c13a50c33b4fc43c4ec63d4dc73e4cc83f4bca404acb4149cc4248ce4347cf4446d04545d24644d34743d44842d54a41d74b3fd84c3ed94d3dda4e3cdb503bdd513ade5238df5337e05536e15635e25734e35933e45a31e55c30e65d2fe75e2ee8602de9612bea632aeb6429eb6628ec6726ed6925ee6a24ef6c23ef6e21f06f20f1711ff1731df2741cf3761bf37819f47918f57b17f57d15f67e14f68013f78212f78410f8850ff8870ef8890cf98b0bf98c0af98e09fa9008fa9207fa9407fb9606fb9706fb9906fb9b06fb9d07fc9f07fca108fca309fca50afca60cfca80dfcaa0ffcac11fcae12fcb014fcb216fcb418fbb61afbb81dfbba1ffbbc21fbbe23fac026fac228fac42afac62df9c72ff9c932f9cb35f8cd37f8cf3af7d13df7d340f6d543f6d746f5d949f5db4cf4dd4ff4df53f4e156f3e35af3e55df2e661f2e865f2ea69f1ec6df1ed71f1ef75f1f179f2f27df2f482f3f586f3f68af4f88ef5f992f6fa96f8fb9af9fc9dfafda1fcffa4\"));\nvar plasma = ramp(colors_default(\"0d088710078813078916078a19068c1b068d1d068e20068f2206902406912605912805922a05932c05942e05952f059631059733059735049837049938049a3a049a3c049b3e049c3f049c41049d43039e44039e46039f48039f4903a04b03a14c02a14e02a25002a25102a35302a35502a45601a45801a45901a55b01a55c01a65e01a66001a66100a76300a76400a76600a76700a86900a86a00a86c00a86e00a86f00a87100a87201a87401a87501a87701a87801a87a02a87b02a87d03a87e03a88004a88104a78305a78405a78606a68707a68808a68a09a58b0aa58d0ba58e0ca48f0da4910ea3920fa39410a29511a19613a19814a099159f9a169f9c179e9d189d9e199da01a9ca11b9ba21d9aa31e9aa51f99a62098a72197a82296aa2395ab2494ac2694ad2793ae2892b02991b12a90b22b8fb32c8eb42e8db52f8cb6308bb7318ab83289ba3388bb3488bc3587bd3786be3885bf3984c03a83c13b82c23c81c33d80c43e7fc5407ec6417dc7427cc8437bc9447aca457acb4679cc4778cc4977cd4a76ce4b75cf4c74d04d73d14e72d24f71d35171d45270d5536fd5546ed6556dd7566cd8576bd9586ada5a6ada5b69db5c68dc5d67dd5e66de5f65de6164df6263e06363e16462e26561e26660e3685fe4695ee56a5de56b5de66c5ce76e5be76f5ae87059e97158e97257ea7457eb7556eb7655ec7754ed7953ed7a52ee7b51ef7c51ef7e50f07f4ff0804ef1814df1834cf2844bf3854bf3874af48849f48948f58b47f58c46f68d45f68f44f79044f79143f79342f89441f89540f9973ff9983ef99a3efa9b3dfa9c3cfa9e3bfb9f3afba139fba238fca338fca537fca636fca835fca934fdab33fdac33fdae32fdaf31fdb130fdb22ffdb42ffdb52efeb72dfeb82cfeba2cfebb2bfebd2afebe2afec029fdc229fdc328fdc527fdc627fdc827fdca26fdcb26fccd25fcce25fcd025fcd225fbd324fbd524fbd724fad824fada24f9dc24f9dd25f8df25f8e125f7e225f7e425f6e626f6e826f5e926f5eb27f4ed27f3ee27f3f027f2f227f1f426f1f525f0f724f0f921\"));\n\n// ../../node_modules/d3-shape/src/constant.js\nfunction constant_default5(x3) {\n return function constant2() {\n return x3;\n };\n}\n\n// ../../node_modules/d3-shape/src/math.js\nvar cos2 = Math.cos;\nvar min4 = Math.min;\nvar sin2 = Math.sin;\nvar sqrt3 = Math.sqrt;\nvar epsilon7 = 1e-12;\nvar pi3 = Math.PI;\nvar halfPi2 = pi3 / 2;\nvar tau4 = 2 * pi3;\n\n// ../../node_modules/d3-shape/src/path.js\nfunction withPath(shape) {\n let digits = 3;\n shape.digits = function(_) {\n if (!arguments.length) return digits;\n if (_ == null) {\n digits = null;\n } else {\n const d = Math.floor(_);\n if (!(d >= 0)) throw new RangeError(`invalid digits: ${_}`);\n digits = d;\n }\n return shape;\n };\n return () => new Path(digits);\n}\n\n// ../../node_modules/d3-shape/src/array.js\nvar slice2 = Array.prototype.slice;\nfunction array_default(x3) {\n return typeof x3 === \"object\" && \"length\" in x3 ? x3 : Array.from(x3);\n}\n\n// ../../node_modules/d3-shape/src/curve/linear.js\nfunction Linear(context) {\n this._context = context;\n}\nLinear.prototype = {\n areaStart: function() {\n this._line = 0;\n },\n areaEnd: function() {\n this._line = NaN;\n },\n lineStart: function() {\n this._point = 0;\n },\n lineEnd: function() {\n if (this._line || this._line !== 0 && this._point === 1) this._context.closePath();\n this._line = 1 - this._line;\n },\n point: function(x3, y3) {\n x3 = +x3, y3 = +y3;\n switch (this._point) {\n case 0:\n this._point = 1;\n this._line ? this._context.lineTo(x3, y3) : this._context.moveTo(x3, y3);\n break;\n case 1:\n this._point = 2;\n // falls through\n default:\n this._context.lineTo(x3, y3);\n break;\n }\n }\n};\nfunction linear_default(context) {\n return new Linear(context);\n}\n\n// ../../node_modules/d3-shape/src/point.js\nfunction x2(p) {\n return p[0];\n}\nfunction y2(p) {\n return p[1];\n}\n\n// ../../node_modules/d3-shape/src/line.js\nfunction line_default2(x3, y3) {\n var defined2 = constant_default5(true), context = null, curve = linear_default, output = null, path2 = withPath(line3);\n x3 = typeof x3 === \"function\" ? x3 : x3 === void 0 ? x2 : constant_default5(x3);\n y3 = typeof y3 === \"function\" ? y3 : y3 === void 0 ? y2 : constant_default5(y3);\n function line3(data) {\n var i, n = (data = array_default(data)).length, d, defined0 = false, buffer2;\n if (context == null) output = curve(buffer2 = path2());\n for (i = 0; i <= n; ++i) {\n if (!(i < n && defined2(d = data[i], i, data)) === defined0) {\n if (defined0 = !defined0) output.lineStart();\n else output.lineEnd();\n }\n if (defined0) output.point(+x3(d, i, data), +y3(d, i, data));\n }\n if (buffer2) return output = null, buffer2 + \"\" || null;\n }\n line3.x = function(_) {\n return arguments.length ? (x3 = typeof _ === \"function\" ? _ : constant_default5(+_), line3) : x3;\n };\n line3.y = function(_) {\n return arguments.length ? (y3 = typeof _ === \"function\" ? _ : constant_default5(+_), line3) : y3;\n };\n line3.defined = function(_) {\n return arguments.length ? (defined2 = typeof _ === \"function\" ? _ : constant_default5(!!_), line3) : defined2;\n };\n line3.curve = function(_) {\n return arguments.length ? (curve = _, context != null && (output = curve(context)), line3) : curve;\n };\n line3.context = function(_) {\n return arguments.length ? (_ == null ? context = output = null : output = curve(context = _), line3) : context;\n };\n return line3;\n}\n\n// ../../node_modules/d3-shape/src/area.js\nfunction area_default3(x06, y06, y12) {\n var x12 = null, defined2 = constant_default5(true), context = null, curve = linear_default, output = null, path2 = withPath(area3);\n x06 = typeof x06 === \"function\" ? x06 : x06 === void 0 ? x2 : constant_default5(+x06);\n y06 = typeof y06 === \"function\" ? y06 : y06 === void 0 ? constant_default5(0) : constant_default5(+y06);\n y12 = typeof y12 === \"function\" ? y12 : y12 === void 0 ? y2 : constant_default5(+y12);\n function area3(data) {\n var i, j, k2, n = (data = array_default(data)).length, d, defined0 = false, buffer2, x0z = new Array(n), y0z = new Array(n);\n if (context == null) output = curve(buffer2 = path2());\n for (i = 0; i <= n; ++i) {\n if (!(i < n && defined2(d = data[i], i, data)) === defined0) {\n if (defined0 = !defined0) {\n j = i;\n output.areaStart();\n output.lineStart();\n } else {\n output.lineEnd();\n output.lineStart();\n for (k2 = i - 1; k2 >= j; --k2) {\n output.point(x0z[k2], y0z[k2]);\n }\n output.lineEnd();\n output.areaEnd();\n }\n }\n if (defined0) {\n x0z[i] = +x06(d, i, data), y0z[i] = +y06(d, i, data);\n output.point(x12 ? +x12(d, i, data) : x0z[i], y12 ? +y12(d, i, data) : y0z[i]);\n }\n }\n if (buffer2) return output = null, buffer2 + \"\" || null;\n }\n function arealine() {\n return line_default2().defined(defined2).curve(curve).context(context);\n }\n area3.x = function(_) {\n return arguments.length ? (x06 = typeof _ === \"function\" ? _ : constant_default5(+_), x12 = null, area3) : x06;\n };\n area3.x0 = function(_) {\n return arguments.length ? (x06 = typeof _ === \"function\" ? _ : constant_default5(+_), area3) : x06;\n };\n area3.x1 = function(_) {\n return arguments.length ? (x12 = _ == null ? null : typeof _ === \"function\" ? _ : constant_default5(+_), area3) : x12;\n };\n area3.y = function(_) {\n return arguments.length ? (y06 = typeof _ === \"function\" ? _ : constant_default5(+_), y12 = null, area3) : y06;\n };\n area3.y0 = function(_) {\n return arguments.length ? (y06 = typeof _ === \"function\" ? _ : constant_default5(+_), area3) : y06;\n };\n area3.y1 = function(_) {\n return arguments.length ? (y12 = _ == null ? null : typeof _ === \"function\" ? _ : constant_default5(+_), area3) : y12;\n };\n area3.lineX0 = area3.lineY0 = function() {\n return arealine().x(x06).y(y06);\n };\n area3.lineY1 = function() {\n return arealine().x(x06).y(y12);\n };\n area3.lineX1 = function() {\n return arealine().x(x12).y(y06);\n };\n area3.defined = function(_) {\n return arguments.length ? (defined2 = typeof _ === \"function\" ? _ : constant_default5(!!_), area3) : defined2;\n };\n area3.curve = function(_) {\n return arguments.length ? (curve = _, context != null && (output = curve(context)), area3) : curve;\n };\n area3.context = function(_) {\n return arguments.length ? (_ == null ? context = output = null : output = curve(context = _), area3) : context;\n };\n return area3;\n}\n\n// ../../node_modules/d3-shape/src/curve/bump.js\nvar Bump = class {\n constructor(context, x3) {\n this._context = context;\n this._x = x3;\n }\n areaStart() {\n this._line = 0;\n }\n areaEnd() {\n this._line = NaN;\n }\n lineStart() {\n this._point = 0;\n }\n lineEnd() {\n if (this._line || this._line !== 0 && this._point === 1) this._context.closePath();\n this._line = 1 - this._line;\n }\n point(x3, y3) {\n x3 = +x3, y3 = +y3;\n switch (this._point) {\n case 0: {\n this._point = 1;\n if (this._line) this._context.lineTo(x3, y3);\n else this._context.moveTo(x3, y3);\n break;\n }\n case 1:\n this._point = 2;\n // falls through\n default: {\n if (this._x) this._context.bezierCurveTo(this._x0 = (this._x0 + x3) / 2, this._y0, this._x0, y3, x3, y3);\n else this._context.bezierCurveTo(this._x0, this._y0 = (this._y0 + y3) / 2, x3, this._y0, x3, y3);\n break;\n }\n }\n this._x0 = x3, this._y0 = y3;\n }\n};\nfunction bumpX(context) {\n return new Bump(context, true);\n}\nfunction bumpY(context) {\n return new Bump(context, false);\n}\n\n// ../../node_modules/d3-shape/src/symbol/asterisk.js\nvar sqrt32 = sqrt3(3);\nvar asterisk_default = {\n draw(context, size) {\n const r = sqrt3(size + min4(size / 28, 0.75)) * 0.59436;\n const t = r / 2;\n const u4 = t * sqrt32;\n context.moveTo(0, r);\n context.lineTo(0, -r);\n context.moveTo(-u4, -t);\n context.lineTo(u4, t);\n context.moveTo(-u4, t);\n context.lineTo(u4, -t);\n }\n};\n\n// ../../node_modules/d3-shape/src/symbol/circle.js\nvar circle_default2 = {\n draw(context, size) {\n const r = sqrt3(size / pi3);\n context.moveTo(r, 0);\n context.arc(0, 0, r, 0, tau4);\n }\n};\n\n// ../../node_modules/d3-shape/src/symbol/cross.js\nvar cross_default = {\n draw(context, size) {\n const r = sqrt3(size / 5) / 2;\n context.moveTo(-3 * r, -r);\n context.lineTo(-r, -r);\n context.lineTo(-r, -3 * r);\n context.lineTo(r, -3 * r);\n context.lineTo(r, -r);\n context.lineTo(3 * r, -r);\n context.lineTo(3 * r, r);\n context.lineTo(r, r);\n context.lineTo(r, 3 * r);\n context.lineTo(-r, 3 * r);\n context.lineTo(-r, r);\n context.lineTo(-3 * r, r);\n context.closePath();\n }\n};\n\n// ../../node_modules/d3-shape/src/symbol/diamond.js\nvar tan30 = sqrt3(1 / 3);\nvar tan30_2 = tan30 * 2;\nvar diamond_default = {\n draw(context, size) {\n const y3 = sqrt3(size / tan30_2);\n const x3 = y3 * tan30;\n context.moveTo(0, -y3);\n context.lineTo(x3, 0);\n context.lineTo(0, y3);\n context.lineTo(-x3, 0);\n context.closePath();\n }\n};\n\n// ../../node_modules/d3-shape/src/symbol/diamond2.js\nvar diamond2_default = {\n draw(context, size) {\n const r = sqrt3(size) * 0.62625;\n context.moveTo(0, -r);\n context.lineTo(r, 0);\n context.lineTo(0, r);\n context.lineTo(-r, 0);\n context.closePath();\n }\n};\n\n// ../../node_modules/d3-shape/src/symbol/plus.js\nvar plus_default = {\n draw(context, size) {\n const r = sqrt3(size - min4(size / 7, 2)) * 0.87559;\n context.moveTo(-r, 0);\n context.lineTo(r, 0);\n context.moveTo(0, r);\n context.lineTo(0, -r);\n }\n};\n\n// ../../node_modules/d3-shape/src/symbol/square.js\nvar square_default = {\n draw(context, size) {\n const w = sqrt3(size);\n const x3 = -w / 2;\n context.rect(x3, x3, w, w);\n }\n};\n\n// ../../node_modules/d3-shape/src/symbol/square2.js\nvar square2_default = {\n draw(context, size) {\n const r = sqrt3(size) * 0.4431;\n context.moveTo(r, r);\n context.lineTo(r, -r);\n context.lineTo(-r, -r);\n context.lineTo(-r, r);\n context.closePath();\n }\n};\n\n// ../../node_modules/d3-shape/src/symbol/star.js\nvar ka = 0.8908130915292852;\nvar kr = sin2(pi3 / 10) / sin2(7 * pi3 / 10);\nvar kx = sin2(tau4 / 10) * kr;\nvar ky = -cos2(tau4 / 10) * kr;\nvar star_default = {\n draw(context, size) {\n const r = sqrt3(size * ka);\n const x3 = kx * r;\n const y3 = ky * r;\n context.moveTo(0, -r);\n context.lineTo(x3, y3);\n for (let i = 1; i < 5; ++i) {\n const a2 = tau4 * i / 5;\n const c4 = cos2(a2);\n const s2 = sin2(a2);\n context.lineTo(s2 * r, -c4 * r);\n context.lineTo(c4 * x3 - s2 * y3, s2 * x3 + c4 * y3);\n }\n context.closePath();\n }\n};\n\n// ../../node_modules/d3-shape/src/symbol/triangle.js\nvar sqrt33 = sqrt3(3);\nvar triangle_default = {\n draw(context, size) {\n const y3 = -sqrt3(size / (sqrt33 * 3));\n context.moveTo(0, y3 * 2);\n context.lineTo(-sqrt33 * y3, -y3);\n context.lineTo(sqrt33 * y3, -y3);\n context.closePath();\n }\n};\n\n// ../../node_modules/d3-shape/src/symbol/triangle2.js\nvar sqrt34 = sqrt3(3);\nvar triangle2_default = {\n draw(context, size) {\n const s2 = sqrt3(size) * 0.6824;\n const t = s2 / 2;\n const u4 = s2 * sqrt34 / 2;\n context.moveTo(0, -s2);\n context.lineTo(u4, t);\n context.lineTo(-u4, t);\n context.closePath();\n }\n};\n\n// ../../node_modules/d3-shape/src/symbol/wye.js\nvar c3 = -0.5;\nvar s = sqrt3(3) / 2;\nvar k = 1 / sqrt3(12);\nvar a = (k / 2 + 1) * 3;\nvar wye_default = {\n draw(context, size) {\n const r = sqrt3(size / a);\n const x06 = r / 2, y06 = r * k;\n const x12 = x06, y12 = r * k + r;\n const x22 = -x12, y22 = y12;\n context.moveTo(x06, y06);\n context.lineTo(x12, y12);\n context.lineTo(x22, y22);\n context.lineTo(c3 * x06 - s * y06, s * x06 + c3 * y06);\n context.lineTo(c3 * x12 - s * y12, s * x12 + c3 * y12);\n context.lineTo(c3 * x22 - s * y22, s * x22 + c3 * y22);\n context.lineTo(c3 * x06 + s * y06, c3 * y06 - s * x06);\n context.lineTo(c3 * x12 + s * y12, c3 * y12 - s * x12);\n context.lineTo(c3 * x22 + s * y22, c3 * y22 - s * x22);\n context.closePath();\n }\n};\n\n// ../../node_modules/d3-shape/src/symbol/times.js\nvar times_default = {\n draw(context, size) {\n const r = sqrt3(size - min4(size / 6, 1.7)) * 0.6189;\n context.moveTo(-r, -r);\n context.lineTo(r, r);\n context.moveTo(-r, r);\n context.lineTo(r, -r);\n }\n};\n\n// ../../node_modules/d3-shape/src/symbol.js\nvar symbolsFill = [\n circle_default2,\n cross_default,\n diamond_default,\n square_default,\n star_default,\n triangle_default,\n wye_default\n];\nvar symbolsStroke = [\n circle_default2,\n plus_default,\n times_default,\n triangle2_default,\n asterisk_default,\n square2_default,\n diamond2_default\n];\n\n// ../../node_modules/d3-shape/src/noop.js\nfunction noop_default2() {\n}\n\n// ../../node_modules/d3-shape/src/curve/basis.js\nfunction point2(that, x3, y3) {\n that._context.bezierCurveTo(\n (2 * that._x0 + that._x1) / 3,\n (2 * that._y0 + that._y1) / 3,\n (that._x0 + 2 * that._x1) / 3,\n (that._y0 + 2 * that._y1) / 3,\n (that._x0 + 4 * that._x1 + x3) / 6,\n (that._y0 + 4 * that._y1 + y3) / 6\n );\n}\nfunction Basis(context) {\n this._context = context;\n}\nBasis.prototype = {\n areaStart: function() {\n this._line = 0;\n },\n areaEnd: function() {\n this._line = NaN;\n },\n lineStart: function() {\n this._x0 = this._x1 = this._y0 = this._y1 = NaN;\n this._point = 0;\n },\n lineEnd: function() {\n switch (this._point) {\n case 3:\n point2(this, this._x1, this._y1);\n // falls through\n case 2:\n this._context.lineTo(this._x1, this._y1);\n break;\n }\n if (this._line || this._line !== 0 && this._point === 1) this._context.closePath();\n this._line = 1 - this._line;\n },\n point: function(x3, y3) {\n x3 = +x3, y3 = +y3;\n switch (this._point) {\n case 0:\n this._point = 1;\n this._line ? this._context.lineTo(x3, y3) : this._context.moveTo(x3, y3);\n break;\n case 1:\n this._point = 2;\n break;\n case 2:\n this._point = 3;\n this._context.lineTo((5 * this._x0 + this._x1) / 6, (5 * this._y0 + this._y1) / 6);\n // falls through\n default:\n point2(this, x3, y3);\n break;\n }\n this._x0 = this._x1, this._x1 = x3;\n this._y0 = this._y1, this._y1 = y3;\n }\n};\nfunction basis_default2(context) {\n return new Basis(context);\n}\n\n// ../../node_modules/d3-shape/src/curve/basisClosed.js\nfunction BasisClosed(context) {\n this._context = context;\n}\nBasisClosed.prototype = {\n areaStart: noop_default2,\n areaEnd: noop_default2,\n lineStart: function() {\n this._x0 = this._x1 = this._x2 = this._x3 = this._x4 = this._y0 = this._y1 = this._y2 = this._y3 = this._y4 = NaN;\n this._point = 0;\n },\n lineEnd: function() {\n switch (this._point) {\n case 1: {\n this._context.moveTo(this._x2, this._y2);\n this._context.closePath();\n break;\n }\n case 2: {\n this._context.moveTo((this._x2 + 2 * this._x3) / 3, (this._y2 + 2 * this._y3) / 3);\n this._context.lineTo((this._x3 + 2 * this._x2) / 3, (this._y3 + 2 * this._y2) / 3);\n this._context.closePath();\n break;\n }\n case 3: {\n this.point(this._x2, this._y2);\n this.point(this._x3, this._y3);\n this.point(this._x4, this._y4);\n break;\n }\n }\n },\n point: function(x3, y3) {\n x3 = +x3, y3 = +y3;\n switch (this._point) {\n case 0:\n this._point = 1;\n this._x2 = x3, this._y2 = y3;\n break;\n case 1:\n this._point = 2;\n this._x3 = x3, this._y3 = y3;\n break;\n case 2:\n this._point = 3;\n this._x4 = x3, this._y4 = y3;\n this._context.moveTo((this._x0 + 4 * this._x1 + x3) / 6, (this._y0 + 4 * this._y1 + y3) / 6);\n break;\n default:\n point2(this, x3, y3);\n break;\n }\n this._x0 = this._x1, this._x1 = x3;\n this._y0 = this._y1, this._y1 = y3;\n }\n};\nfunction basisClosed_default2(context) {\n return new BasisClosed(context);\n}\n\n// ../../node_modules/d3-shape/src/curve/basisOpen.js\nfunction BasisOpen(context) {\n this._context = context;\n}\nBasisOpen.prototype = {\n areaStart: function() {\n this._line = 0;\n },\n areaEnd: function() {\n this._line = NaN;\n },\n lineStart: function() {\n this._x0 = this._x1 = this._y0 = this._y1 = NaN;\n this._point = 0;\n },\n lineEnd: function() {\n if (this._line || this._line !== 0 && this._point === 3) this._context.closePath();\n this._line = 1 - this._line;\n },\n point: function(x3, y3) {\n x3 = +x3, y3 = +y3;\n switch (this._point) {\n case 0:\n this._point = 1;\n break;\n case 1:\n this._point = 2;\n break;\n case 2:\n this._point = 3;\n var x06 = (this._x0 + 4 * this._x1 + x3) / 6, y06 = (this._y0 + 4 * this._y1 + y3) / 6;\n this._line ? this._context.lineTo(x06, y06) : this._context.moveTo(x06, y06);\n break;\n case 3:\n this._point = 4;\n // falls through\n default:\n point2(this, x3, y3);\n break;\n }\n this._x0 = this._x1, this._x1 = x3;\n this._y0 = this._y1, this._y1 = y3;\n }\n};\nfunction basisOpen_default(context) {\n return new BasisOpen(context);\n}\n\n// ../../node_modules/d3-shape/src/curve/bundle.js\nfunction Bundle(context, beta) {\n this._basis = new Basis(context);\n this._beta = beta;\n}\nBundle.prototype = {\n lineStart: function() {\n this._x = [];\n this._y = [];\n this._basis.lineStart();\n },\n lineEnd: function() {\n var x3 = this._x, y3 = this._y, j = x3.length - 1;\n if (j > 0) {\n var x06 = x3[0], y06 = y3[0], dx = x3[j] - x06, dy = y3[j] - y06, i = -1, t;\n while (++i <= j) {\n t = i / j;\n this._basis.point(\n this._beta * x3[i] + (1 - this._beta) * (x06 + t * dx),\n this._beta * y3[i] + (1 - this._beta) * (y06 + t * dy)\n );\n }\n }\n this._x = this._y = null;\n this._basis.lineEnd();\n },\n point: function(x3, y3) {\n this._x.push(+x3);\n this._y.push(+y3);\n }\n};\nvar bundle_default = function custom(beta) {\n function bundle(context) {\n return beta === 1 ? new Basis(context) : new Bundle(context, beta);\n }\n bundle.beta = function(beta2) {\n return custom(+beta2);\n };\n return bundle;\n}(0.85);\n\n// ../../node_modules/d3-shape/src/curve/cardinal.js\nfunction point3(that, x3, y3) {\n that._context.bezierCurveTo(\n that._x1 + that._k * (that._x2 - that._x0),\n that._y1 + that._k * (that._y2 - that._y0),\n that._x2 + that._k * (that._x1 - x3),\n that._y2 + that._k * (that._y1 - y3),\n that._x2,\n that._y2\n );\n}\nfunction Cardinal(context, tension) {\n this._context = context;\n this._k = (1 - tension) / 6;\n}\nCardinal.prototype = {\n areaStart: function() {\n this._line = 0;\n },\n areaEnd: function() {\n this._line = NaN;\n },\n lineStart: function() {\n this._x0 = this._x1 = this._x2 = this._y0 = this._y1 = this._y2 = NaN;\n this._point = 0;\n },\n lineEnd: function() {\n switch (this._point) {\n case 2:\n this._context.lineTo(this._x2, this._y2);\n break;\n case 3:\n point3(this, this._x1, this._y1);\n break;\n }\n if (this._line || this._line !== 0 && this._point === 1) this._context.closePath();\n this._line = 1 - this._line;\n },\n point: function(x3, y3) {\n x3 = +x3, y3 = +y3;\n switch (this._point) {\n case 0:\n this._point = 1;\n this._line ? this._context.lineTo(x3, y3) : this._context.moveTo(x3, y3);\n break;\n case 1:\n this._point = 2;\n this._x1 = x3, this._y1 = y3;\n break;\n case 2:\n this._point = 3;\n // falls through\n default:\n point3(this, x3, y3);\n break;\n }\n this._x0 = this._x1, this._x1 = this._x2, this._x2 = x3;\n this._y0 = this._y1, this._y1 = this._y2, this._y2 = y3;\n }\n};\nvar cardinal_default = function custom2(tension) {\n function cardinal(context) {\n return new Cardinal(context, tension);\n }\n cardinal.tension = function(tension2) {\n return custom2(+tension2);\n };\n return cardinal;\n}(0);\n\n// ../../node_modules/d3-shape/src/curve/cardinalClosed.js\nfunction CardinalClosed(context, tension) {\n this._context = context;\n this._k = (1 - tension) / 6;\n}\nCardinalClosed.prototype = {\n areaStart: noop_default2,\n areaEnd: noop_default2,\n lineStart: function() {\n this._x0 = this._x1 = this._x2 = this._x3 = this._x4 = this._x5 = this._y0 = this._y1 = this._y2 = this._y3 = this._y4 = this._y5 = NaN;\n this._point = 0;\n },\n lineEnd: function() {\n switch (this._point) {\n case 1: {\n this._context.moveTo(this._x3, this._y3);\n this._context.closePath();\n break;\n }\n case 2: {\n this._context.lineTo(this._x3, this._y3);\n this._context.closePath();\n break;\n }\n case 3: {\n this.point(this._x3, this._y3);\n this.point(this._x4, this._y4);\n this.point(this._x5, this._y5);\n break;\n }\n }\n },\n point: function(x3, y3) {\n x3 = +x3, y3 = +y3;\n switch (this._point) {\n case 0:\n this._point = 1;\n this._x3 = x3, this._y3 = y3;\n break;\n case 1:\n this._point = 2;\n this._context.moveTo(this._x4 = x3, this._y4 = y3);\n break;\n case 2:\n this._point = 3;\n this._x5 = x3, this._y5 = y3;\n break;\n default:\n point3(this, x3, y3);\n break;\n }\n this._x0 = this._x1, this._x1 = this._x2, this._x2 = x3;\n this._y0 = this._y1, this._y1 = this._y2, this._y2 = y3;\n }\n};\nvar cardinalClosed_default = function custom3(tension) {\n function cardinal(context) {\n return new CardinalClosed(context, tension);\n }\n cardinal.tension = function(tension2) {\n return custom3(+tension2);\n };\n return cardinal;\n}(0);\n\n// ../../node_modules/d3-shape/src/curve/cardinalOpen.js\nfunction CardinalOpen(context, tension) {\n this._context = context;\n this._k = (1 - tension) / 6;\n}\nCardinalOpen.prototype = {\n areaStart: function() {\n this._line = 0;\n },\n areaEnd: function() {\n this._line = NaN;\n },\n lineStart: function() {\n this._x0 = this._x1 = this._x2 = this._y0 = this._y1 = this._y2 = NaN;\n this._point = 0;\n },\n lineEnd: function() {\n if (this._line || this._line !== 0 && this._point === 3) this._context.closePath();\n this._line = 1 - this._line;\n },\n point: function(x3, y3) {\n x3 = +x3, y3 = +y3;\n switch (this._point) {\n case 0:\n this._point = 1;\n break;\n case 1:\n this._point = 2;\n break;\n case 2:\n this._point = 3;\n this._line ? this._context.lineTo(this._x2, this._y2) : this._context.moveTo(this._x2, this._y2);\n break;\n case 3:\n this._point = 4;\n // falls through\n default:\n point3(this, x3, y3);\n break;\n }\n this._x0 = this._x1, this._x1 = this._x2, this._x2 = x3;\n this._y0 = this._y1, this._y1 = this._y2, this._y2 = y3;\n }\n};\nvar cardinalOpen_default = function custom4(tension) {\n function cardinal(context) {\n return new CardinalOpen(context, tension);\n }\n cardinal.tension = function(tension2) {\n return custom4(+tension2);\n };\n return cardinal;\n}(0);\n\n// ../../node_modules/d3-shape/src/curve/catmullRom.js\nfunction point4(that, x3, y3) {\n var x12 = that._x1, y12 = that._y1, x22 = that._x2, y22 = that._y2;\n if (that._l01_a > epsilon7) {\n var a2 = 2 * that._l01_2a + 3 * that._l01_a * that._l12_a + that._l12_2a, n = 3 * that._l01_a * (that._l01_a + that._l12_a);\n x12 = (x12 * a2 - that._x0 * that._l12_2a + that._x2 * that._l01_2a) / n;\n y12 = (y12 * a2 - that._y0 * that._l12_2a + that._y2 * that._l01_2a) / n;\n }\n if (that._l23_a > epsilon7) {\n var b = 2 * that._l23_2a + 3 * that._l23_a * that._l12_a + that._l12_2a, m = 3 * that._l23_a * (that._l23_a + that._l12_a);\n x22 = (x22 * b + that._x1 * that._l23_2a - x3 * that._l12_2a) / m;\n y22 = (y22 * b + that._y1 * that._l23_2a - y3 * that._l12_2a) / m;\n }\n that._context.bezierCurveTo(x12, y12, x22, y22, that._x2, that._y2);\n}\nfunction CatmullRom(context, alpha) {\n this._context = context;\n this._alpha = alpha;\n}\nCatmullRom.prototype = {\n areaStart: function() {\n this._line = 0;\n },\n areaEnd: function() {\n this._line = NaN;\n },\n lineStart: function() {\n this._x0 = this._x1 = this._x2 = this._y0 = this._y1 = this._y2 = NaN;\n this._l01_a = this._l12_a = this._l23_a = this._l01_2a = this._l12_2a = this._l23_2a = this._point = 0;\n },\n lineEnd: function() {\n switch (this._point) {\n case 2:\n this._context.lineTo(this._x2, this._y2);\n break;\n case 3:\n this.point(this._x2, this._y2);\n break;\n }\n if (this._line || this._line !== 0 && this._point === 1) this._context.closePath();\n this._line = 1 - this._line;\n },\n point: function(x3, y3) {\n x3 = +x3, y3 = +y3;\n if (this._point) {\n var x23 = this._x2 - x3, y23 = this._y2 - y3;\n this._l23_a = Math.sqrt(this._l23_2a = Math.pow(x23 * x23 + y23 * y23, this._alpha));\n }\n switch (this._point) {\n case 0:\n this._point = 1;\n this._line ? this._context.lineTo(x3, y3) : this._context.moveTo(x3, y3);\n break;\n case 1:\n this._point = 2;\n break;\n case 2:\n this._point = 3;\n // falls through\n default:\n point4(this, x3, y3);\n break;\n }\n this._l01_a = this._l12_a, this._l12_a = this._l23_a;\n this._l01_2a = this._l12_2a, this._l12_2a = this._l23_2a;\n this._x0 = this._x1, this._x1 = this._x2, this._x2 = x3;\n this._y0 = this._y1, this._y1 = this._y2, this._y2 = y3;\n }\n};\nvar catmullRom_default = function custom5(alpha) {\n function catmullRom(context) {\n return alpha ? new CatmullRom(context, alpha) : new Cardinal(context, 0);\n }\n catmullRom.alpha = function(alpha2) {\n return custom5(+alpha2);\n };\n return catmullRom;\n}(0.5);\n\n// ../../node_modules/d3-shape/src/curve/catmullRomClosed.js\nfunction CatmullRomClosed(context, alpha) {\n this._context = context;\n this._alpha = alpha;\n}\nCatmullRomClosed.prototype = {\n areaStart: noop_default2,\n areaEnd: noop_default2,\n lineStart: function() {\n this._x0 = this._x1 = this._x2 = this._x3 = this._x4 = this._x5 = this._y0 = this._y1 = this._y2 = this._y3 = this._y4 = this._y5 = NaN;\n this._l01_a = this._l12_a = this._l23_a = this._l01_2a = this._l12_2a = this._l23_2a = this._point = 0;\n },\n lineEnd: function() {\n switch (this._point) {\n case 1: {\n this._context.moveTo(this._x3, this._y3);\n this._context.closePath();\n break;\n }\n case 2: {\n this._context.lineTo(this._x3, this._y3);\n this._context.closePath();\n break;\n }\n case 3: {\n this.point(this._x3, this._y3);\n this.point(this._x4, this._y4);\n this.point(this._x5, this._y5);\n break;\n }\n }\n },\n point: function(x3, y3) {\n x3 = +x3, y3 = +y3;\n if (this._point) {\n var x23 = this._x2 - x3, y23 = this._y2 - y3;\n this._l23_a = Math.sqrt(this._l23_2a = Math.pow(x23 * x23 + y23 * y23, this._alpha));\n }\n switch (this._point) {\n case 0:\n this._point = 1;\n this._x3 = x3, this._y3 = y3;\n break;\n case 1:\n this._point = 2;\n this._context.moveTo(this._x4 = x3, this._y4 = y3);\n break;\n case 2:\n this._point = 3;\n this._x5 = x3, this._y5 = y3;\n break;\n default:\n point4(this, x3, y3);\n break;\n }\n this._l01_a = this._l12_a, this._l12_a = this._l23_a;\n this._l01_2a = this._l12_2a, this._l12_2a = this._l23_2a;\n this._x0 = this._x1, this._x1 = this._x2, this._x2 = x3;\n this._y0 = this._y1, this._y1 = this._y2, this._y2 = y3;\n }\n};\nvar catmullRomClosed_default = function custom6(alpha) {\n function catmullRom(context) {\n return alpha ? new CatmullRomClosed(context, alpha) : new CardinalClosed(context, 0);\n }\n catmullRom.alpha = function(alpha2) {\n return custom6(+alpha2);\n };\n return catmullRom;\n}(0.5);\n\n// ../../node_modules/d3-shape/src/curve/catmullRomOpen.js\nfunction CatmullRomOpen(context, alpha) {\n this._context = context;\n this._alpha = alpha;\n}\nCatmullRomOpen.prototype = {\n areaStart: function() {\n this._line = 0;\n },\n areaEnd: function() {\n this._line = NaN;\n },\n lineStart: function() {\n this._x0 = this._x1 = this._x2 = this._y0 = this._y1 = this._y2 = NaN;\n this._l01_a = this._l12_a = this._l23_a = this._l01_2a = this._l12_2a = this._l23_2a = this._point = 0;\n },\n lineEnd: function() {\n if (this._line || this._line !== 0 && this._point === 3) this._context.closePath();\n this._line = 1 - this._line;\n },\n point: function(x3, y3) {\n x3 = +x3, y3 = +y3;\n if (this._point) {\n var x23 = this._x2 - x3, y23 = this._y2 - y3;\n this._l23_a = Math.sqrt(this._l23_2a = Math.pow(x23 * x23 + y23 * y23, this._alpha));\n }\n switch (this._point) {\n case 0:\n this._point = 1;\n break;\n case 1:\n this._point = 2;\n break;\n case 2:\n this._point = 3;\n this._line ? this._context.lineTo(this._x2, this._y2) : this._context.moveTo(this._x2, this._y2);\n break;\n case 3:\n this._point = 4;\n // falls through\n default:\n point4(this, x3, y3);\n break;\n }\n this._l01_a = this._l12_a, this._l12_a = this._l23_a;\n this._l01_2a = this._l12_2a, this._l12_2a = this._l23_2a;\n this._x0 = this._x1, this._x1 = this._x2, this._x2 = x3;\n this._y0 = this._y1, this._y1 = this._y2, this._y2 = y3;\n }\n};\nvar catmullRomOpen_default = function custom7(alpha) {\n function catmullRom(context) {\n return alpha ? new CatmullRomOpen(context, alpha) : new CardinalOpen(context, 0);\n }\n catmullRom.alpha = function(alpha2) {\n return custom7(+alpha2);\n };\n return catmullRom;\n}(0.5);\n\n// ../../node_modules/d3-shape/src/curve/linearClosed.js\nfunction LinearClosed(context) {\n this._context = context;\n}\nLinearClosed.prototype = {\n areaStart: noop_default2,\n areaEnd: noop_default2,\n lineStart: function() {\n this._point = 0;\n },\n lineEnd: function() {\n if (this._point) this._context.closePath();\n },\n point: function(x3, y3) {\n x3 = +x3, y3 = +y3;\n if (this._point) this._context.lineTo(x3, y3);\n else this._point = 1, this._context.moveTo(x3, y3);\n }\n};\nfunction linearClosed_default(context) {\n return new LinearClosed(context);\n}\n\n// ../../node_modules/d3-shape/src/curve/monotone.js\nfunction sign2(x3) {\n return x3 < 0 ? -1 : 1;\n}\nfunction slope3(that, x22, y22) {\n var h0 = that._x1 - that._x0, h1 = x22 - that._x1, s0 = (that._y1 - that._y0) / (h0 || h1 < 0 && -0), s1 = (y22 - that._y1) / (h1 || h0 < 0 && -0), p = (s0 * h1 + s1 * h0) / (h0 + h1);\n return (sign2(s0) + sign2(s1)) * Math.min(Math.abs(s0), Math.abs(s1), 0.5 * Math.abs(p)) || 0;\n}\nfunction slope2(that, t) {\n var h = that._x1 - that._x0;\n return h ? (3 * (that._y1 - that._y0) / h - t) / 2 : t;\n}\nfunction point5(that, t03, t13) {\n var x06 = that._x0, y06 = that._y0, x12 = that._x1, y12 = that._y1, dx = (x12 - x06) / 3;\n that._context.bezierCurveTo(x06 + dx, y06 + dx * t03, x12 - dx, y12 - dx * t13, x12, y12);\n}\nfunction MonotoneX(context) {\n this._context = context;\n}\nMonotoneX.prototype = {\n areaStart: function() {\n this._line = 0;\n },\n areaEnd: function() {\n this._line = NaN;\n },\n lineStart: function() {\n this._x0 = this._x1 = this._y0 = this._y1 = this._t0 = NaN;\n this._point = 0;\n },\n lineEnd: function() {\n switch (this._point) {\n case 2:\n this._context.lineTo(this._x1, this._y1);\n break;\n case 3:\n point5(this, this._t0, slope2(this, this._t0));\n break;\n }\n if (this._line || this._line !== 0 && this._point === 1) this._context.closePath();\n this._line = 1 - this._line;\n },\n point: function(x3, y3) {\n var t13 = NaN;\n x3 = +x3, y3 = +y3;\n if (x3 === this._x1 && y3 === this._y1) return;\n switch (this._point) {\n case 0:\n this._point = 1;\n this._line ? this._context.lineTo(x3, y3) : this._context.moveTo(x3, y3);\n break;\n case 1:\n this._point = 2;\n break;\n case 2:\n this._point = 3;\n point5(this, slope2(this, t13 = slope3(this, x3, y3)), t13);\n break;\n default:\n point5(this, this._t0, t13 = slope3(this, x3, y3));\n break;\n }\n this._x0 = this._x1, this._x1 = x3;\n this._y0 = this._y1, this._y1 = y3;\n this._t0 = t13;\n }\n};\nfunction MonotoneY(context) {\n this._context = new ReflectContext(context);\n}\n(MonotoneY.prototype = Object.create(MonotoneX.prototype)).point = function(x3, y3) {\n MonotoneX.prototype.point.call(this, y3, x3);\n};\nfunction ReflectContext(context) {\n this._context = context;\n}\nReflectContext.prototype = {\n moveTo: function(x3, y3) {\n this._context.moveTo(y3, x3);\n },\n closePath: function() {\n this._context.closePath();\n },\n lineTo: function(x3, y3) {\n this._context.lineTo(y3, x3);\n },\n bezierCurveTo: function(x12, y12, x22, y22, x3, y3) {\n this._context.bezierCurveTo(y12, x12, y22, x22, y3, x3);\n }\n};\nfunction monotoneX(context) {\n return new MonotoneX(context);\n}\nfunction monotoneY(context) {\n return new MonotoneY(context);\n}\n\n// ../../node_modules/d3-shape/src/curve/natural.js\nfunction Natural(context) {\n this._context = context;\n}\nNatural.prototype = {\n areaStart: function() {\n this._line = 0;\n },\n areaEnd: function() {\n this._line = NaN;\n },\n lineStart: function() {\n this._x = [];\n this._y = [];\n },\n lineEnd: function() {\n var x3 = this._x, y3 = this._y, n = x3.length;\n if (n) {\n this._line ? this._context.lineTo(x3[0], y3[0]) : this._context.moveTo(x3[0], y3[0]);\n if (n === 2) {\n this._context.lineTo(x3[1], y3[1]);\n } else {\n var px = controlPoints(x3), py = controlPoints(y3);\n for (var i0 = 0, i1 = 1; i1 < n; ++i0, ++i1) {\n this._context.bezierCurveTo(px[0][i0], py[0][i0], px[1][i0], py[1][i0], x3[i1], y3[i1]);\n }\n }\n }\n if (this._line || this._line !== 0 && n === 1) this._context.closePath();\n this._line = 1 - this._line;\n this._x = this._y = null;\n },\n point: function(x3, y3) {\n this._x.push(+x3);\n this._y.push(+y3);\n }\n};\nfunction controlPoints(x3) {\n var i, n = x3.length - 1, m, a2 = new Array(n), b = new Array(n), r = new Array(n);\n a2[0] = 0, b[0] = 2, r[0] = x3[0] + 2 * x3[1];\n for (i = 1; i < n - 1; ++i) a2[i] = 1, b[i] = 4, r[i] = 4 * x3[i] + 2 * x3[i + 1];\n a2[n - 1] = 2, b[n - 1] = 7, r[n - 1] = 8 * x3[n - 1] + x3[n];\n for (i = 1; i < n; ++i) m = a2[i] / b[i - 1], b[i] -= m, r[i] -= m * r[i - 1];\n a2[n - 1] = r[n - 1] / b[n - 1];\n for (i = n - 2; i >= 0; --i) a2[i] = (r[i] - a2[i + 1]) / b[i];\n b[n - 1] = (x3[n] + a2[n - 1]) / 2;\n for (i = 0; i < n - 1; ++i) b[i] = 2 * x3[i + 1] - a2[i + 1];\n return [a2, b];\n}\nfunction natural_default(context) {\n return new Natural(context);\n}\n\n// ../../node_modules/d3-shape/src/curve/step.js\nfunction Step(context, t) {\n this._context = context;\n this._t = t;\n}\nStep.prototype = {\n areaStart: function() {\n this._line = 0;\n },\n areaEnd: function() {\n this._line = NaN;\n },\n lineStart: function() {\n this._x = this._y = NaN;\n this._point = 0;\n },\n lineEnd: function() {\n if (0 < this._t && this._t < 1 && this._point === 2) this._context.lineTo(this._x, this._y);\n if (this._line || this._line !== 0 && this._point === 1) this._context.closePath();\n if (this._line >= 0) this._t = 1 - this._t, this._line = 1 - this._line;\n },\n point: function(x3, y3) {\n x3 = +x3, y3 = +y3;\n switch (this._point) {\n case 0:\n this._point = 1;\n this._line ? this._context.lineTo(x3, y3) : this._context.moveTo(x3, y3);\n break;\n case 1:\n this._point = 2;\n // falls through\n default: {\n if (this._t <= 0) {\n this._context.lineTo(this._x, y3);\n this._context.lineTo(x3, y3);\n } else {\n var x12 = this._x * (1 - this._t) + x3 * this._t;\n this._context.lineTo(x12, this._y);\n this._context.lineTo(x12, y3);\n }\n break;\n }\n }\n this._x = x3, this._y = y3;\n }\n};\nfunction step_default(context) {\n return new Step(context, 0.5);\n}\nfunction stepBefore(context) {\n return new Step(context, 0);\n}\nfunction stepAfter(context) {\n return new Step(context, 1);\n}\n\n// ../../node_modules/d3-zoom/src/constant.js\nvar constant_default6 = (x3) => () => x3;\n\n// ../../node_modules/d3-zoom/src/event.js\nfunction ZoomEvent(type2, {\n sourceEvent,\n target,\n transform: transform3,\n dispatch: dispatch2\n}) {\n Object.defineProperties(this, {\n type: { value: type2, enumerable: true, configurable: true },\n sourceEvent: { value: sourceEvent, enumerable: true, configurable: true },\n target: { value: target, enumerable: true, configurable: true },\n transform: { value: transform3, enumerable: true, configurable: true },\n _: { value: dispatch2 }\n });\n}\n\n// ../../node_modules/d3-zoom/src/transform.js\nfunction Transform2(k2, x3, y3) {\n this.k = k2;\n this.x = x3;\n this.y = y3;\n}\nTransform2.prototype = {\n constructor: Transform2,\n scale: function(k2) {\n return k2 === 1 ? this : new Transform2(this.k * k2, this.x, this.y);\n },\n translate: function(x3, y3) {\n return x3 === 0 & y3 === 0 ? this : new Transform2(this.k, this.x + this.k * x3, this.y + this.k * y3);\n },\n apply: function(point6) {\n return [point6[0] * this.k + this.x, point6[1] * this.k + this.y];\n },\n applyX: function(x3) {\n return x3 * this.k + this.x;\n },\n applyY: function(y3) {\n return y3 * this.k + this.y;\n },\n invert: function(location) {\n return [(location[0] - this.x) / this.k, (location[1] - this.y) / this.k];\n },\n invertX: function(x3) {\n return (x3 - this.x) / this.k;\n },\n invertY: function(y3) {\n return (y3 - this.y) / this.k;\n },\n rescaleX: function(x3) {\n return x3.copy().domain(x3.range().map(this.invertX, this).map(x3.invert, x3));\n },\n rescaleY: function(y3) {\n return y3.copy().domain(y3.range().map(this.invertY, this).map(y3.invert, y3));\n },\n toString: function() {\n return \"translate(\" + this.x + \",\" + this.y + \") scale(\" + this.k + \")\";\n }\n};\nvar identity6 = new Transform2(1, 0, 0);\ntransform.prototype = Transform2.prototype;\nfunction transform(node) {\n while (!node.__zoom) if (!(node = node.parentNode)) return identity6;\n return node.__zoom;\n}\n\n// ../../node_modules/d3-zoom/src/noevent.js\nfunction nopropagation2(event) {\n event.stopImmediatePropagation();\n}\nfunction noevent_default3(event) {\n event.preventDefault();\n event.stopImmediatePropagation();\n}\n\n// ../../node_modules/d3-zoom/src/zoom.js\nfunction defaultFilter2(event) {\n return (!event.ctrlKey || event.type === \"wheel\") && !event.button;\n}\nfunction defaultExtent2() {\n var e = this;\n if (e instanceof SVGElement) {\n e = e.ownerSVGElement || e;\n if (e.hasAttribute(\"viewBox\")) {\n e = e.viewBox.baseVal;\n return [[e.x, e.y], [e.x + e.width, e.y + e.height]];\n }\n return [[0, 0], [e.width.baseVal.value, e.height.baseVal.value]];\n }\n return [[0, 0], [e.clientWidth, e.clientHeight]];\n}\nfunction defaultTransform() {\n return this.__zoom || identity6;\n}\nfunction defaultWheelDelta(event) {\n return -event.deltaY * (event.deltaMode === 1 ? 0.05 : event.deltaMode ? 1 : 2e-3) * (event.ctrlKey ? 10 : 1);\n}\nfunction defaultTouchable2() {\n return navigator.maxTouchPoints || \"ontouchstart\" in this;\n}\nfunction defaultConstrain(transform3, extent4, translateExtent) {\n var dx0 = transform3.invertX(extent4[0][0]) - translateExtent[0][0], dx1 = transform3.invertX(extent4[1][0]) - translateExtent[1][0], dy0 = transform3.invertY(extent4[0][1]) - translateExtent[0][1], dy1 = transform3.invertY(extent4[1][1]) - translateExtent[1][1];\n return transform3.translate(\n dx1 > dx0 ? (dx0 + dx1) / 2 : Math.min(0, dx0) || Math.max(0, dx1),\n dy1 > dy0 ? (dy0 + dy1) / 2 : Math.min(0, dy0) || Math.max(0, dy1)\n );\n}\nfunction zoom_default2() {\n var filter3 = defaultFilter2, extent4 = defaultExtent2, constrain = defaultConstrain, wheelDelta = defaultWheelDelta, touchable = defaultTouchable2, scaleExtent = [0, Infinity], translateExtent = [[-Infinity, -Infinity], [Infinity, Infinity]], duration2 = 250, interpolate = zoom_default, listeners = dispatch_default(\"start\", \"zoom\", \"end\"), touchstarting, touchfirst, touchending, touchDelay = 500, wheelDelay = 150, clickDistance2 = 0, tapDistance = 10;\n function zoom2(selection2) {\n selection2.property(\"__zoom\", defaultTransform).on(\"wheel.zoom\", wheeled, { passive: false }).on(\"mousedown.zoom\", mousedowned).on(\"dblclick.zoom\", dblclicked).filter(touchable).on(\"touchstart.zoom\", touchstarted).on(\"touchmove.zoom\", touchmoved).on(\"touchend.zoom touchcancel.zoom\", touchended).style(\"-webkit-tap-highlight-color\", \"rgba(0,0,0,0)\");\n }\n zoom2.transform = function(collection, transform3, point6, event) {\n var selection2 = collection.selection ? collection.selection() : collection;\n selection2.property(\"__zoom\", defaultTransform);\n if (collection !== selection2) {\n schedule(collection, transform3, point6, event);\n } else {\n selection2.interrupt().each(function() {\n gesture(this, arguments).event(event).start().zoom(null, typeof transform3 === \"function\" ? transform3.apply(this, arguments) : transform3).end();\n });\n }\n };\n zoom2.scaleBy = function(selection2, k2, p, event) {\n zoom2.scaleTo(selection2, function() {\n var k0 = this.__zoom.k, k1 = typeof k2 === \"function\" ? k2.apply(this, arguments) : k2;\n return k0 * k1;\n }, p, event);\n };\n zoom2.scaleTo = function(selection2, k2, p, event) {\n zoom2.transform(selection2, function() {\n var e = extent4.apply(this, arguments), t03 = this.__zoom, p0 = p == null ? centroid3(e) : typeof p === \"function\" ? p.apply(this, arguments) : p, p1 = t03.invert(p0), k1 = typeof k2 === \"function\" ? k2.apply(this, arguments) : k2;\n return constrain(translate(scale3(t03, k1), p0, p1), e, translateExtent);\n }, p, event);\n };\n zoom2.translateBy = function(selection2, x3, y3, event) {\n zoom2.transform(selection2, function() {\n return constrain(this.__zoom.translate(\n typeof x3 === \"function\" ? x3.apply(this, arguments) : x3,\n typeof y3 === \"function\" ? y3.apply(this, arguments) : y3\n ), extent4.apply(this, arguments), translateExtent);\n }, null, event);\n };\n zoom2.translateTo = function(selection2, x3, y3, p, event) {\n zoom2.transform(selection2, function() {\n var e = extent4.apply(this, arguments), t = this.__zoom, p0 = p == null ? centroid3(e) : typeof p === \"function\" ? p.apply(this, arguments) : p;\n return constrain(identity6.translate(p0[0], p0[1]).scale(t.k).translate(\n typeof x3 === \"function\" ? -x3.apply(this, arguments) : -x3,\n typeof y3 === \"function\" ? -y3.apply(this, arguments) : -y3\n ), e, translateExtent);\n }, p, event);\n };\n function scale3(transform3, k2) {\n k2 = Math.max(scaleExtent[0], Math.min(scaleExtent[1], k2));\n return k2 === transform3.k ? transform3 : new Transform2(k2, transform3.x, transform3.y);\n }\n function translate(transform3, p0, p1) {\n var x3 = p0[0] - p1[0] * transform3.k, y3 = p0[1] - p1[1] * transform3.k;\n return x3 === transform3.x && y3 === transform3.y ? transform3 : new Transform2(transform3.k, x3, y3);\n }\n function centroid3(extent5) {\n return [(+extent5[0][0] + +extent5[1][0]) / 2, (+extent5[0][1] + +extent5[1][1]) / 2];\n }\n function schedule(transition2, transform3, point6, event) {\n transition2.on(\"start.zoom\", function() {\n gesture(this, arguments).event(event).start();\n }).on(\"interrupt.zoom end.zoom\", function() {\n gesture(this, arguments).event(event).end();\n }).tween(\"zoom\", function() {\n var that = this, args = arguments, g = gesture(that, args).event(event), e = extent4.apply(that, args), p = point6 == null ? centroid3(e) : typeof point6 === \"function\" ? point6.apply(that, args) : point6, w = Math.max(e[1][0] - e[0][0], e[1][1] - e[0][1]), a2 = that.__zoom, b = typeof transform3 === \"function\" ? transform3.apply(that, args) : transform3, i = interpolate(a2.invert(p).concat(w / a2.k), b.invert(p).concat(w / b.k));\n return function(t) {\n if (t === 1) t = b;\n else {\n var l = i(t), k2 = w / l[2];\n t = new Transform2(k2, p[0] - l[0] * k2, p[1] - l[1] * k2);\n }\n g.zoom(null, t);\n };\n });\n }\n function gesture(that, args, clean) {\n return !clean && that.__zooming || new Gesture(that, args);\n }\n function Gesture(that, args) {\n this.that = that;\n this.args = args;\n this.active = 0;\n this.sourceEvent = null;\n this.extent = extent4.apply(that, args);\n this.taps = 0;\n }\n Gesture.prototype = {\n event: function(event) {\n if (event) this.sourceEvent = event;\n return this;\n },\n start: function() {\n if (++this.active === 1) {\n this.that.__zooming = this;\n this.emit(\"start\");\n }\n return this;\n },\n zoom: function(key, transform3) {\n if (this.mouse && key !== \"mouse\") this.mouse[1] = transform3.invert(this.mouse[0]);\n if (this.touch0 && key !== \"touch\") this.touch0[1] = transform3.invert(this.touch0[0]);\n if (this.touch1 && key !== \"touch\") this.touch1[1] = transform3.invert(this.touch1[0]);\n this.that.__zoom = transform3;\n this.emit(\"zoom\");\n return this;\n },\n end: function() {\n if (--this.active === 0) {\n delete this.that.__zooming;\n this.emit(\"end\");\n }\n return this;\n },\n emit: function(type2) {\n var d = select_default2(this.that).datum();\n listeners.call(\n type2,\n this.that,\n new ZoomEvent(type2, {\n sourceEvent: this.sourceEvent,\n target: zoom2,\n type: type2,\n transform: this.that.__zoom,\n dispatch: listeners\n }),\n d\n );\n }\n };\n function wheeled(event, ...args) {\n if (!filter3.apply(this, arguments)) return;\n var g = gesture(this, args).event(event), t = this.__zoom, k2 = Math.max(scaleExtent[0], Math.min(scaleExtent[1], t.k * Math.pow(2, wheelDelta.apply(this, arguments)))), p = pointer_default(event);\n if (g.wheel) {\n if (g.mouse[0][0] !== p[0] || g.mouse[0][1] !== p[1]) {\n g.mouse[1] = t.invert(g.mouse[0] = p);\n }\n clearTimeout(g.wheel);\n } else if (t.k === k2) return;\n else {\n g.mouse = [p, t.invert(p)];\n interrupt_default(this);\n g.start();\n }\n noevent_default3(event);\n g.wheel = setTimeout(wheelidled, wheelDelay);\n g.zoom(\"mouse\", constrain(translate(scale3(t, k2), g.mouse[0], g.mouse[1]), g.extent, translateExtent));\n function wheelidled() {\n g.wheel = null;\n g.end();\n }\n }\n function mousedowned(event, ...args) {\n if (touchending || !filter3.apply(this, arguments)) return;\n var currentTarget = event.currentTarget, g = gesture(this, args, true).event(event), v2 = select_default2(event.view).on(\"mousemove.zoom\", mousemoved, true).on(\"mouseup.zoom\", mouseupped, true), p = pointer_default(event, currentTarget), x06 = event.clientX, y06 = event.clientY;\n nodrag_default(event.view);\n nopropagation2(event);\n g.mouse = [p, this.__zoom.invert(p)];\n interrupt_default(this);\n g.start();\n function mousemoved(event2) {\n noevent_default3(event2);\n if (!g.moved) {\n var dx = event2.clientX - x06, dy = event2.clientY - y06;\n g.moved = dx * dx + dy * dy > clickDistance2;\n }\n g.event(event2).zoom(\"mouse\", constrain(translate(g.that.__zoom, g.mouse[0] = pointer_default(event2, currentTarget), g.mouse[1]), g.extent, translateExtent));\n }\n function mouseupped(event2) {\n v2.on(\"mousemove.zoom mouseup.zoom\", null);\n yesdrag(event2.view, g.moved);\n noevent_default3(event2);\n g.event(event2).end();\n }\n }\n function dblclicked(event, ...args) {\n if (!filter3.apply(this, arguments)) return;\n var t03 = this.__zoom, p0 = pointer_default(event.changedTouches ? event.changedTouches[0] : event, this), p1 = t03.invert(p0), k1 = t03.k * (event.shiftKey ? 0.5 : 2), t13 = constrain(translate(scale3(t03, k1), p0, p1), extent4.apply(this, args), translateExtent);\n noevent_default3(event);\n if (duration2 > 0) select_default2(this).transition().duration(duration2).call(schedule, t13, p0, event);\n else select_default2(this).call(zoom2.transform, t13, p0, event);\n }\n function touchstarted(event, ...args) {\n if (!filter3.apply(this, arguments)) return;\n var touches = event.touches, n = touches.length, g = gesture(this, args, event.changedTouches.length === n).event(event), started, i, t, p;\n nopropagation2(event);\n for (i = 0; i < n; ++i) {\n t = touches[i], p = pointer_default(t, this);\n p = [p, this.__zoom.invert(p), t.identifier];\n if (!g.touch0) g.touch0 = p, started = true, g.taps = 1 + !!touchstarting;\n else if (!g.touch1 && g.touch0[2] !== p[2]) g.touch1 = p, g.taps = 0;\n }\n if (touchstarting) touchstarting = clearTimeout(touchstarting);\n if (started) {\n if (g.taps < 2) touchfirst = p[0], touchstarting = setTimeout(function() {\n touchstarting = null;\n }, touchDelay);\n interrupt_default(this);\n g.start();\n }\n }\n function touchmoved(event, ...args) {\n if (!this.__zooming) return;\n var g = gesture(this, args).event(event), touches = event.changedTouches, n = touches.length, i, t, p, l;\n noevent_default3(event);\n for (i = 0; i < n; ++i) {\n t = touches[i], p = pointer_default(t, this);\n if (g.touch0 && g.touch0[2] === t.identifier) g.touch0[0] = p;\n else if (g.touch1 && g.touch1[2] === t.identifier) g.touch1[0] = p;\n }\n t = g.that.__zoom;\n if (g.touch1) {\n var p0 = g.touch0[0], l0 = g.touch0[1], p1 = g.touch1[0], l1 = g.touch1[1], dp = (dp = p1[0] - p0[0]) * dp + (dp = p1[1] - p0[1]) * dp, dl = (dl = l1[0] - l0[0]) * dl + (dl = l1[1] - l0[1]) * dl;\n t = scale3(t, Math.sqrt(dp / dl));\n p = [(p0[0] + p1[0]) / 2, (p0[1] + p1[1]) / 2];\n l = [(l0[0] + l1[0]) / 2, (l0[1] + l1[1]) / 2];\n } else if (g.touch0) p = g.touch0[0], l = g.touch0[1];\n else return;\n g.zoom(\"touch\", constrain(translate(t, p, l), g.extent, translateExtent));\n }\n function touchended(event, ...args) {\n if (!this.__zooming) return;\n var g = gesture(this, args).event(event), touches = event.changedTouches, n = touches.length, i, t;\n nopropagation2(event);\n if (touchending) clearTimeout(touchending);\n touchending = setTimeout(function() {\n touchending = null;\n }, touchDelay);\n for (i = 0; i < n; ++i) {\n t = touches[i];\n if (g.touch0 && g.touch0[2] === t.identifier) delete g.touch0;\n else if (g.touch1 && g.touch1[2] === t.identifier) delete g.touch1;\n }\n if (g.touch1 && !g.touch0) g.touch0 = g.touch1, delete g.touch1;\n if (g.touch0) g.touch0[1] = this.__zoom.invert(g.touch0[0]);\n else {\n g.end();\n if (g.taps === 2) {\n t = pointer_default(t, this);\n if (Math.hypot(touchfirst[0] - t[0], touchfirst[1] - t[1]) < tapDistance) {\n var p = select_default2(this).on(\"dblclick.zoom\");\n if (p) p.apply(this, arguments);\n }\n }\n }\n }\n zoom2.wheelDelta = function(_) {\n return arguments.length ? (wheelDelta = typeof _ === \"function\" ? _ : constant_default6(+_), zoom2) : wheelDelta;\n };\n zoom2.filter = function(_) {\n return arguments.length ? (filter3 = typeof _ === \"function\" ? _ : constant_default6(!!_), zoom2) : filter3;\n };\n zoom2.touchable = function(_) {\n return arguments.length ? (touchable = typeof _ === \"function\" ? _ : constant_default6(!!_), zoom2) : touchable;\n };\n zoom2.extent = function(_) {\n return arguments.length ? (extent4 = typeof _ === \"function\" ? _ : constant_default6([[+_[0][0], +_[0][1]], [+_[1][0], +_[1][1]]]), zoom2) : extent4;\n };\n zoom2.scaleExtent = function(_) {\n return arguments.length ? (scaleExtent[0] = +_[0], scaleExtent[1] = +_[1], zoom2) : [scaleExtent[0], scaleExtent[1]];\n };\n zoom2.translateExtent = function(_) {\n return arguments.length ? (translateExtent[0][0] = +_[0][0], translateExtent[1][0] = +_[1][0], translateExtent[0][1] = +_[0][1], translateExtent[1][1] = +_[1][1], zoom2) : [[translateExtent[0][0], translateExtent[0][1]], [translateExtent[1][0], translateExtent[1][1]]];\n };\n zoom2.constrain = function(_) {\n return arguments.length ? (constrain = _, zoom2) : constrain;\n };\n zoom2.duration = function(_) {\n return arguments.length ? (duration2 = +_, zoom2) : duration2;\n };\n zoom2.interpolate = function(_) {\n return arguments.length ? (interpolate = _, zoom2) : interpolate;\n };\n zoom2.on = function() {\n var value = listeners.on.apply(listeners, arguments);\n return value === listeners ? zoom2 : value;\n };\n zoom2.clickDistance = function(_) {\n return arguments.length ? (clickDistance2 = (_ = +_) * _, zoom2) : Math.sqrt(clickDistance2);\n };\n zoom2.tapDistance = function(_) {\n return arguments.length ? (tapDistance = +_, zoom2) : tapDistance;\n };\n return zoom2;\n}\n\n// ../../node_modules/@observablehq/plot/src/defined.js\nfunction defined(x3) {\n return x3 != null && !Number.isNaN(x3);\n}\nfunction ascendingDefined2(a2, b) {\n return +defined(b) - +defined(a2) || ascending(a2, b);\n}\nfunction descendingDefined(a2, b) {\n return +defined(b) - +defined(a2) || descending(a2, b);\n}\nfunction nonempty(x3) {\n return x3 != null && `${x3}` !== \"\";\n}\nfunction finite2(x3) {\n return isFinite(x3) ? x3 : NaN;\n}\nfunction positive(x3) {\n return x3 > 0 && isFinite(x3) ? x3 : NaN;\n}\nfunction negative(x3) {\n return x3 < 0 && isFinite(x3) ? x3 : NaN;\n}\n\n// ../../node_modules/isoformat/src/format.js\nfunction format2(date3, fallback) {\n if (!(date3 instanceof Date)) date3 = /* @__PURE__ */ new Date(+date3);\n if (isNaN(date3)) return typeof fallback === \"function\" ? fallback(date3) : fallback;\n const hours = date3.getUTCHours();\n const minutes = date3.getUTCMinutes();\n const seconds2 = date3.getUTCSeconds();\n const milliseconds2 = date3.getUTCMilliseconds();\n return `${formatYear2(date3.getUTCFullYear(), 4)}-${pad2(date3.getUTCMonth() + 1, 2)}-${pad2(date3.getUTCDate(), 2)}${hours || minutes || seconds2 || milliseconds2 ? `T${pad2(hours, 2)}:${pad2(minutes, 2)}${seconds2 || milliseconds2 ? `:${pad2(seconds2, 2)}${milliseconds2 ? `.${pad2(milliseconds2, 3)}` : ``}` : ``}Z` : ``}`;\n}\nfunction formatYear2(year) {\n return year < 0 ? `-${pad2(-year, 6)}` : year > 9999 ? `+${pad2(year, 6)}` : pad2(year, 4);\n}\nfunction pad2(value, width2) {\n return `${value}`.padStart(width2, \"0\");\n}\n\n// ../../node_modules/isoformat/src/parse.js\nvar re2 = /^(?:[-+]\\d{2})?\\d{4}(?:-\\d{2}(?:-\\d{2})?)?(?:T\\d{2}:\\d{2}(?::\\d{2}(?:\\.\\d{3})?)?(?:Z|[-+]\\d{2}:?\\d{2})?)?$/;\nfunction parse(string2, fallback) {\n if (!re2.test(string2 += \"\")) return typeof fallback === \"function\" ? fallback(string2) : fallback;\n return new Date(string2);\n}\n\n// ../../node_modules/@observablehq/plot/src/order.js\nfunction orderof(values2) {\n if (values2 == null) return;\n const first3 = values2[0];\n const last2 = values2[values2.length - 1];\n return descending(first3, last2);\n}\n\n// ../../node_modules/@observablehq/plot/src/time.js\nvar durationSecond2 = 1e3;\nvar durationMinute2 = durationSecond2 * 60;\nvar durationHour2 = durationMinute2 * 60;\nvar durationDay2 = durationHour2 * 24;\nvar durationWeek2 = durationDay2 * 7;\nvar durationMonth2 = durationDay2 * 30;\nvar durationYear2 = durationDay2 * 365;\nvar tickIntervals = [\n [\"millisecond\", 1],\n [\"2 milliseconds\", 2],\n [\"5 milliseconds\", 5],\n [\"10 milliseconds\", 10],\n [\"20 milliseconds\", 20],\n [\"50 milliseconds\", 50],\n [\"100 milliseconds\", 100],\n [\"200 milliseconds\", 200],\n [\"500 milliseconds\", 500],\n [\"second\", durationSecond2],\n [\"5 seconds\", 5 * durationSecond2],\n [\"15 seconds\", 15 * durationSecond2],\n [\"30 seconds\", 30 * durationSecond2],\n [\"minute\", durationMinute2],\n [\"5 minutes\", 5 * durationMinute2],\n [\"15 minutes\", 15 * durationMinute2],\n [\"30 minutes\", 30 * durationMinute2],\n [\"hour\", durationHour2],\n [\"3 hours\", 3 * durationHour2],\n [\"6 hours\", 6 * durationHour2],\n [\"12 hours\", 12 * durationHour2],\n [\"day\", durationDay2],\n [\"2 days\", 2 * durationDay2],\n [\"week\", durationWeek2],\n [\"2 weeks\", 2 * durationWeek2],\n // https://github.com/d3/d3-time/issues/46\n [\"month\", durationMonth2],\n [\"3 months\", 3 * durationMonth2],\n [\"6 months\", 6 * durationMonth2],\n // https://github.com/d3/d3-time/issues/46\n [\"year\", durationYear2],\n [\"2 years\", 2 * durationYear2],\n [\"5 years\", 5 * durationYear2],\n [\"10 years\", 10 * durationYear2],\n [\"20 years\", 20 * durationYear2],\n [\"50 years\", 50 * durationYear2],\n [\"100 years\", 100 * durationYear2]\n // TODO generalize to longer time scales\n];\nvar durations = /* @__PURE__ */ new Map([\n [\"second\", durationSecond2],\n [\"minute\", durationMinute2],\n [\"hour\", durationHour2],\n [\"day\", durationDay2],\n [\"monday\", durationWeek2],\n [\"tuesday\", durationWeek2],\n [\"wednesday\", durationWeek2],\n [\"thursday\", durationWeek2],\n [\"friday\", durationWeek2],\n [\"saturday\", durationWeek2],\n [\"sunday\", durationWeek2],\n [\"week\", durationWeek2],\n [\"month\", durationMonth2],\n [\"year\", durationYear2]\n]);\nvar timeIntervals = /* @__PURE__ */ new Map([\n [\"second\", second],\n [\"minute\", timeMinute],\n [\"hour\", timeHour],\n [\"day\", timeDay],\n // https://github.com/d3/d3-time/issues/62\n [\"monday\", timeMonday],\n [\"tuesday\", timeTuesday],\n [\"wednesday\", timeWednesday],\n [\"thursday\", timeThursday],\n [\"friday\", timeFriday],\n [\"saturday\", timeSaturday],\n [\"sunday\", timeSunday],\n [\"week\", timeSunday],\n [\"month\", timeMonth],\n [\"year\", timeYear]\n]);\nvar utcIntervals = /* @__PURE__ */ new Map([\n [\"second\", second],\n [\"minute\", utcMinute],\n [\"hour\", utcHour],\n [\"day\", unixDay],\n [\"monday\", utcMonday],\n [\"tuesday\", utcTuesday],\n [\"wednesday\", utcWednesday],\n [\"thursday\", utcThursday],\n [\"friday\", utcFriday],\n [\"saturday\", utcSaturday],\n [\"sunday\", utcSunday],\n [\"week\", utcSunday],\n [\"month\", utcMonth],\n [\"year\", utcYear]\n]);\nvar intervalDuration = Symbol(\"intervalDuration\");\nvar intervalType = Symbol(\"intervalType\");\nfor (const [name2, interval3] of timeIntervals) {\n interval3[intervalDuration] = durations.get(name2);\n interval3[intervalType] = \"time\";\n}\nfor (const [name2, interval3] of utcIntervals) {\n interval3[intervalDuration] = durations.get(name2);\n interval3[intervalType] = \"utc\";\n}\nvar utcFormatIntervals = [\n [\"year\", utcYear, \"utc\"],\n [\"month\", utcMonth, \"utc\"],\n [\"day\", unixDay, \"utc\", 6 * durationMonth2],\n [\"hour\", utcHour, \"utc\", 3 * durationDay2],\n [\"minute\", utcMinute, \"utc\", 6 * durationHour2],\n [\"second\", second, \"utc\", 30 * durationMinute2]\n];\nvar timeFormatIntervals = [\n [\"year\", timeYear, \"time\"],\n [\"month\", timeMonth, \"time\"],\n [\"day\", timeDay, \"time\", 6 * durationMonth2],\n [\"hour\", timeHour, \"time\", 3 * durationDay2],\n [\"minute\", timeMinute, \"time\", 6 * durationHour2],\n [\"second\", second, \"time\", 30 * durationMinute2]\n];\nvar formatIntervals = [\n utcFormatIntervals[0],\n timeFormatIntervals[0],\n utcFormatIntervals[1],\n timeFormatIntervals[1],\n utcFormatIntervals[2],\n timeFormatIntervals[2],\n // Below day, local time typically has an hourly offset from UTC and hence the\n // two are aligned and indistinguishable; therefore, we only consider UTC, and\n // we don’t consider these if the domain only has a single value.\n ...utcFormatIntervals.slice(3)\n];\nfunction parseTimeInterval(input3) {\n let name2 = `${input3}`.toLowerCase();\n if (name2.endsWith(\"s\")) name2 = name2.slice(0, -1);\n let period = 1;\n const match = /^(?:(\\d+)\\s+)/.exec(name2);\n if (match) {\n name2 = name2.slice(match[0].length);\n period = +match[1];\n }\n switch (name2) {\n case \"quarter\":\n name2 = \"month\";\n period *= 3;\n break;\n case \"half\":\n name2 = \"month\";\n period *= 6;\n break;\n }\n let interval3 = utcIntervals.get(name2);\n if (!interval3) throw new Error(`unknown interval: ${input3}`);\n if (period > 1 && !interval3.every) throw new Error(`non-periodic interval: ${name2}`);\n return [name2, period];\n}\nfunction timeInterval2(input3) {\n return asInterval(parseTimeInterval(input3), \"time\");\n}\nfunction utcInterval(input3) {\n return asInterval(parseTimeInterval(input3), \"utc\");\n}\nfunction asInterval([name2, period], type2) {\n let interval3 = (type2 === \"time\" ? timeIntervals : utcIntervals).get(name2);\n if (period > 1) {\n interval3 = interval3.every(period);\n interval3[intervalDuration] = durations.get(name2) * period;\n interval3[intervalType] = type2;\n }\n return interval3;\n}\nfunction generalizeTimeInterval(interval3, n) {\n if (!(n > 1)) return;\n const duration2 = interval3[intervalDuration];\n if (!tickIntervals.some(([, d]) => d === duration2)) return;\n if (duration2 % durationDay2 === 0 && durationDay2 < duration2 && duration2 < durationMonth2) return;\n const [i] = tickIntervals[bisector(([, step]) => Math.log(step)).center(tickIntervals, Math.log(duration2 * n))];\n return (interval3[intervalType] === \"time\" ? timeInterval2 : utcInterval)(i);\n}\nfunction formatTimeInterval(name2, type2, anchor) {\n const format3 = type2 === \"time\" ? timeFormat : utcFormat;\n if (anchor == null) {\n return format3(\n name2 === \"year\" ? \"%Y\" : name2 === \"month\" ? \"%Y-%m\" : name2 === \"day\" ? \"%Y-%m-%d\" : name2 === \"hour\" || name2 === \"minute\" ? \"%Y-%m-%dT%H:%M\" : name2 === \"second\" ? \"%Y-%m-%dT%H:%M:%S\" : \"%Y-%m-%dT%H:%M:%S.%L\"\n );\n }\n const template2 = getTimeTemplate(anchor);\n switch (name2) {\n case \"millisecond\":\n return formatConditional(format3(\".%L\"), format3(\":%M:%S\"), template2);\n case \"second\":\n return formatConditional(format3(\":%S\"), format3(\"%-I:%M\"), template2);\n case \"minute\":\n return formatConditional(format3(\"%-I:%M\"), format3(\"%p\"), template2);\n case \"hour\":\n return formatConditional(format3(\"%-I %p\"), format3(\"%b %-d\"), template2);\n case \"day\":\n return formatConditional(format3(\"%-d\"), format3(\"%b\"), template2);\n case \"month\":\n return formatConditional(format3(\"%b\"), format3(\"%Y\"), template2);\n case \"year\":\n return format3(\"%Y\");\n }\n throw new Error(\"unable to format time ticks\");\n}\nfunction getTimeTemplate(anchor) {\n return anchor === \"left\" || anchor === \"right\" ? (f1, f2) => `\n${f1}\n${f2}` : anchor === \"top\" ? (f1, f2) => `${f2}\n${f1}` : (f1, f2) => `${f1}\n${f2}`;\n}\nfunction getFormatIntervals(type2) {\n return type2 === \"time\" ? timeFormatIntervals : type2 === \"utc\" ? utcFormatIntervals : formatIntervals;\n}\nfunction inferTimeFormat(type2, dates, anchor) {\n const step = max2(pairs2(dates, (a2, b) => Math.abs(b - a2)));\n if (step < 1e3) return formatTimeInterval(\"millisecond\", \"utc\", anchor);\n for (const [name2, interval3, intervalType2, maxStep] of getFormatIntervals(type2)) {\n if (step > maxStep) break;\n if (name2 === \"hour\" && !step) break;\n if (dates.every((d) => interval3.floor(d) >= d)) return formatTimeInterval(name2, intervalType2, anchor);\n }\n}\nfunction formatConditional(format1, format22, template2) {\n return (x3, i, X3) => {\n const f1 = format1(x3, i);\n const f2 = format22(x3, i);\n const j = i - orderof(X3);\n return i !== j && X3[j] !== void 0 && f2 === format22(X3[j], j) ? f1 : template2(f1, f2);\n };\n}\n\n// ../../node_modules/@observablehq/plot/src/options.js\nvar TypedArray2 = Object.getPrototypeOf(Uint8Array);\nvar objectToString = Object.prototype.toString;\nfunction isArray2(value) {\n return value instanceof Array || value instanceof TypedArray2;\n}\nfunction isNumberArray2(value) {\n return value instanceof TypedArray2 && !isBigIntArray(value);\n}\nfunction isNumberType(type2) {\n return type2?.prototype instanceof TypedArray2 && !isBigIntType(type2);\n}\nfunction isBigIntArray(value) {\n return value instanceof BigInt64Array || value instanceof BigUint64Array;\n}\nfunction isBigIntType(type2) {\n return type2 === BigInt64Array || type2 === BigUint64Array;\n}\nvar reindex = Symbol(\"reindex\");\nfunction valueof(data, value, type2) {\n const valueType = typeof value;\n return valueType === \"string\" ? isArrowTable2(data) ? maybeTypedArrowify(data.getChild(value), type2) : maybeTypedMap(data, field2(value), type2) : valueType === \"function\" ? maybeTypedMap(data, value, type2) : valueType === \"number\" || value instanceof Date || valueType === \"boolean\" ? map3(data, constant(value), type2) : typeof value?.transform === \"function\" ? maybeTypedArrayify(value.transform(data), type2) : maybeTake(maybeTypedArrayify(value, type2), data?.[reindex]);\n}\nfunction maybeTake(values2, index2) {\n return values2 != null && index2 ? take(values2, index2) : values2;\n}\nfunction maybeTypedMap(data, f, type2) {\n return map3(data, isNumberType(type2) ? (d, i) => coerceNumber(f(d, i)) : f, type2);\n}\nfunction maybeTypedArrayify(data, type2) {\n return type2 === void 0 ? arrayify2(data) : isArrowVector(data) ? maybeTypedArrowify(data, type2) : data instanceof type2 ? data : type2.from(data, isNumberType(type2) && !isNumberArray2(data) ? coerceNumber : void 0);\n}\nfunction maybeTypedArrowify(vector3, type2) {\n return vector3 == null ? vector3 : (type2 === void 0 || type2 === Array) && isArrowDateType(vector3.type) ? coerceDates(vector3.toArray()) : maybeTypedArrayify(vector3.toArray(), type2);\n}\nvar singleton = [null];\nvar field2 = (name2) => (d) => {\n const v2 = d[name2];\n return v2 === void 0 && d.type === \"Feature\" ? d.properties?.[name2] : v2;\n};\nvar indexOf = { transform: range2 };\nvar identity7 = { transform: (d) => d };\nvar one2 = () => 1;\nvar yes = () => true;\nvar string = (x3) => x3 == null ? x3 : `${x3}`;\nvar number5 = (x3) => x3 == null ? x3 : +x3;\nvar first2 = (x3) => x3 ? x3[0] : void 0;\nvar second2 = (x3) => x3 ? x3[1] : void 0;\nvar third = (x3) => x3 ? x3[2] : void 0;\nvar constant = (x3) => () => x3;\nfunction percentile(reduce) {\n const p = +`${reduce}`.slice(1) / 100;\n return (I, f) => quantile2(I, p, f);\n}\nfunction coerceNumbers(values2) {\n return isNumberArray2(values2) ? values2 : map3(values2, coerceNumber, Float64Array);\n}\nfunction coerceNumber(x3) {\n return x3 == null ? NaN : Number(x3);\n}\nfunction coerceDates(values2) {\n return map3(values2, coerceDate);\n}\nfunction coerceDate(x3) {\n return x3 instanceof Date && !isNaN(x3) ? x3 : typeof x3 === \"string\" ? parse(x3) : x3 == null || isNaN(x3 = Number(x3)) ? void 0 : new Date(x3);\n}\nfunction maybeColorChannel(value, defaultValue) {\n if (value === void 0) value = defaultValue;\n return value === null ? [void 0, \"none\"] : isColor(value) ? [void 0, value] : [value, void 0];\n}\nfunction maybeNumberChannel(value, defaultValue) {\n if (value === void 0) value = defaultValue;\n return value === null || typeof value === \"number\" ? [void 0, value] : [value, void 0];\n}\nfunction maybeKeyword(input3, name2, allowed) {\n if (input3 != null) return keyword(input3, name2, allowed);\n}\nfunction keyword(input3, name2, allowed) {\n const i = `${input3}`.toLowerCase();\n if (!allowed.includes(i)) throw new Error(`invalid ${name2}: ${input3}`);\n return i;\n}\nfunction dataify(data) {\n return isArrowTable2(data) ? data : arrayify2(data);\n}\nfunction arrayify2(values2) {\n if (values2 == null || isArray2(values2)) return values2;\n if (isArrowVector(values2)) return maybeTypedArrowify(values2);\n switch (values2.type) {\n case \"FeatureCollection\":\n return values2.features;\n case \"GeometryCollection\":\n return values2.geometries;\n case \"Feature\":\n case \"LineString\":\n case \"MultiLineString\":\n case \"MultiPoint\":\n case \"MultiPolygon\":\n case \"Point\":\n case \"Polygon\":\n case \"Sphere\":\n return [values2];\n }\n return Array.from(values2);\n}\nfunction map3(values2, f, type2 = Array) {\n return values2 == null ? values2 : values2 instanceof type2 ? values2.map(f) : type2.from(values2, f);\n}\nfunction slice3(values2, type2 = Array) {\n return values2 instanceof type2 ? values2.slice() : type2.from(values2);\n}\nfunction hasX({ x: x3, x1: x12, x2: x22 }) {\n return x3 !== void 0 || x12 !== void 0 || x22 !== void 0;\n}\nfunction hasY({ y: y3, y1: y12, y2: y22 }) {\n return y3 !== void 0 || y12 !== void 0 || y22 !== void 0;\n}\nfunction hasXY(options) {\n return hasX(options) || hasY(options) || options.interval !== void 0;\n}\nfunction isObject(option) {\n return option?.toString === objectToString;\n}\nfunction isScaleOptions(option) {\n return isObject(option) && (option.type !== void 0 || option.domain !== void 0);\n}\nfunction isOptions(option) {\n return isObject(option) && typeof option.transform !== \"function\";\n}\nfunction isDomainSort(sort3) {\n return isOptions(sort3) && sort3.value === void 0 && sort3.channel === void 0;\n}\nfunction maybeZero(x3, x12, x22, x32 = identity7) {\n if (x12 === void 0 && x22 === void 0) {\n x12 = 0, x22 = x3 === void 0 ? x32 : x3;\n } else if (x12 === void 0) {\n x12 = x3 === void 0 ? 0 : x3;\n } else if (x22 === void 0) {\n x22 = x3 === void 0 ? 0 : x3;\n }\n return [x12, x22];\n}\nfunction maybeTuple(x3, y3) {\n return x3 === void 0 && y3 === void 0 ? [first2, second2] : [x3, y3];\n}\nfunction maybeZ({ z, fill, stroke } = {}) {\n if (z === void 0) [z] = maybeColorChannel(fill);\n if (z === void 0) [z] = maybeColorChannel(stroke);\n return z;\n}\nfunction lengthof(data) {\n return isArray2(data) ? data.length : data?.numRows;\n}\nfunction range2(data) {\n const n = lengthof(data);\n const r = new Uint32Array(n);\n for (let i = 0; i < n; ++i) r[i] = i;\n return r;\n}\nfunction take(values2, index2) {\n return isArray2(values2) ? map3(index2, (i) => values2[i], values2.constructor) : map3(index2, (i) => values2.at(i));\n}\nfunction taker(f) {\n return f.length === 1 ? (index2, values2) => f(take(values2, index2)) : f;\n}\nfunction subarray(I, i, j) {\n return I.subarray ? I.subarray(i, j) : I.slice(i, j);\n}\nfunction keyof2(value) {\n return value !== null && typeof value === \"object\" ? value.valueOf() : value;\n}\nfunction maybeInput(key, options) {\n if (options[key] !== void 0) return options[key];\n switch (key) {\n case \"x1\":\n case \"x2\":\n key = \"x\";\n break;\n case \"y1\":\n case \"y2\":\n key = \"y\";\n break;\n }\n return options[key];\n}\nfunction column2(source) {\n let value;\n return [\n {\n transform: () => value,\n label: labelof(source)\n },\n (v2) => value = v2\n ];\n}\nfunction maybeColumn(source) {\n return source == null ? [source] : column2(source);\n}\nfunction labelof(value, defaultValue) {\n return typeof value === \"string\" ? value : value && value.label !== void 0 ? value.label : defaultValue;\n}\nfunction mid(x12, x22) {\n return {\n transform(data) {\n const X13 = x12.transform(data);\n const X23 = x22.transform(data);\n return isTemporal(X13) || isTemporal(X23) ? map3(X13, (_, i) => new Date((+X13[i] + +X23[i]) / 2)) : map3(X13, (_, i) => (+X13[i] + +X23[i]) / 2, Float64Array);\n },\n label: x12.label\n };\n}\nfunction maybeApplyInterval(V, scale3) {\n const t = maybeIntervalTransform(scale3?.interval, scale3?.type);\n return t ? map3(V, t) : V;\n}\nfunction maybeIntervalTransform(interval3, type2) {\n const i = maybeInterval(interval3, type2);\n return i && ((v2) => defined(v2) ? i.floor(v2) : v2);\n}\nfunction maybeInterval(interval3, type2) {\n if (interval3 == null) return;\n if (typeof interval3 === \"number\") return numberInterval(interval3);\n if (typeof interval3 === \"string\") return (type2 === \"time\" ? timeInterval2 : utcInterval)(interval3);\n if (typeof interval3.floor !== \"function\") throw new Error(\"invalid interval; missing floor method\");\n if (typeof interval3.offset !== \"function\") throw new Error(\"invalid interval; missing offset method\");\n return interval3;\n}\nfunction numberInterval(interval3) {\n interval3 = +interval3;\n if (0 < interval3 && interval3 < 1 && Number.isInteger(1 / interval3)) interval3 = -1 / interval3;\n const n = Math.abs(interval3);\n return interval3 < 0 ? {\n floor: (d) => Math.floor(d * n) / n,\n offset: (d, s2 = 1) => (d * n + Math.floor(s2)) / n,\n range: (lo, hi) => range(Math.ceil(lo * n), hi * n).map((x3) => x3 / n)\n } : {\n floor: (d) => Math.floor(d / n) * n,\n offset: (d, s2 = 1) => d + n * Math.floor(s2),\n range: (lo, hi) => range(Math.ceil(lo / n), hi / n).map((x3) => x3 * n)\n };\n}\nfunction maybeRangeInterval(interval3, type2) {\n interval3 = maybeInterval(interval3, type2);\n if (interval3 && typeof interval3.range !== \"function\") throw new Error(\"invalid interval: missing range method\");\n return interval3;\n}\nfunction maybeNiceInterval(interval3, type2) {\n interval3 = maybeRangeInterval(interval3, type2);\n if (interval3 && typeof interval3.ceil !== \"function\") throw new Error(\"invalid interval: missing ceil method\");\n return interval3;\n}\nfunction isTimeInterval(t) {\n return isInterval(t) && typeof t?.floor === \"function\" && t.floor() instanceof Date;\n}\nfunction isInterval(t) {\n return typeof t?.range === \"function\";\n}\nfunction maybeValue(value) {\n return value === void 0 || isOptions(value) ? value : { value };\n}\nfunction numberChannel(source) {\n return source == null ? null : {\n transform: (data) => valueof(data, source, Float64Array),\n label: labelof(source)\n };\n}\nfunction isTuples(data) {\n if (!isIterable(data)) return false;\n for (const d of data) {\n if (d == null) continue;\n return typeof d === \"object\" && \"0\" in d && \"1\" in d;\n }\n}\nfunction isIterable(value) {\n return value && typeof value[Symbol.iterator] === \"function\";\n}\nfunction isTextual(values2) {\n for (const value of values2) {\n if (value == null) continue;\n return typeof value !== \"object\" || value instanceof Date;\n }\n}\nfunction isOrdinal(values2) {\n for (const value of values2) {\n if (value == null) continue;\n const type2 = typeof value;\n return type2 === \"string\" || type2 === \"boolean\";\n }\n}\nfunction isTemporal(values2) {\n for (const value of values2) {\n if (value == null) continue;\n return value instanceof Date;\n }\n}\nfunction isTemporalString(values2) {\n for (const value of values2) {\n if (value == null) continue;\n return typeof value === \"string\" && isNaN(value) && parse(value);\n }\n}\nfunction isNumericString(values2) {\n for (const value of values2) {\n if (value == null) continue;\n if (typeof value !== \"string\") return false;\n if (!value.trim()) continue;\n return !isNaN(value);\n }\n}\nfunction isNumeric(values2) {\n for (const value of values2) {\n if (value == null) continue;\n return typeof value === \"number\";\n }\n}\nfunction isEvery(values2, is) {\n let every;\n for (const value of values2) {\n if (value == null) continue;\n if (!is(value)) return false;\n every = true;\n }\n return every;\n}\nvar namedColors = new Set(\"none,currentcolor,transparent,aliceblue,antiquewhite,aqua,aquamarine,azure,beige,bisque,black,blanchedalmond,blue,blueviolet,brown,burlywood,cadetblue,chartreuse,chocolate,coral,cornflowerblue,cornsilk,crimson,cyan,darkblue,darkcyan,darkgoldenrod,darkgray,darkgreen,darkgrey,darkkhaki,darkmagenta,darkolivegreen,darkorange,darkorchid,darkred,darksalmon,darkseagreen,darkslateblue,darkslategray,darkslategrey,darkturquoise,darkviolet,deeppink,deepskyblue,dimgray,dimgrey,dodgerblue,firebrick,floralwhite,forestgreen,fuchsia,gainsboro,ghostwhite,gold,goldenrod,gray,green,greenyellow,grey,honeydew,hotpink,indianred,indigo,ivory,khaki,lavender,lavenderblush,lawngreen,lemonchiffon,lightblue,lightcoral,lightcyan,lightgoldenrodyellow,lightgray,lightgreen,lightgrey,lightpink,lightsalmon,lightseagreen,lightskyblue,lightslategray,lightslategrey,lightsteelblue,lightyellow,lime,limegreen,linen,magenta,maroon,mediumaquamarine,mediumblue,mediumorchid,mediumpurple,mediumseagreen,mediumslateblue,mediumspringgreen,mediumturquoise,mediumvioletred,midnightblue,mintcream,mistyrose,moccasin,navajowhite,navy,oldlace,olive,olivedrab,orange,orangered,orchid,palegoldenrod,palegreen,paleturquoise,palevioletred,papayawhip,peachpuff,peru,pink,plum,powderblue,purple,rebeccapurple,red,rosybrown,royalblue,saddlebrown,salmon,sandybrown,seagreen,seashell,sienna,silver,skyblue,slateblue,slategray,slategrey,snow,springgreen,steelblue,tan,teal,thistle,tomato,turquoise,violet,wheat,white,whitesmoke,yellow\".split(\",\"));\nfunction isColor(value) {\n if (typeof value !== \"string\") return false;\n value = value.toLowerCase().trim();\n return /^#[0-9a-f]{3,8}$/.test(value) || // hex rgb, rgba, rrggbb, rrggbbaa\n /^(?:url|var|rgb|rgba|hsl|hsla|hwb|lab|lch|oklab|oklch|color|color-mix)\\(.*\\)$/.test(value) || // , CSS variable, color, etc.\n namedColors.has(value);\n}\nfunction isOpacity(value) {\n return typeof value === \"number\" && (0 <= value && value <= 1 || isNaN(value));\n}\nfunction isNoneish(value) {\n return value == null || isNone(value);\n}\nfunction isNone(value) {\n return /^\\s*none\\s*$/i.test(value);\n}\nfunction isRound(value) {\n return /^\\s*round\\s*$/i.test(value);\n}\nfunction maybeAnchor(value, name2) {\n return maybeKeyword(value, name2, [\n \"middle\",\n \"top-left\",\n \"top\",\n \"top-right\",\n \"right\",\n \"bottom-right\",\n \"bottom\",\n \"bottom-left\",\n \"left\"\n ]);\n}\nfunction maybeFrameAnchor(value = \"middle\") {\n return maybeAnchor(value, \"frameAnchor\");\n}\nfunction inherit2(options = {}, ...rest) {\n let o = options;\n for (const defaults22 of rest) {\n for (const key in defaults22) {\n if (o[key] === void 0) {\n const value = defaults22[key];\n if (o === options) o = { ...o, [key]: value };\n else o[key] = value;\n }\n }\n }\n return o;\n}\nfunction named2(things) {\n console.warn(\"named iterables are deprecated; please use an object instead\");\n const names = /* @__PURE__ */ new Set();\n return Object.fromEntries(\n Array.from(things, (thing) => {\n const { name: name2 } = thing;\n if (name2 == null) throw new Error(\"missing name\");\n const key = `${name2}`;\n if (key === \"__proto__\") throw new Error(`illegal name: ${key}`);\n if (names.has(key)) throw new Error(`duplicate name: ${key}`);\n names.add(key);\n return [name2, thing];\n })\n );\n}\nfunction maybeNamed(things) {\n return isIterable(things) ? named2(things) : things;\n}\nfunction maybeClip(clip) {\n if (clip === true) clip = \"frame\";\n else if (clip === false) clip = null;\n else if (clip != null) clip = keyword(clip, \"clip\", [\"frame\", \"sphere\"]);\n return clip;\n}\nfunction isArrowTable2(value) {\n return value && typeof value.getChild === \"function\" && typeof value.toArray === \"function\" && value.schema && Array.isArray(value.schema.fields);\n}\nfunction isArrowVector(value) {\n return value && typeof value.toArray === \"function\" && value.type;\n}\nfunction isArrowDateType(type2) {\n return type2 && (type2.typeId === 8 || // date\n type2.typeId === 10) && // timestamp\n type2.unit === 1;\n}\n\n// ../../node_modules/@observablehq/plot/src/scales/index.js\nvar position = Symbol(\"position\");\nvar color2 = Symbol(\"color\");\nvar radius = Symbol(\"radius\");\nvar length3 = Symbol(\"length\");\nvar opacity = Symbol(\"opacity\");\nvar symbol = Symbol(\"symbol\");\nvar projection2 = Symbol(\"projection\");\nvar registry = /* @__PURE__ */ new Map([\n [\"x\", position],\n [\"y\", position],\n [\"fx\", position],\n [\"fy\", position],\n [\"r\", radius],\n [\"color\", color2],\n [\"opacity\", opacity],\n [\"symbol\", symbol],\n [\"length\", length3],\n [\"projection\", projection2]\n]);\nfunction isPosition(kind) {\n return kind === position || kind === projection2;\n}\nfunction hasNumericRange(kind) {\n return kind === position || kind === radius || kind === length3 || kind === opacity;\n}\n\n// ../../node_modules/@observablehq/plot/src/symbol.js\nvar sqrt35 = Math.sqrt(3);\nvar sqrt4_3 = 2 / sqrt35;\nvar symbolHexagon = {\n draw(context, size) {\n const rx = Math.sqrt(size / Math.PI), ry = rx * sqrt4_3, hy = ry / 2;\n context.moveTo(0, ry);\n context.lineTo(rx, hy);\n context.lineTo(rx, -hy);\n context.lineTo(0, -ry);\n context.lineTo(-rx, -hy);\n context.lineTo(-rx, hy);\n context.closePath();\n }\n};\nvar symbols = /* @__PURE__ */ new Map([\n [\"asterisk\", asterisk_default],\n [\"circle\", circle_default2],\n [\"cross\", cross_default],\n [\"diamond\", diamond_default],\n [\"diamond2\", diamond2_default],\n [\"hexagon\", symbolHexagon],\n [\"plus\", plus_default],\n [\"square\", square_default],\n [\"square2\", square2_default],\n [\"star\", star_default],\n [\"times\", times_default],\n [\"triangle\", triangle_default],\n [\"triangle2\", triangle2_default],\n [\"wye\", wye_default]\n]);\nfunction isSymbolObject(value) {\n return value && typeof value.draw === \"function\";\n}\nfunction isSymbol(value) {\n if (isSymbolObject(value)) return true;\n if (typeof value !== \"string\") return false;\n return symbols.has(value.toLowerCase());\n}\nfunction maybeSymbol(symbol2) {\n if (symbol2 == null || isSymbolObject(symbol2)) return symbol2;\n const value = symbols.get(`${symbol2}`.toLowerCase());\n if (value) return value;\n throw new Error(`invalid symbol: ${symbol2}`);\n}\nfunction maybeSymbolChannel(symbol2) {\n if (symbol2 == null || isSymbolObject(symbol2)) return [void 0, symbol2];\n if (typeof symbol2 === \"string\") {\n const value = symbols.get(`${symbol2}`.toLowerCase());\n if (value) return [void 0, value];\n }\n return [symbol2, void 0];\n}\n\n// ../../node_modules/@observablehq/plot/src/transforms/basic.js\nfunction basic({ filter: f1, sort: s1, reverse: r1, transform: t13, initializer: i1, ...options } = {}, transform3) {\n if (t13 === void 0) {\n if (f1 != null) t13 = filterTransform(f1);\n if (s1 != null && !isDomainSort(s1)) t13 = composeTransform(t13, sortTransform(s1));\n if (r1) t13 = composeTransform(t13, reverseTransform);\n }\n if (transform3 != null && i1 != null) throw new Error(\"transforms cannot be applied after initializers\");\n return {\n ...options,\n ...(s1 === null || isDomainSort(s1)) && { sort: s1 },\n transform: composeTransform(t13, transform3)\n };\n}\nfunction initializer({ filter: f1, sort: s1, reverse: r1, initializer: i1, ...options } = {}, initializer2) {\n if (i1 === void 0) {\n if (f1 != null) i1 = filterTransform(f1);\n if (s1 != null && !isDomainSort(s1)) i1 = composeInitializer(i1, sortTransform(s1));\n if (r1) i1 = composeInitializer(i1, reverseTransform);\n }\n return {\n ...options,\n ...(s1 === null || isDomainSort(s1)) && { sort: s1 },\n initializer: composeInitializer(i1, initializer2)\n };\n}\nfunction composeTransform(t13, t22) {\n if (t13 == null) return t22 === null ? void 0 : t22;\n if (t22 == null) return t13 === null ? void 0 : t13;\n return function(data, facets, plotOptions) {\n ({ data, facets } = t13.call(this, data, facets, plotOptions));\n return t22.call(this, dataify(data), facets, plotOptions);\n };\n}\nfunction composeInitializer(i1, i2) {\n if (i1 == null) return i2 === null ? void 0 : i2;\n if (i2 == null) return i1 === null ? void 0 : i1;\n return function(data, facets, channels, ...args) {\n let c1, d1, f1, c22, d2, f2;\n ({ data: d1 = data, facets: f1 = facets, channels: c1 } = i1.call(this, data, facets, channels, ...args));\n ({ data: d2 = d1, facets: f2 = f1, channels: c22 } = i2.call(this, d1, f1, { ...channels, ...c1 }, ...args));\n return { data: d2, facets: f2, channels: { ...c1, ...c22 } };\n };\n}\nfunction apply(options, t) {\n return (options.initializer != null ? initializer : basic)(options, t);\n}\nfunction filter2(test, options) {\n return apply(options, filterTransform(test));\n}\nfunction filterTransform(value) {\n return (data, facets) => {\n const V = valueof(data, value);\n return { data, facets: facets.map((I) => I.filter((i) => V[i])) };\n };\n}\nfunction reverse2({ sort: sort3, ...options } = {}) {\n return {\n ...apply(options, reverseTransform),\n sort: isDomainSort(sort3) ? sort3 : null\n };\n}\nfunction reverseTransform(data, facets) {\n return { data, facets: facets.map((I) => I.slice().reverse()) };\n}\nfunction shuffle({ seed, sort: sort3, ...options } = {}) {\n return {\n ...apply(options, sortValue(seed == null ? Math.random : lcg(seed))),\n sort: isDomainSort(sort3) ? sort3 : null\n };\n}\nfunction sort2(order, { sort: sort3, ...options } = {}) {\n return {\n ...(isOptions(order) && order.channel !== void 0 ? initializer : apply)(options, sortTransform(order)),\n sort: isDomainSort(sort3) ? sort3 : null\n };\n}\nfunction sortTransform(value) {\n return (typeof value === \"function\" && value.length !== 1 ? sortData : sortValue)(value);\n}\nfunction sortData(compare) {\n return (data, facets) => {\n const compareData = isArray2(data) ? (i, j) => compare(data[i], data[j]) : (i, j) => compare(data.get(i), data.get(j));\n return { data, facets: facets.map((I) => I.slice().sort(compareData)) };\n };\n}\nfunction sortValue(value) {\n let channel, order;\n ({ channel, value, order } = { ...maybeValue(value) });\n const negate2 = channel?.startsWith(\"-\");\n if (negate2) channel = channel.slice(1);\n if (order === void 0) order = negate2 ? descendingDefined : ascendingDefined2;\n if (typeof order !== \"function\") {\n switch (`${order}`.toLowerCase()) {\n case \"ascending\":\n order = ascendingDefined2;\n break;\n case \"descending\":\n order = descendingDefined;\n break;\n default:\n throw new Error(`invalid order: ${order}`);\n }\n }\n return (data, facets, channels) => {\n let V;\n if (channel === void 0) {\n V = valueof(data, value);\n } else {\n if (channels === void 0) throw new Error(\"channel sort requires an initializer\");\n V = channels[channel];\n if (!V) return {};\n V = V.value;\n }\n const compareValue = (i, j) => order(V[i], V[j]);\n return { data, facets: facets.map((I) => I.slice().sort(compareValue)) };\n };\n}\n\n// ../../node_modules/@observablehq/plot/src/transforms/group.js\nfunction groupZ(outputs, options) {\n return groupn(null, null, outputs, options);\n}\nfunction groupX(outputs = { y: \"count\" }, options = {}) {\n const { x: x3 = identity7 } = options;\n if (x3 == null) throw new Error(\"missing channel: x\");\n return groupn(x3, null, outputs, options);\n}\nfunction groupY(outputs = { x: \"count\" }, options = {}) {\n const { y: y3 = identity7 } = options;\n if (y3 == null) throw new Error(\"missing channel: y\");\n return groupn(null, y3, outputs, options);\n}\nfunction group2(outputs = { fill: \"count\" }, options = {}) {\n let { x: x3, y: y3 } = options;\n [x3, y3] = maybeTuple(x3, y3);\n if (x3 == null) throw new Error(\"missing channel: x\");\n if (y3 == null) throw new Error(\"missing channel: y\");\n return groupn(x3, y3, outputs, options);\n}\nfunction groupn(x3, y3, {\n data: reduceData = reduceIdentity,\n filter: filter3,\n sort: sort3,\n reverse: reverse3,\n ...outputs\n // output channel definitions\n} = {}, inputs = {}) {\n outputs = maybeGroupOutputs(outputs, inputs);\n reduceData = maybeGroupReduce(reduceData, identity7);\n sort3 = sort3 == null ? void 0 : maybeGroupOutput(\"sort\", sort3, inputs);\n filter3 = filter3 == null ? void 0 : maybeGroupEvaluator(\"filter\", filter3, inputs);\n const [GX, setGX] = maybeColumn(x3);\n const [GY, setGY] = maybeColumn(y3);\n const {\n z,\n fill,\n stroke,\n x1: x12,\n x2: x22,\n // consumed if x is an output\n y1: y12,\n y2: y22,\n // consumed if y is an output\n ...options\n } = inputs;\n const [GZ, setGZ] = maybeColumn(z);\n const [vfill] = maybeColorChannel(fill);\n const [vstroke] = maybeColorChannel(stroke);\n const [GF, setGF] = maybeColumn(vfill);\n const [GS, setGS] = maybeColumn(vstroke);\n return {\n ...\"z\" in inputs && { z: GZ || z },\n ...\"fill\" in inputs && { fill: GF || fill },\n ...\"stroke\" in inputs && { stroke: GS || stroke },\n ...basic(options, (data, facets, plotOptions) => {\n const X3 = maybeApplyInterval(valueof(data, x3), plotOptions?.x);\n const Y3 = maybeApplyInterval(valueof(data, y3), plotOptions?.y);\n const Z = valueof(data, z);\n const F = valueof(data, vfill);\n const S = valueof(data, vstroke);\n const G = maybeSubgroup(outputs, { z: Z, fill: F, stroke: S });\n const groupFacets = [];\n const groupData = [];\n const GX2 = X3 && setGX([]);\n const GY2 = Y3 && setGY([]);\n const GZ2 = Z && setGZ([]);\n const GF2 = F && setGF([]);\n const GS2 = S && setGS([]);\n let i = 0;\n for (const o of outputs) o.initialize(data);\n if (sort3) sort3.initialize(data);\n if (filter3) filter3.initialize(data);\n for (const facet of facets) {\n const groupFacet = [];\n for (const o of outputs) o.scope(\"facet\", facet);\n if (sort3) sort3.scope(\"facet\", facet);\n if (filter3) filter3.scope(\"facet\", facet);\n for (const [f, I] of maybeGroup(facet, G)) {\n for (const [y4, gg] of maybeGroup(I, Y3)) {\n for (const [x4, g] of maybeGroup(gg, X3)) {\n const extent4 = { data };\n if (X3) extent4.x = x4;\n if (Y3) extent4.y = y4;\n if (G) extent4.z = f;\n if (filter3 && !filter3.reduce(g, extent4)) continue;\n groupFacet.push(i++);\n groupData.push(reduceData.reduceIndex(g, data, extent4));\n if (X3) GX2.push(x4);\n if (Y3) GY2.push(y4);\n if (Z) GZ2.push(G === Z ? f : Z[g[0]]);\n if (F) GF2.push(G === F ? f : F[g[0]]);\n if (S) GS2.push(G === S ? f : S[g[0]]);\n for (const o of outputs) o.reduce(g, extent4);\n if (sort3) sort3.reduce(g, extent4);\n }\n }\n }\n groupFacets.push(groupFacet);\n }\n maybeSort(groupFacets, sort3, reverse3);\n return { data: groupData, facets: groupFacets };\n }),\n ...!hasOutput(outputs, \"x\") && (GX ? { x: GX } : { x1: x12, x2: x22 }),\n ...!hasOutput(outputs, \"y\") && (GY ? { y: GY } : { y1: y12, y2: y22 }),\n ...Object.fromEntries(outputs.map(({ name: name2, output }) => [name2, output]))\n };\n}\nfunction hasOutput(outputs, ...names) {\n for (const { name: name2 } of outputs) {\n if (names.includes(name2)) {\n return true;\n }\n }\n return false;\n}\nfunction maybeOutputs(outputs, inputs, asOutput = maybeOutput) {\n const entries = Object.entries(outputs);\n if (inputs.title != null && outputs.title === void 0) entries.push([\"title\", reduceTitle]);\n if (inputs.href != null && outputs.href === void 0) entries.push([\"href\", reduceFirst]);\n return entries.filter(([, reduce]) => reduce !== void 0).map(([name2, reduce]) => reduce === null ? nullOutput(name2) : asOutput(name2, reduce, inputs));\n}\nfunction maybeOutput(name2, reduce, inputs, asEvaluator = maybeEvaluator) {\n let scale3;\n if (isObject(reduce) && \"reduce\" in reduce) scale3 = reduce.scale, reduce = reduce.reduce;\n const evaluator = asEvaluator(name2, reduce, inputs);\n const [output, setOutput] = column2(evaluator.label);\n let O;\n return {\n name: name2,\n output: scale3 === void 0 ? output : { value: output, scale: scale3 },\n initialize(data) {\n evaluator.initialize(data);\n O = setOutput([]);\n },\n scope(scope, I) {\n evaluator.scope(scope, I);\n },\n reduce(I, extent4) {\n O.push(evaluator.reduce(I, extent4));\n }\n };\n}\nfunction nullOutput(name2) {\n return { name: name2, initialize() {\n }, scope() {\n }, reduce() {\n } };\n}\nfunction maybeEvaluator(name2, reduce, inputs, asReduce = maybeReduce) {\n const input3 = maybeInput(name2, inputs);\n const reducer2 = asReduce(reduce, input3);\n let V, context;\n return {\n label: labelof(reducer2 === reduceCount ? null : input3, reducer2.label),\n initialize(data) {\n V = input3 === void 0 ? data : valueof(data, input3);\n if (reducer2.scope === \"data\") {\n context = reducer2.reduceIndex(range2(data), V);\n }\n },\n scope(scope, I) {\n if (reducer2.scope === scope) {\n context = reducer2.reduceIndex(I, V);\n }\n },\n reduce(I, extent4) {\n return reducer2.scope == null ? reducer2.reduceIndex(I, V, extent4) : reducer2.reduceIndex(I, V, context, extent4);\n }\n };\n}\nfunction maybeGroup(I, X3) {\n return X3 ? group(I, (i) => X3[i]) : [[, I]];\n}\nfunction maybeReduce(reduce, value, fallback = invalidReduce) {\n if (reduce == null) return fallback(reduce);\n if (typeof reduce.reduceIndex === \"function\") return reduce;\n if (typeof reduce.reduce === \"function\" && isObject(reduce)) return reduceReduce(reduce);\n if (typeof reduce === \"function\") return reduceFunction(reduce);\n if (/^p\\d{2}$/i.test(reduce)) return reduceAccessor(percentile(reduce));\n switch (`${reduce}`.toLowerCase()) {\n case \"first\":\n return reduceFirst;\n case \"last\":\n return reduceLast;\n case \"identity\":\n return reduceIdentity;\n case \"count\":\n return reduceCount;\n case \"distinct\":\n return reduceDistinct;\n case \"sum\":\n return value == null ? reduceCount : reduceSum;\n case \"proportion\":\n return reduceProportion(value, \"data\");\n case \"proportion-facet\":\n return reduceProportion(value, \"facet\");\n case \"deviation\":\n return reduceAccessor(deviation);\n case \"min\":\n return reduceAccessor(min2);\n case \"min-index\":\n return reduceAccessor(minIndex);\n case \"max\":\n return reduceAccessor(max2);\n case \"max-index\":\n return reduceAccessor(maxIndex);\n case \"mean\":\n return reduceMaybeTemporalAccessor(mean2);\n case \"median\":\n return reduceMaybeTemporalAccessor(median2);\n case \"variance\":\n return reduceAccessor(variance2);\n case \"mode\":\n return reduceAccessor(mode2);\n }\n return fallback(reduce);\n}\nfunction invalidReduce(reduce) {\n throw new Error(`invalid reduce: ${reduce}`);\n}\nfunction maybeGroupOutputs(outputs, inputs) {\n return maybeOutputs(outputs, inputs, maybeGroupOutput);\n}\nfunction maybeGroupOutput(name2, reduce, inputs) {\n return maybeOutput(name2, reduce, inputs, maybeGroupEvaluator);\n}\nfunction maybeGroupEvaluator(name2, reduce, inputs) {\n return maybeEvaluator(name2, reduce, inputs, maybeGroupReduce);\n}\nfunction maybeGroupReduce(reduce, value) {\n return maybeReduce(reduce, value, maybeGroupReduceFallback);\n}\nfunction maybeGroupReduceFallback(reduce) {\n switch (`${reduce}`.toLowerCase()) {\n case \"x\":\n return reduceX;\n case \"y\":\n return reduceY;\n case \"z\":\n return reduceZ;\n }\n throw new Error(`invalid group reduce: ${reduce}`);\n}\nfunction maybeSubgroup(outputs, inputs) {\n for (const name2 in inputs) {\n const value = inputs[name2];\n if (value !== void 0 && !outputs.some((o) => o.name === name2)) {\n return value;\n }\n }\n}\nfunction maybeSort(facets, sort3, reverse3) {\n if (sort3) {\n const S = sort3.output.transform();\n const compare = (i, j) => ascendingDefined2(S[i], S[j]);\n facets.forEach((f) => f.sort(compare));\n }\n if (reverse3) {\n facets.forEach((f) => f.reverse());\n }\n}\nfunction reduceReduce(reduce) {\n console.warn(\"deprecated reduce interface; implement reduceIndex instead.\");\n return { ...reduce, reduceIndex: reduce.reduce.bind(reduce) };\n}\nfunction reduceFunction(f) {\n return {\n reduceIndex(I, X3, extent4) {\n return f(take(X3, I), extent4);\n }\n };\n}\nfunction reduceAccessor(f) {\n return {\n reduceIndex(I, X3) {\n return f(I, (i) => X3[i]);\n }\n };\n}\nfunction reduceMaybeTemporalAccessor(f) {\n return {\n reduceIndex(I, X3) {\n const x3 = f(I, (i) => X3[i]);\n return isTemporal(X3) ? new Date(x3) : x3;\n }\n };\n}\nvar reduceIdentity = {\n reduceIndex(I, X3) {\n return take(X3, I);\n }\n};\nvar reduceFirst = {\n reduceIndex(I, X3) {\n return X3[I[0]];\n }\n};\nvar reduceTitle = {\n reduceIndex(I, X3) {\n const n = 5;\n const groups2 = sort(\n rollup(\n I,\n (V) => V.length,\n (i) => X3[i]\n ),\n second2\n );\n const top2 = groups2.slice(-n).reverse();\n if (top2.length < groups2.length) {\n const bottom2 = groups2.slice(0, 1 - n);\n top2[n - 1] = [`\\u2026 ${bottom2.length.toLocaleString(\"en-US\")} more`, sum2(bottom2, second2)];\n }\n return top2.map(([key, value]) => `${key} (${value.toLocaleString(\"en-US\")})`).join(\"\\n\");\n }\n};\nvar reduceLast = {\n reduceIndex(I, X3) {\n return X3[I[I.length - 1]];\n }\n};\nvar reduceCount = {\n label: \"Frequency\",\n reduceIndex(I) {\n return I.length;\n }\n};\nvar reduceDistinct = {\n label: \"Distinct\",\n reduceIndex(I, X3) {\n const s2 = new InternSet();\n for (const i of I) s2.add(X3[i]);\n return s2.size;\n }\n};\nvar reduceSum = reduceAccessor(sum2);\nfunction reduceProportion(value, scope) {\n return value == null ? { scope, label: \"Frequency\", reduceIndex: (I, V, basis2 = 1) => I.length / basis2 } : { scope, reduceIndex: (I, V, basis2 = 1) => sum2(I, (i) => V[i]) / basis2 };\n}\nvar reduceX = {\n reduceIndex(I, X3, { x: x3 }) {\n return x3;\n }\n};\nvar reduceY = {\n reduceIndex(I, X3, { y: y3 }) {\n return y3;\n }\n};\nvar reduceZ = {\n reduceIndex(I, X3, { z }) {\n return z;\n }\n};\nfunction find2(test) {\n if (typeof test !== \"function\") throw new Error(`invalid test function: ${test}`);\n return {\n reduceIndex(I, V, { data }) {\n return V[I.find(isArray2(data) ? (i) => test(data[i], i, data) : (i) => test(data.get(i), i, data))];\n }\n };\n}\n\n// ../../node_modules/@observablehq/plot/src/channel.js\nfunction createChannel(data, { scale: scale3, type: type2, value, filter: filter3, hint, label: label2 = labelof(value) }, name2) {\n if (hint === void 0 && typeof value?.transform === \"function\") hint = value.hint;\n const cs = inferChannelScale(name2, {\n scale: scale3,\n type: type2,\n value: valueof(data, value),\n label: label2,\n filter: filter3,\n hint\n });\n return cs;\n}\nfunction createChannels(channels, data) {\n return Object.fromEntries(\n Object.entries(channels).map(([name2, channel]) => [name2, createChannel(data, channel, name2)])\n );\n}\nfunction valueObject(channels, scales2) {\n const values2 = Object.fromEntries(\n Object.entries(channels).map(([name2, { scale: scaleName, value }]) => {\n const scale3 = scaleName == null ? null : scales2[scaleName];\n return [name2, scale3 == null ? value : map3(value, scale3)];\n })\n );\n values2.channels = channels;\n return values2;\n}\nfunction inferChannelScale(name2, channel) {\n const { scale: scale3, value } = channel;\n if (scale3 === true || scale3 === \"auto\") {\n switch (name2) {\n case \"fill\":\n case \"stroke\":\n case \"color\":\n channel.scale = scale3 !== true && isEvery(value, isColor) ? null : \"color\";\n channel.defaultScale = \"color\";\n break;\n case \"fillOpacity\":\n case \"strokeOpacity\":\n case \"opacity\":\n channel.scale = scale3 !== true && isEvery(value, isOpacity) ? null : \"opacity\";\n channel.defaultScale = \"opacity\";\n break;\n case \"symbol\":\n if (scale3 !== true && isEvery(value, isSymbol)) {\n channel.scale = null;\n channel.value = map3(value, maybeSymbol);\n } else {\n channel.scale = \"symbol\";\n }\n channel.defaultScale = \"symbol\";\n break;\n default:\n channel.scale = registry.has(name2) ? name2 : null;\n break;\n }\n } else if (scale3 === false) {\n channel.scale = null;\n } else if (scale3 != null && !registry.has(scale3)) {\n throw new Error(`unknown scale: ${scale3}`);\n }\n return channel;\n}\nfunction channelDomain(data, facets, channels, facetChannels, options) {\n const { order: defaultOrder, reverse: defaultReverse, reduce: defaultReduce = true, limit: defaultLimit } = options;\n for (const x3 in options) {\n if (!registry.has(x3)) continue;\n let { value: y3, order = defaultOrder, reverse: reverse3 = defaultReverse, reduce = defaultReduce, limit = defaultLimit } = maybeValue(options[x3]);\n const negate2 = y3?.startsWith(\"-\");\n if (negate2) y3 = y3.slice(1);\n order = order === void 0 ? negate2 !== (y3 === \"width\" || y3 === \"height\") ? descendingGroup : ascendingGroup : maybeOrder(order);\n if (reduce == null || reduce === false) continue;\n const X3 = x3 === \"fx\" || x3 === \"fy\" ? reindexFacetChannel(facets, facetChannels[x3]) : findScaleChannel(channels, x3);\n if (!X3) throw new Error(`missing channel for scale: ${x3}`);\n const XV = X3.value;\n const [lo = 0, hi = Infinity] = isIterable(limit) ? limit : limit < 0 ? [limit] : [0, limit];\n if (y3 == null) {\n X3.domain = () => {\n let domain = Array.from(new InternSet(XV));\n if (reverse3) domain = domain.reverse();\n if (lo !== 0 || hi !== Infinity) domain = domain.slice(lo, hi);\n return domain;\n };\n } else {\n const YV = y3 === \"data\" ? data : y3 === \"height\" ? difference(channels, \"y1\", \"y2\") : y3 === \"width\" ? difference(channels, \"x1\", \"x2\") : values(channels, y3, y3 === \"y\" ? \"y2\" : y3 === \"x\" ? \"x2\" : void 0);\n const reducer2 = maybeReduce(reduce === true ? \"max\" : reduce, YV);\n X3.domain = () => {\n let domain = rollups(\n range2(XV),\n (I) => reducer2.reduceIndex(I, YV),\n (i) => XV[i]\n );\n if (order) domain.sort(order);\n if (reverse3) domain.reverse();\n if (lo !== 0 || hi !== Infinity) domain = domain.slice(lo, hi);\n return domain.map(first2);\n };\n }\n }\n}\nfunction findScaleChannel(channels, scale3) {\n for (const name2 in channels) {\n const channel = channels[name2];\n if (channel.scale === scale3) return channel;\n }\n}\nfunction reindexFacetChannel(facets, channel) {\n const originalFacets = facets.original;\n if (originalFacets === facets) return channel;\n const V1 = channel.value;\n const V2 = channel.value = [];\n for (let i = 0; i < originalFacets.length; ++i) {\n const vi = V1[originalFacets[i][0]];\n for (const j of facets[i]) V2[j] = vi;\n }\n return channel;\n}\nfunction difference(channels, k1, k2) {\n const X13 = values(channels, k1);\n const X23 = values(channels, k2);\n return map3(X23, (x22, i) => Math.abs(x22 - X13[i]), Float64Array);\n}\nfunction values(channels, name2, alias) {\n let channel = channels[name2];\n if (!channel && alias !== void 0) channel = channels[alias];\n if (channel) return channel.value;\n throw new Error(`missing channel: ${name2}`);\n}\nfunction maybeOrder(order) {\n if (order == null || typeof order === \"function\") return order;\n switch (`${order}`.toLowerCase()) {\n case \"ascending\":\n return ascendingGroup;\n case \"descending\":\n return descendingGroup;\n }\n throw new Error(`invalid order: ${order}`);\n}\nfunction ascendingGroup([ak, av], [bk, bv]) {\n return ascendingDefined2(av, bv) || ascendingDefined2(ak, bk);\n}\nfunction descendingGroup([ak, av], [bk, bv]) {\n return descendingDefined(av, bv) || ascendingDefined2(ak, bk);\n}\nfunction getSource(channels, key) {\n let channel = channels[key];\n if (!channel) return;\n while (channel.source) channel = channel.source;\n return channel.source === null ? null : channel;\n}\n\n// ../../node_modules/@observablehq/plot/src/scales/schemes.js\nvar categoricalSchemes = /* @__PURE__ */ new Map([\n [\"accent\", Accent_default],\n [\"category10\", category10_default],\n [\"dark2\", Dark2_default],\n [\"observable10\", observable10_default],\n [\"paired\", Paired_default],\n [\"pastel1\", Pastel1_default],\n [\"pastel2\", Pastel2_default],\n [\"set1\", Set1_default],\n [\"set2\", Set2_default],\n [\"set3\", Set3_default],\n [\"tableau10\", Tableau10_default]\n]);\nfunction isCategoricalScheme(scheme28) {\n return scheme28 != null && categoricalSchemes.has(`${scheme28}`.toLowerCase());\n}\nvar ordinalSchemes = new Map([\n ...categoricalSchemes,\n // diverging\n [\"brbg\", scheme112(scheme, BrBG_default)],\n [\"prgn\", scheme112(scheme2, PRGn_default)],\n [\"piyg\", scheme112(scheme3, PiYG_default)],\n [\"puor\", scheme112(scheme4, PuOr_default)],\n [\"rdbu\", scheme112(scheme5, RdBu_default)],\n [\"rdgy\", scheme112(scheme6, RdGy_default)],\n [\"rdylbu\", scheme112(scheme7, RdYlBu_default)],\n [\"rdylgn\", scheme112(scheme8, RdYlGn_default)],\n [\"spectral\", scheme112(scheme9, Spectral_default)],\n // reversed diverging (for temperature data)\n [\"burd\", scheme11r(scheme5, RdBu_default)],\n [\"buylrd\", scheme11r(scheme7, RdYlBu_default)],\n // sequential (single-hue)\n [\"blues\", scheme92(scheme22, Blues_default)],\n [\"greens\", scheme92(scheme23, Greens_default)],\n [\"greys\", scheme92(scheme24, Greys_default)],\n [\"oranges\", scheme92(scheme27, Oranges_default)],\n [\"purples\", scheme92(scheme25, Purples_default)],\n [\"reds\", scheme92(scheme26, Reds_default)],\n // sequential (multi-hue)\n [\"turbo\", schemei(turbo_default)],\n [\"viridis\", schemei(viridis_default)],\n [\"magma\", schemei(magma)],\n [\"inferno\", schemei(inferno)],\n [\"plasma\", schemei(plasma)],\n [\"cividis\", schemei(cividis_default)],\n [\"cubehelix\", schemei(cubehelix_default2)],\n [\"warm\", schemei(warm)],\n [\"cool\", schemei(cool)],\n [\"bugn\", scheme92(scheme10, BuGn_default)],\n [\"bupu\", scheme92(scheme11, BuPu_default)],\n [\"gnbu\", scheme92(scheme12, GnBu_default)],\n [\"orrd\", scheme92(scheme13, OrRd_default)],\n [\"pubu\", scheme92(scheme15, PuBu_default)],\n [\"pubugn\", scheme92(scheme14, PuBuGn_default)],\n [\"purd\", scheme92(scheme16, PuRd_default)],\n [\"rdpu\", scheme92(scheme17, RdPu_default)],\n [\"ylgn\", scheme92(scheme19, YlGn_default)],\n [\"ylgnbu\", scheme92(scheme18, YlGnBu_default)],\n [\"ylorbr\", scheme92(scheme20, YlOrBr_default)],\n [\"ylorrd\", scheme92(scheme21, YlOrRd_default)],\n // cyclical\n [\"rainbow\", schemeicyclical(rainbow_default)],\n [\"sinebow\", schemeicyclical(sinebow_default)]\n]);\nfunction scheme92(scheme28, interpolate) {\n return ({ length: n }) => {\n if (n === 1) return [scheme28[3][1]];\n if (n === 2) return [scheme28[3][1], scheme28[3][2]];\n n = Math.max(3, Math.floor(n));\n return n > 9 ? quantize_default(interpolate, n) : scheme28[n];\n };\n}\nfunction scheme112(scheme28, interpolate) {\n return ({ length: n }) => {\n if (n === 2) return [scheme28[3][0], scheme28[3][2]];\n n = Math.max(3, Math.floor(n));\n return n > 11 ? quantize_default(interpolate, n) : scheme28[n];\n };\n}\nfunction scheme11r(scheme28, interpolate) {\n return ({ length: n }) => {\n if (n === 2) return [scheme28[3][2], scheme28[3][0]];\n n = Math.max(3, Math.floor(n));\n return n > 11 ? quantize_default((t) => interpolate(1 - t), n) : scheme28[n].slice().reverse();\n };\n}\nfunction schemei(interpolate) {\n return ({ length: n }) => quantize_default(interpolate, Math.max(2, Math.floor(n)));\n}\nfunction schemeicyclical(interpolate) {\n return ({ length: n }) => quantize_default(interpolate, Math.floor(n) + 1).slice(0, -1);\n}\nfunction ordinalScheme(scheme28) {\n const s2 = `${scheme28}`.toLowerCase();\n if (!ordinalSchemes.has(s2)) throw new Error(`unknown ordinal scheme: ${s2}`);\n return ordinalSchemes.get(s2);\n}\nfunction ordinalRange(scheme28, length4) {\n const s2 = ordinalScheme(scheme28);\n const r = typeof s2 === \"function\" ? s2({ length: length4 }) : s2;\n return r.length !== length4 ? r.slice(0, length4) : r;\n}\nfunction maybeBooleanRange(domain, scheme28 = \"greys\") {\n const range3 = /* @__PURE__ */ new Set();\n const [f, t] = ordinalRange(scheme28, 2);\n for (const value of domain) {\n if (value == null) continue;\n if (value === true) range3.add(t);\n else if (value === false) range3.add(f);\n else return;\n }\n return [...range3];\n}\nvar quantitativeSchemes = /* @__PURE__ */ new Map([\n // diverging\n [\"brbg\", BrBG_default],\n [\"prgn\", PRGn_default],\n [\"piyg\", PiYG_default],\n [\"puor\", PuOr_default],\n [\"rdbu\", RdBu_default],\n [\"rdgy\", RdGy_default],\n [\"rdylbu\", RdYlBu_default],\n [\"rdylgn\", RdYlGn_default],\n [\"spectral\", Spectral_default],\n // reversed diverging (for temperature data)\n [\"burd\", (t) => RdBu_default(1 - t)],\n [\"buylrd\", (t) => RdYlBu_default(1 - t)],\n // sequential (single-hue)\n [\"blues\", Blues_default],\n [\"greens\", Greens_default],\n [\"greys\", Greys_default],\n [\"purples\", Purples_default],\n [\"reds\", Reds_default],\n [\"oranges\", Oranges_default],\n // sequential (multi-hue)\n [\"turbo\", turbo_default],\n [\"viridis\", viridis_default],\n [\"magma\", magma],\n [\"inferno\", inferno],\n [\"plasma\", plasma],\n [\"cividis\", cividis_default],\n [\"cubehelix\", cubehelix_default2],\n [\"warm\", warm],\n [\"cool\", cool],\n [\"bugn\", BuGn_default],\n [\"bupu\", BuPu_default],\n [\"gnbu\", GnBu_default],\n [\"orrd\", OrRd_default],\n [\"pubugn\", PuBuGn_default],\n [\"pubu\", PuBu_default],\n [\"purd\", PuRd_default],\n [\"rdpu\", RdPu_default],\n [\"ylgnbu\", YlGnBu_default],\n [\"ylgn\", YlGn_default],\n [\"ylorbr\", YlOrBr_default],\n [\"ylorrd\", YlOrRd_default],\n // cyclical\n [\"rainbow\", rainbow_default],\n [\"sinebow\", sinebow_default]\n]);\nfunction quantitativeScheme(scheme28) {\n const s2 = `${scheme28}`.toLowerCase();\n if (!quantitativeSchemes.has(s2)) throw new Error(`unknown quantitative scheme: ${s2}`);\n return quantitativeSchemes.get(s2);\n}\nvar divergingSchemes = /* @__PURE__ */ new Set([\n \"brbg\",\n \"prgn\",\n \"piyg\",\n \"puor\",\n \"rdbu\",\n \"rdgy\",\n \"rdylbu\",\n \"rdylgn\",\n \"spectral\",\n \"burd\",\n \"buylrd\"\n]);\nfunction isDivergingScheme(scheme28) {\n return scheme28 != null && divergingSchemes.has(`${scheme28}`.toLowerCase());\n}\n\n// ../../node_modules/@observablehq/plot/src/scales/quantitative.js\nvar flip = (i) => (t) => i(1 - t);\nvar unit2 = [0, 1];\nvar interpolators = /* @__PURE__ */ new Map([\n // numbers\n [\"number\", number_default],\n // color spaces\n [\"rgb\", rgb_default],\n [\"hsl\", hsl_default],\n [\"hcl\", hcl_default],\n [\"lab\", lab2]\n]);\nfunction maybeInterpolator(interpolate) {\n const i = `${interpolate}`.toLowerCase();\n if (!interpolators.has(i)) throw new Error(`unknown interpolator: ${i}`);\n return interpolators.get(i);\n}\nfunction createScaleQ(key, scale3, channels, {\n type: type2,\n nice: nice3,\n clamp,\n zero: zero3,\n domain = inferAutoDomain(key, channels),\n unknown,\n round: round2,\n scheme: scheme28,\n interval: interval3,\n range: range3 = registry.get(key) === radius ? inferRadialRange(channels, domain) : registry.get(key) === length3 ? inferLengthRange(channels, domain) : registry.get(key) === opacity ? unit2 : void 0,\n interpolate = registry.get(key) === color2 ? scheme28 == null && range3 !== void 0 ? rgb_default : quantitativeScheme(scheme28 !== void 0 ? scheme28 : type2 === \"cyclical\" ? \"rainbow\" : \"turbo\") : round2 ? round_default : number_default,\n reverse: reverse3\n}) {\n interval3 = maybeRangeInterval(interval3, type2);\n if (type2 === \"cyclical\" || type2 === \"sequential\") type2 = \"linear\";\n if (typeof interpolate !== \"function\") interpolate = maybeInterpolator(interpolate);\n reverse3 = !!reverse3;\n if (range3 !== void 0) {\n const n = (domain = arrayify2(domain)).length;\n const m = (range3 = arrayify2(range3)).length;\n if (n !== m) {\n if (interpolate.length === 1) throw new Error(\"invalid piecewise interpolator\");\n interpolate = piecewise(interpolate, range3);\n range3 = void 0;\n }\n }\n if (interpolate.length === 1) {\n if (reverse3) {\n interpolate = flip(interpolate);\n reverse3 = false;\n }\n if (range3 === void 0) {\n range3 = Float64Array.from(domain, (_, i) => i / (domain.length - 1));\n if (range3.length === 2) range3 = unit2;\n }\n scale3.interpolate((range3 === unit2 ? constant : interpolatePiecewise)(interpolate));\n } else {\n scale3.interpolate(interpolate);\n }\n if (zero3) {\n const [min5, max4] = extent(domain);\n if (min5 > 0 || max4 < 0) {\n domain = slice3(domain);\n const o = orderof(domain) || 1;\n if (o === Math.sign(min5)) domain[0] = 0;\n else domain[domain.length - 1] = 0;\n }\n }\n if (reverse3) domain = reverse(domain);\n scale3.domain(domain).unknown(unknown);\n if (nice3) scale3.nice(maybeNice(nice3, type2)), domain = scale3.domain();\n if (range3 !== void 0) scale3.range(range3);\n if (clamp) scale3.clamp(clamp);\n return { type: type2, domain, range: range3, scale: scale3, interpolate, interval: interval3 };\n}\nfunction maybeNice(nice3, type2) {\n return nice3 === true ? void 0 : typeof nice3 === \"number\" ? nice3 : maybeNiceInterval(nice3, type2);\n}\nfunction createScaleLinear(key, channels, options) {\n return createScaleQ(key, linear2(), channels, options);\n}\nfunction createScaleSqrt(key, channels, options) {\n return createScalePow(key, channels, { ...options, exponent: 0.5 });\n}\nfunction createScalePow(key, channels, { exponent = 1, ...options }) {\n return createScaleQ(key, pow3().exponent(exponent), channels, { ...options, type: \"pow\" });\n}\nfunction createScaleLog(key, channels, { base = 10, domain = inferLogDomain(channels), ...options }) {\n return createScaleQ(key, log2().base(base), channels, { ...options, domain });\n}\nfunction createScaleSymlog(key, channels, { constant: constant2 = 1, ...options }) {\n return createScaleQ(key, symlog().constant(constant2), channels, options);\n}\nfunction createScaleQuantile(key, channels, {\n range: range3,\n quantiles = range3 === void 0 ? 5 : (range3 = [...range3]).length,\n // deprecated; use n instead\n n = quantiles,\n scheme: scheme28 = \"rdylbu\",\n domain = inferQuantileDomain(channels),\n unknown,\n interpolate,\n reverse: reverse3\n}) {\n if (range3 === void 0) {\n range3 = interpolate !== void 0 ? quantize_default(interpolate, n) : registry.get(key) === color2 ? ordinalRange(scheme28, n) : void 0;\n }\n if (domain.length > 0) {\n domain = quantile3(domain, range3 === void 0 ? { length: n } : range3).quantiles();\n }\n return createScaleThreshold(key, channels, { domain, range: range3, reverse: reverse3, unknown });\n}\nfunction createScaleQuantize(key, channels, {\n range: range3,\n n = range3 === void 0 ? 5 : (range3 = [...range3]).length,\n scheme: scheme28 = \"rdylbu\",\n domain = inferAutoDomain(key, channels),\n unknown,\n interpolate,\n reverse: reverse3\n}) {\n const [min5, max4] = extent(domain);\n let thresholds;\n if (range3 === void 0) {\n thresholds = ticks(min5, max4, n);\n if (thresholds[0] <= min5) thresholds.splice(0, 1);\n if (thresholds[thresholds.length - 1] >= max4) thresholds.pop();\n n = thresholds.length + 1;\n range3 = interpolate !== void 0 ? quantize_default(interpolate, n) : registry.get(key) === color2 ? ordinalRange(scheme28, n) : void 0;\n } else {\n thresholds = quantize_default(number_default(min5, max4), n + 1).slice(1, -1);\n if (min5 instanceof Date) thresholds = thresholds.map((x3) => new Date(x3));\n }\n if (orderof(arrayify2(domain)) < 0) thresholds.reverse();\n return createScaleThreshold(key, channels, { domain: thresholds, range: range3, reverse: reverse3, unknown });\n}\nfunction createScaleThreshold(key, channels, {\n domain = [0],\n // explicit thresholds in ascending order\n unknown,\n scheme: scheme28 = \"rdylbu\",\n interpolate,\n range: range3 = interpolate !== void 0 ? quantize_default(interpolate, domain.length + 1) : registry.get(key) === color2 ? ordinalRange(scheme28, domain.length + 1) : void 0,\n reverse: reverse3\n}) {\n domain = arrayify2(domain);\n const sign3 = orderof(domain);\n if (!isNaN(sign3) && !isOrdered(domain, sign3)) throw new Error(`the ${key} scale has a non-monotonic domain`);\n if (reverse3) range3 = reverse(range3);\n return {\n type: \"threshold\",\n scale: threshold(sign3 < 0 ? reverse(domain) : domain, range3 === void 0 ? [] : range3).unknown(unknown),\n domain,\n range: range3\n };\n}\nfunction isOrdered(domain, sign3) {\n for (let i = 1, n = domain.length, d = domain[0]; i < n; ++i) {\n const s2 = descending(d, d = domain[i]);\n if (s2 !== 0 && s2 !== sign3) return false;\n }\n return true;\n}\nfunction createScaleIdentity(key) {\n return { type: \"identity\", scale: hasNumericRange(registry.get(key)) ? identity5() : (d) => d };\n}\nfunction inferDomain(channels, f = finite2) {\n return channels.length ? [\n min2(channels, ({ value }) => value === void 0 ? value : min2(value, f)),\n max2(channels, ({ value }) => value === void 0 ? value : max2(value, f))\n ] : [0, 1];\n}\nfunction inferAutoDomain(key, channels) {\n const type2 = registry.get(key);\n return (type2 === radius || type2 === opacity || type2 === length3 ? inferZeroDomain : inferDomain)(channels);\n}\nfunction inferZeroDomain(channels) {\n return [0, channels.length ? max2(channels, ({ value }) => value === void 0 ? value : max2(value, finite2)) : 1];\n}\nfunction inferRadialRange(channels, domain) {\n const hint = channels.find(({ radius: radius2 }) => radius2 !== void 0);\n if (hint !== void 0) return [0, hint.radius];\n const h25 = quantile2(channels, 0.5, ({ value }) => value === void 0 ? NaN : quantile2(value, 0.25, positive));\n const range3 = domain.map((d) => 3 * Math.sqrt(d / h25));\n const k2 = 30 / max2(range3);\n return k2 < 1 ? range3.map((r) => r * k2) : range3;\n}\nfunction inferLengthRange(channels, domain) {\n const h50 = median2(channels, ({ value }) => value === void 0 ? NaN : median2(value, Math.abs));\n const range3 = domain.map((d) => 12 * d / h50);\n const k2 = 60 / max2(range3);\n return k2 < 1 ? range3.map((r) => r * k2) : range3;\n}\nfunction inferLogDomain(channels) {\n for (const { value } of channels) {\n if (value !== void 0) {\n for (let v2 of value) {\n if (v2 > 0) return inferDomain(channels, positive);\n if (v2 < 0) return inferDomain(channels, negative);\n }\n }\n }\n return [1, 10];\n}\nfunction inferQuantileDomain(channels) {\n const domain = [];\n for (const { value } of channels) {\n if (value === void 0) continue;\n for (const v2 of value) domain.push(v2);\n }\n return domain;\n}\nfunction interpolatePiecewise(interpolate) {\n return (i, j) => (t) => interpolate(i + t * (j - i));\n}\n\n// ../../node_modules/@observablehq/plot/src/warnings.js\nvar warnings = 0;\nvar lastMessage;\nfunction consumeWarnings() {\n const w = warnings;\n warnings = 0;\n lastMessage = void 0;\n return w;\n}\nfunction warn(message) {\n if (message === lastMessage) return;\n lastMessage = message;\n console.warn(message);\n ++warnings;\n}\n\n// ../../node_modules/@observablehq/plot/src/scales/diverging.js\nfunction createScaleD(key, scale3, transform3, channels, {\n type: type2,\n nice: nice3,\n clamp,\n domain = inferDomain(channels),\n unknown,\n pivot = 0,\n scheme: scheme28,\n range: range3,\n symmetric = true,\n interpolate = registry.get(key) === color2 ? scheme28 == null && range3 !== void 0 ? rgb_default : quantitativeScheme(scheme28 !== void 0 ? scheme28 : \"rdbu\") : number_default,\n reverse: reverse3\n}) {\n pivot = +pivot;\n domain = arrayify2(domain);\n let [min5, max4] = domain;\n if (domain.length > 2) warn(`Warning: the diverging ${key} scale domain contains extra elements.`);\n if (descending(min5, max4) < 0) [min5, max4] = [max4, min5], reverse3 = !reverse3;\n min5 = Math.min(min5, pivot);\n max4 = Math.max(max4, pivot);\n if (typeof interpolate !== \"function\") {\n interpolate = maybeInterpolator(interpolate);\n }\n if (range3 !== void 0) {\n interpolate = interpolate.length === 1 ? interpolatePiecewise(interpolate)(...range3) : piecewise(interpolate, range3);\n }\n if (reverse3) interpolate = flip(interpolate);\n if (symmetric) {\n const mid2 = transform3.apply(pivot);\n const mindelta = mid2 - transform3.apply(min5);\n const maxdelta = transform3.apply(max4) - mid2;\n if (mindelta < maxdelta) min5 = transform3.invert(mid2 - maxdelta);\n else if (mindelta > maxdelta) max4 = transform3.invert(mid2 + mindelta);\n }\n scale3.domain([min5, pivot, max4]).unknown(unknown).interpolator(interpolate);\n if (clamp) scale3.clamp(clamp);\n if (nice3) scale3.nice(nice3);\n return { type: type2, domain: [min5, max4], pivot, interpolate, scale: scale3 };\n}\nfunction createScaleDiverging(key, channels, options) {\n return createScaleD(key, diverging(), transformIdentity, channels, options);\n}\nfunction createScaleDivergingSqrt(key, channels, options) {\n return createScaleDivergingPow(key, channels, { ...options, exponent: 0.5 });\n}\nfunction createScaleDivergingPow(key, channels, { exponent = 1, ...options }) {\n return createScaleD(key, divergingPow().exponent(exponent = +exponent), transformPow2(exponent), channels, {\n ...options,\n type: \"diverging-pow\"\n });\n}\nfunction createScaleDivergingLog(key, channels, { base = 10, pivot = 1, domain = inferDomain(channels, pivot < 0 ? negative : positive), ...options }) {\n return createScaleD(key, divergingLog().base(base = +base), transformLog2, channels, {\n domain,\n pivot,\n ...options\n });\n}\nfunction createScaleDivergingSymlog(key, channels, { constant: constant2 = 1, ...options }) {\n return createScaleD(\n key,\n divergingSymlog().constant(constant2 = +constant2),\n transformSymlog2(constant2),\n channels,\n options\n );\n}\nvar transformIdentity = {\n apply(x3) {\n return x3;\n },\n invert(x3) {\n return x3;\n }\n};\nvar transformLog2 = {\n apply: Math.log,\n invert: Math.exp\n};\nvar transformSqrt2 = {\n apply(x3) {\n return Math.sign(x3) * Math.sqrt(Math.abs(x3));\n },\n invert(x3) {\n return Math.sign(x3) * (x3 * x3);\n }\n};\nfunction transformPow2(exponent) {\n return exponent === 0.5 ? transformSqrt2 : {\n apply(x3) {\n return Math.sign(x3) * Math.pow(Math.abs(x3), exponent);\n },\n invert(x3) {\n return Math.sign(x3) * Math.pow(Math.abs(x3), 1 / exponent);\n }\n };\n}\nfunction transformSymlog2(constant2) {\n return {\n apply(x3) {\n return Math.sign(x3) * Math.log1p(Math.abs(x3 / constant2));\n },\n invert(x3) {\n return Math.sign(x3) * Math.expm1(Math.abs(x3)) * constant2;\n }\n };\n}\n\n// ../../node_modules/@observablehq/plot/src/scales/temporal.js\nfunction createScaleT(key, scale3, channels, options) {\n return createScaleQ(key, scale3, channels, options);\n}\nfunction createScaleTime(key, channels, options) {\n return createScaleT(key, time2(), channels, options);\n}\nfunction createScaleUtc(key, channels, options) {\n return createScaleT(key, utcTime(), channels, options);\n}\n\n// ../../node_modules/@observablehq/plot/src/scales/ordinal.js\nvar ordinalImplicit = Symbol(\"ordinal\");\nfunction createScaleO(key, scale3, channels, { type: type2, interval: interval3, domain, range: range3, reverse: reverse3, hint }) {\n interval3 = maybeRangeInterval(interval3, type2);\n if (domain === void 0) domain = inferDomain2(channels, interval3, key);\n if (type2 === \"categorical\" || type2 === ordinalImplicit) type2 = \"ordinal\";\n if (reverse3) domain = reverse(domain);\n domain = scale3.domain(domain).domain();\n if (range3 !== void 0) {\n if (typeof range3 === \"function\") range3 = range3(domain);\n scale3.range(range3);\n }\n return { type: type2, domain, range: range3, scale: scale3, hint, interval: interval3 };\n}\nfunction createScaleOrdinal(key, channels, { type: type2, interval: interval3, domain, range: range3, scheme: scheme28, unknown, ...options }) {\n interval3 = maybeRangeInterval(interval3, type2);\n if (domain === void 0) domain = inferDomain2(channels, interval3, key);\n let hint;\n if (registry.get(key) === symbol) {\n hint = inferSymbolHint(channels);\n range3 = range3 === void 0 ? inferSymbolRange(hint) : map3(range3, maybeSymbol);\n } else if (registry.get(key) === color2) {\n if (range3 === void 0 && (type2 === \"ordinal\" || type2 === ordinalImplicit)) {\n range3 = maybeBooleanRange(domain, scheme28);\n if (range3 !== void 0) scheme28 = void 0;\n }\n if (scheme28 === void 0 && range3 === void 0) {\n scheme28 = type2 === \"ordinal\" ? \"turbo\" : \"observable10\";\n }\n if (scheme28 !== void 0) {\n if (range3 !== void 0) {\n const interpolate = quantitativeScheme(scheme28);\n const t03 = range3[0], d = range3[1] - range3[0];\n range3 = ({ length: n }) => quantize_default((t) => interpolate(t03 + d * t), n);\n } else {\n range3 = ordinalScheme(scheme28);\n }\n }\n }\n if (unknown === implicit) {\n throw new Error(`implicit unknown on ${key} scale is not supported`);\n }\n return createScaleO(key, ordinal().unknown(unknown), channels, { ...options, type: type2, domain, range: range3, hint });\n}\nfunction createScalePoint(key, channels, { align: align3 = 0.5, padding: padding2 = 0.5, ...options }) {\n return maybeRound(point().align(align3).padding(padding2), channels, options, key);\n}\nfunction createScaleBand(key, channels, {\n align: align3 = 0.5,\n padding: padding2 = 0.1,\n paddingInner = padding2,\n paddingOuter = key === \"fx\" || key === \"fy\" ? 0 : padding2,\n ...options\n}) {\n return maybeRound(\n band().align(align3).paddingInner(paddingInner).paddingOuter(paddingOuter),\n channels,\n options,\n key\n );\n}\nfunction maybeRound(scale3, channels, options, key) {\n let { round: round2 } = options;\n if (round2 !== void 0) scale3.round(round2 = !!round2);\n scale3 = createScaleO(key, scale3, channels, options);\n scale3.round = round2;\n return scale3;\n}\nfunction inferDomain2(channels, interval3, key) {\n const values2 = new InternSet();\n for (const { value, domain } of channels) {\n if (domain !== void 0) return domain();\n if (value === void 0) continue;\n for (const v2 of value) values2.add(v2);\n }\n if (interval3 !== void 0) {\n const [min5, max4] = extent(values2).map(interval3.floor, interval3);\n return interval3.range(min5, interval3.offset(max4));\n }\n if (values2.size > 1e4 && registry.get(key) === position) {\n throw new Error(`implicit ordinal domain of ${key} scale has more than 10,000 values`);\n }\n return sort(values2, ascendingDefined2);\n}\nfunction inferHint(channels, key) {\n let value;\n for (const { hint } of channels) {\n const candidate = hint?.[key];\n if (candidate === void 0) continue;\n if (value === void 0) value = candidate;\n else if (value !== candidate) return;\n }\n return value;\n}\nfunction inferSymbolHint(channels) {\n return {\n fill: inferHint(channels, \"fill\"),\n stroke: inferHint(channels, \"stroke\")\n };\n}\nfunction inferSymbolRange(hint) {\n return isNoneish(hint.fill) ? symbolsStroke : symbolsFill;\n}\n\n// ../../node_modules/@observablehq/plot/src/scales.js\nfunction createScales(channelsByScale, {\n label: globalLabel,\n inset: globalInset = 0,\n insetTop: globalInsetTop = globalInset,\n insetRight: globalInsetRight = globalInset,\n insetBottom: globalInsetBottom = globalInset,\n insetLeft: globalInsetLeft = globalInset,\n round: round2,\n nice: nice3,\n clamp,\n zero: zero3,\n align: align3,\n padding: padding2,\n projection: projection3,\n facet: { label: facetLabel2 = globalLabel } = {},\n ...options\n} = {}) {\n const scales2 = {};\n for (const [key, channels] of channelsByScale) {\n const scaleOptions = options[key];\n const scale3 = createScale(key, channels, {\n round: registry.get(key) === position ? round2 : void 0,\n // only for position\n nice: nice3,\n clamp,\n zero: zero3,\n align: align3,\n padding: padding2,\n projection: projection3,\n ...scaleOptions\n });\n if (scale3) {\n let {\n label: label2 = key === \"fx\" || key === \"fy\" ? facetLabel2 : globalLabel,\n percent,\n transform: transform3,\n inset: inset2,\n insetTop = inset2 !== void 0 ? inset2 : key === \"y\" ? globalInsetTop : 0,\n // not fy\n insetRight = inset2 !== void 0 ? inset2 : key === \"x\" ? globalInsetRight : 0,\n // not fx\n insetBottom = inset2 !== void 0 ? inset2 : key === \"y\" ? globalInsetBottom : 0,\n // not fy\n insetLeft = inset2 !== void 0 ? inset2 : key === \"x\" ? globalInsetLeft : 0\n // not fx\n } = scaleOptions || {};\n if (transform3 == null) transform3 = void 0;\n else if (typeof transform3 !== \"function\") throw new Error(\"invalid scale transform; not a function\");\n scale3.percent = !!percent;\n scale3.label = label2 === void 0 ? inferScaleLabel(channels, scale3) : label2;\n scale3.transform = transform3;\n if (key === \"x\" || key === \"fx\") {\n scale3.insetLeft = +insetLeft;\n scale3.insetRight = +insetRight;\n } else if (key === \"y\" || key === \"fy\") {\n scale3.insetTop = +insetTop;\n scale3.insetBottom = +insetBottom;\n }\n scales2[key] = scale3;\n }\n }\n return scales2;\n}\nfunction createScaleFunctions(descriptors) {\n const scales2 = {};\n const scaleFunctions = { scales: scales2 };\n for (const [key, descriptor] of Object.entries(descriptors)) {\n const { scale: scale3, type: type2, interval: interval3, label: label2 } = descriptor;\n scales2[key] = exposeScale(descriptor);\n scaleFunctions[key] = scale3;\n scale3.type = type2;\n if (interval3 != null) scale3.interval = interval3;\n if (label2 != null) scale3.label = label2;\n }\n return scaleFunctions;\n}\nfunction autoScaleRange(scales2, dimensions) {\n const { x: x3, y: y3, fx, fy } = scales2;\n const superdimensions = fx || fy ? outerDimensions(dimensions) : dimensions;\n if (fx) autoScaleRangeX(fx, superdimensions);\n if (fy) autoScaleRangeY(fy, superdimensions);\n const subdimensions = fx || fy ? innerDimensions(scales2, dimensions) : dimensions;\n if (x3) autoScaleRangeX(x3, subdimensions);\n if (y3) autoScaleRangeY(y3, subdimensions);\n}\nfunction inferScaleLabel(channels = [], scale3) {\n let label2;\n for (const { label: l } of channels) {\n if (l === void 0) continue;\n if (label2 === void 0) label2 = l;\n else if (label2 !== l) return;\n }\n if (label2 === void 0) return;\n if (!isOrdinalScale(scale3) && scale3.percent) label2 = `${label2} (%)`;\n return { inferred: true, toString: () => label2 };\n}\nfunction inferScaleOrder(scale3) {\n return Math.sign(orderof(scale3.domain())) * Math.sign(orderof(scale3.range()));\n}\nfunction outerDimensions(dimensions) {\n const {\n marginTop: marginTop2,\n marginRight: marginRight2,\n marginBottom: marginBottom2,\n marginLeft: marginLeft2,\n width: width2,\n height: height2,\n facet: {\n marginTop: facetMarginTop2,\n marginRight: facetMarginRight2,\n marginBottom: facetMarginBottom2,\n marginLeft: facetMarginLeft2\n }\n } = dimensions;\n return {\n marginTop: Math.max(marginTop2, facetMarginTop2),\n marginRight: Math.max(marginRight2, facetMarginRight2),\n marginBottom: Math.max(marginBottom2, facetMarginBottom2),\n marginLeft: Math.max(marginLeft2, facetMarginLeft2),\n width: width2,\n height: height2\n };\n}\nfunction innerDimensions({ fx, fy }, dimensions) {\n const { marginTop: marginTop2, marginRight: marginRight2, marginBottom: marginBottom2, marginLeft: marginLeft2, width: width2, height: height2 } = outerDimensions(dimensions);\n return {\n marginTop: marginTop2,\n marginRight: marginRight2,\n marginBottom: marginBottom2,\n marginLeft: marginLeft2,\n width: fx ? fx.scale.bandwidth() + marginLeft2 + marginRight2 : width2,\n height: fy ? fy.scale.bandwidth() + marginTop2 + marginBottom2 : height2,\n facet: { width: width2, height: height2 }\n };\n}\nfunction autoScaleRangeX(scale3, dimensions) {\n if (scale3.range === void 0) {\n const { insetLeft, insetRight } = scale3;\n const { width: width2, marginLeft: marginLeft2 = 0, marginRight: marginRight2 = 0 } = dimensions;\n const left2 = marginLeft2 + insetLeft;\n const right2 = width2 - marginRight2 - insetRight;\n scale3.range = [left2, Math.max(left2, right2)];\n if (!isOrdinalScale(scale3)) scale3.range = piecewiseRange(scale3);\n scale3.scale.range(scale3.range);\n }\n autoScaleRound(scale3);\n}\nfunction autoScaleRangeY(scale3, dimensions) {\n if (scale3.range === void 0) {\n const { insetTop, insetBottom } = scale3;\n const { height: height2, marginTop: marginTop2 = 0, marginBottom: marginBottom2 = 0 } = dimensions;\n const top2 = marginTop2 + insetTop;\n const bottom2 = height2 - marginBottom2 - insetBottom;\n scale3.range = [Math.max(top2, bottom2), top2];\n if (!isOrdinalScale(scale3)) scale3.range = piecewiseRange(scale3);\n else scale3.range.reverse();\n scale3.scale.range(scale3.range);\n }\n autoScaleRound(scale3);\n}\nfunction autoScaleRound(scale3) {\n if (scale3.round === void 0 && isBandScale(scale3) && roundError(scale3) <= 30) {\n scale3.scale.round(true);\n }\n}\nfunction roundError({ scale: scale3 }) {\n const n = scale3.domain().length;\n const [start2, stop] = scale3.range();\n const paddingInner = scale3.paddingInner ? scale3.paddingInner() : 1;\n const paddingOuter = scale3.paddingOuter ? scale3.paddingOuter() : scale3.padding();\n const m = n - paddingInner;\n const step = Math.abs(stop - start2) / Math.max(1, m + paddingOuter * 2);\n return (step - Math.floor(step)) * m;\n}\nfunction piecewiseRange(scale3) {\n const length4 = scale3.scale.domain().length + isThresholdScale(scale3);\n if (!(length4 > 2)) return scale3.range;\n const [start2, end] = scale3.range;\n return Array.from({ length: length4 }, (_, i) => start2 + i / (length4 - 1) * (end - start2));\n}\nfunction normalizeScale(key, scale3, hint) {\n return createScale(key, hint === void 0 ? void 0 : [{ hint }], { ...scale3 });\n}\nfunction createScale(key, channels = [], options = {}) {\n const type2 = inferScaleType(key, channels, options);\n if (options.type === void 0 && options.domain === void 0 && options.range === void 0 && options.interval == null && key !== \"fx\" && key !== \"fy\" && isOrdinalScale({ type: type2 })) {\n const values2 = channels.map(({ value }) => value).filter((value) => value !== void 0);\n if (values2.some(isTemporal))\n warn(\n `Warning: some data associated with the ${key} scale are dates. Dates are typically associated with a \"utc\" or \"time\" scale rather than a \"${formatScaleType(\n type2\n )}\" scale. If you are using a bar mark, you probably want a rect mark with the interval option instead; if you are using a group transform, you probably want a bin transform instead. If you want to treat this data as ordinal, you can specify the interval of the ${key} scale (e.g., d3.utcDay), or you can suppress this warning by setting the type of the ${key} scale to \"${formatScaleType(\n type2\n )}\".`\n );\n else if (values2.some(isTemporalString))\n warn(\n `Warning: some data associated with the ${key} scale are strings that appear to be dates (e.g., YYYY-MM-DD). If these strings represent dates, you should parse them to Date objects. Dates are typically associated with a \"utc\" or \"time\" scale rather than a \"${formatScaleType(\n type2\n )}\" scale. If you are using a bar mark, you probably want a rect mark with the interval option instead; if you are using a group transform, you probably want a bin transform instead. If you want to treat this data as ordinal, you can suppress this warning by setting the type of the ${key} scale to \"${formatScaleType(\n type2\n )}\".`\n );\n else if (values2.some(isNumericString))\n warn(\n `Warning: some data associated with the ${key} scale are strings that appear to be numbers. If these strings represent numbers, you should parse or coerce them to numbers. Numbers are typically associated with a \"linear\" scale rather than a \"${formatScaleType(\n type2\n )}\" scale. If you want to treat this data as ordinal, you can specify the interval of the ${key} scale (e.g., 1 for integers), or you can suppress this warning by setting the type of the ${key} scale to \"${formatScaleType(\n type2\n )}\".`\n );\n }\n options.type = type2;\n switch (type2) {\n case \"diverging\":\n case \"diverging-sqrt\":\n case \"diverging-pow\":\n case \"diverging-log\":\n case \"diverging-symlog\":\n case \"cyclical\":\n case \"sequential\":\n case \"linear\":\n case \"sqrt\":\n case \"threshold\":\n case \"quantile\":\n case \"pow\":\n case \"log\":\n case \"symlog\":\n options = coerceType(channels, options, coerceNumbers);\n break;\n case \"identity\":\n switch (registry.get(key)) {\n case position:\n options = coerceType(channels, options, coerceNumbers);\n break;\n case symbol:\n options = coerceType(channels, options, coerceSymbols);\n break;\n }\n break;\n case \"utc\":\n case \"time\":\n options = coerceType(channels, options, coerceDates);\n break;\n }\n switch (type2) {\n case \"diverging\":\n return createScaleDiverging(key, channels, options);\n case \"diverging-sqrt\":\n return createScaleDivergingSqrt(key, channels, options);\n case \"diverging-pow\":\n return createScaleDivergingPow(key, channels, options);\n case \"diverging-log\":\n return createScaleDivergingLog(key, channels, options);\n case \"diverging-symlog\":\n return createScaleDivergingSymlog(key, channels, options);\n case \"categorical\":\n case \"ordinal\":\n case ordinalImplicit:\n return createScaleOrdinal(key, channels, options);\n case \"cyclical\":\n case \"sequential\":\n case \"linear\":\n return createScaleLinear(key, channels, options);\n case \"sqrt\":\n return createScaleSqrt(key, channels, options);\n case \"threshold\":\n return createScaleThreshold(key, channels, options);\n case \"quantile\":\n return createScaleQuantile(key, channels, options);\n case \"quantize\":\n return createScaleQuantize(key, channels, options);\n case \"pow\":\n return createScalePow(key, channels, options);\n case \"log\":\n return createScaleLog(key, channels, options);\n case \"symlog\":\n return createScaleSymlog(key, channels, options);\n case \"utc\":\n return createScaleUtc(key, channels, options);\n case \"time\":\n return createScaleTime(key, channels, options);\n case \"point\":\n return createScalePoint(key, channels, options);\n case \"band\":\n return createScaleBand(key, channels, options);\n case \"identity\":\n return createScaleIdentity(key);\n case void 0:\n return;\n default:\n throw new Error(`unknown scale type: ${type2}`);\n }\n}\nfunction formatScaleType(type2) {\n return typeof type2 === \"symbol\" ? type2.description : type2;\n}\nfunction maybeScaleType(type2) {\n return typeof type2 === \"string\" ? `${type2}`.toLowerCase() : type2;\n}\nvar typeProjection = { toString: () => \"projection\" };\nfunction inferScaleType(key, channels, { type: type2, domain, range: range3, scheme: scheme28, pivot, projection: projection3 }) {\n type2 = maybeScaleType(type2);\n if (key === \"fx\" || key === \"fy\") return \"band\";\n if ((key === \"x\" || key === \"y\") && projection3 != null) type2 = typeProjection;\n for (const channel of channels) {\n const t = maybeScaleType(channel.type);\n if (t === void 0) continue;\n else if (type2 === void 0) type2 = t;\n else if (type2 !== t) throw new Error(`scale incompatible with channel: ${type2} !== ${t}`);\n }\n if (type2 === typeProjection) return;\n if (type2 !== void 0) return type2;\n if (domain === void 0 && !channels.some(({ value }) => value !== void 0)) return;\n const kind = registry.get(key);\n if (kind === radius) return \"sqrt\";\n if (kind === opacity || kind === length3) return \"linear\";\n if (kind === symbol) return \"ordinal\";\n if ((domain || range3 || []).length > 2) return asOrdinalType(kind);\n if (domain !== void 0) {\n if (isOrdinal(domain)) return asOrdinalType(kind);\n if (isTemporal(domain)) return \"utc\";\n } else {\n const values2 = channels.map(({ value }) => value).filter((value) => value !== void 0);\n if (values2.some(isOrdinal)) return asOrdinalType(kind);\n if (values2.some(isTemporal)) return \"utc\";\n }\n if (kind === color2) {\n if (pivot != null || isDivergingScheme(scheme28)) return \"diverging\";\n if (isCategoricalScheme(scheme28)) return \"categorical\";\n }\n return \"linear\";\n}\nfunction asOrdinalType(kind) {\n switch (kind) {\n case position:\n return \"point\";\n case color2:\n return ordinalImplicit;\n default:\n return \"ordinal\";\n }\n}\nfunction isOrdinalScale({ type: type2 }) {\n return type2 === \"ordinal\" || type2 === \"point\" || type2 === \"band\" || type2 === ordinalImplicit;\n}\nfunction isThresholdScale({ type: type2 }) {\n return type2 === \"threshold\";\n}\nfunction isBandScale({ type: type2 }) {\n return type2 === \"point\" || type2 === \"band\";\n}\nfunction isCollapsed(scale3) {\n if (scale3 === void 0) return true;\n const domain = scale3.domain();\n const value = scale3(domain[0]);\n for (let i = 1, n = domain.length; i < n; ++i) {\n if (scale3(domain[i]) - value) {\n return false;\n }\n }\n return true;\n}\nfunction coerceType(channels, { domain, ...options }, coerceValues) {\n for (const c4 of channels) {\n if (c4.value !== void 0) {\n if (domain === void 0) domain = c4.value?.domain;\n c4.value = coerceValues(c4.value);\n }\n }\n return {\n domain: domain === void 0 ? domain : coerceValues(domain),\n ...options\n };\n}\nfunction coerceSymbols(values2) {\n return map3(values2, maybeSymbol);\n}\nfunction scale2(options = {}) {\n let scale3;\n for (const key in options) {\n if (!registry.has(key)) continue;\n if (!isScaleOptions(options[key])) continue;\n if (scale3 !== void 0) throw new Error(\"ambiguous scale definition; multiple scales found\");\n scale3 = exposeScale(normalizeScale(key, options[key]));\n }\n if (scale3 === void 0) throw new Error(\"invalid scale definition; no scale found\");\n return scale3;\n}\nfunction exposeScales(scales2) {\n return (key) => {\n if (!registry.has(key = `${key}`)) throw new Error(`unknown scale: ${key}`);\n return scales2[key];\n };\n}\nfunction exposeScale({ scale: scale3, type: type2, domain, range: range3, interpolate, interval: interval3, transform: transform3, percent, pivot }) {\n if (type2 === \"identity\") return { type: \"identity\", apply: (d) => d, invert: (d) => d };\n const unknown = scale3.unknown ? scale3.unknown() : void 0;\n return {\n type: type2,\n domain: slice3(domain),\n // defensive copy\n ...range3 !== void 0 && { range: slice3(range3) },\n // defensive copy\n ...transform3 !== void 0 && { transform: transform3 },\n ...percent && { percent },\n // only exposed if truthy\n ...unknown !== void 0 && { unknown },\n ...interval3 !== void 0 && { interval: interval3 },\n // quantitative\n ...interpolate !== void 0 && { interpolate },\n ...scale3.clamp && { clamp: scale3.clamp() },\n // diverging (always asymmetric; we never want to apply the symmetric transform twice)\n ...pivot !== void 0 && { pivot, symmetric: false },\n // log, diverging-log\n ...scale3.base && { base: scale3.base() },\n // pow, diverging-pow\n ...scale3.exponent && { exponent: scale3.exponent() },\n // symlog, diverging-symlog\n ...scale3.constant && { constant: scale3.constant() },\n // band, point\n ...scale3.align && { align: scale3.align(), round: scale3.round() },\n ...scale3.padding && (scale3.paddingInner ? { paddingInner: scale3.paddingInner(), paddingOuter: scale3.paddingOuter() } : { padding: scale3.padding() }),\n ...scale3.bandwidth && { bandwidth: scale3.bandwidth(), step: scale3.step() },\n // utilities\n apply: (t) => scale3(t),\n ...scale3.invert && { invert: (t) => scale3.invert(t) }\n };\n}\n\n// ../../node_modules/@observablehq/plot/src/facet.js\nfunction createFacets(channelsByScale, options) {\n const { fx, fy } = createScales(channelsByScale, options);\n const fxDomain2 = fx?.scale.domain();\n const fyDomain2 = fy?.scale.domain();\n return fxDomain2 && fyDomain2 ? cross(fxDomain2, fyDomain2).map(([x3, y3], i) => ({ x: x3, y: y3, i })) : fxDomain2 ? fxDomain2.map((x3, i) => ({ x: x3, i })) : fyDomain2 ? fyDomain2.map((y3, i) => ({ y: y3, i })) : void 0;\n}\nfunction recreateFacets(facets, { x: X3, y: Y3 }) {\n X3 &&= facetIndex(X3);\n Y3 &&= facetIndex(Y3);\n return facets.filter(\n X3 && Y3 ? (f) => X3.has(f.x) && Y3.has(f.y) : X3 ? (f) => X3.has(f.x) : (f) => Y3.has(f.y)\n ).sort(\n X3 && Y3 ? (a2, b) => X3.get(a2.x) - X3.get(b.x) || Y3.get(a2.y) - Y3.get(b.y) : X3 ? (a2, b) => X3.get(a2.x) - X3.get(b.x) : (a2, b) => Y3.get(a2.y) - Y3.get(b.y)\n );\n}\nfunction facetGroups(data, { fx, fy }) {\n const I = range2(data);\n const FX = fx?.value;\n const FY = fy?.value;\n return fx && fy ? rollup(\n I,\n (G) => (G.fx = FX[G[0]], G.fy = FY[G[0]], G),\n (i) => FX[i],\n (i) => FY[i]\n ) : fx ? rollup(\n I,\n (G) => (G.fx = FX[G[0]], G),\n (i) => FX[i]\n ) : rollup(\n I,\n (G) => (G.fy = FY[G[0]], G),\n (i) => FY[i]\n );\n}\nfunction facetTranslator(fx, fy, { marginTop: marginTop2, marginLeft: marginLeft2 }) {\n return fx && fy ? ({ x: x3, y: y3 }) => `translate(${fx(x3) - marginLeft2},${fy(y3) - marginTop2})` : fx ? ({ x: x3 }) => `translate(${fx(x3) - marginLeft2},0)` : ({ y: y3 }) => `translate(0,${fy(y3) - marginTop2})`;\n}\nfunction facetExclude(index2) {\n const ex = [];\n const e = new Uint32Array(sum2(index2, (d) => d.length));\n for (const i of index2) {\n let n = 0;\n for (const j of index2) {\n if (i === j) continue;\n e.set(j, n);\n n += j.length;\n }\n ex.push(e.slice(0, n));\n }\n return ex;\n}\nvar facetAnchors = /* @__PURE__ */ new Map([\n [\"top\", facetAnchorTop],\n [\"right\", facetAnchorRight],\n [\"bottom\", facetAnchorBottom],\n [\"left\", facetAnchorLeft],\n [\"top-left\", and2(facetAnchorTop, facetAnchorLeft)],\n [\"top-right\", and2(facetAnchorTop, facetAnchorRight)],\n [\"bottom-left\", and2(facetAnchorBottom, facetAnchorLeft)],\n [\"bottom-right\", and2(facetAnchorBottom, facetAnchorRight)],\n [\"top-empty\", facetAnchorTopEmpty],\n [\"right-empty\", facetAnchorRightEmpty],\n [\"bottom-empty\", facetAnchorBottomEmpty],\n [\"left-empty\", facetAnchorLeftEmpty],\n [\"empty\", facetAnchorEmpty]\n]);\nfunction maybeFacetAnchor(facetAnchor) {\n if (facetAnchor == null) return null;\n const anchor = facetAnchors.get(`${facetAnchor}`.toLowerCase());\n if (anchor) return anchor;\n throw new Error(`invalid facet anchor: ${facetAnchor}`);\n}\nvar indexCache = /* @__PURE__ */ new WeakMap();\nfunction facetIndex(V) {\n let I = indexCache.get(V);\n if (!I) indexCache.set(V, I = new InternMap(map3(V, (v2, i) => [v2, i])));\n return I;\n}\nfunction facetIndexOf(V, v2) {\n return facetIndex(V).get(v2);\n}\nfunction facetFind(facets, x3, y3) {\n x3 = keyof2(x3);\n y3 = keyof2(y3);\n return facets.find((f) => Object.is(keyof2(f.x), x3) && Object.is(keyof2(f.y), y3));\n}\nfunction facetEmpty(facets, x3, y3) {\n return facetFind(facets, x3, y3)?.empty;\n}\nfunction facetAnchorTop(facets, { y: Y3 }, { y: y3 }) {\n return Y3 ? facetIndexOf(Y3, y3) === 0 : true;\n}\nfunction facetAnchorBottom(facets, { y: Y3 }, { y: y3 }) {\n return Y3 ? facetIndexOf(Y3, y3) === Y3.length - 1 : true;\n}\nfunction facetAnchorLeft(facets, { x: X3 }, { x: x3 }) {\n return X3 ? facetIndexOf(X3, x3) === 0 : true;\n}\nfunction facetAnchorRight(facets, { x: X3 }, { x: x3 }) {\n return X3 ? facetIndexOf(X3, x3) === X3.length - 1 : true;\n}\nfunction facetAnchorTopEmpty(facets, { y: Y3 }, { x: x3, y: y3, empty: empty4 }) {\n if (empty4) return false;\n if (!Y3) return;\n const i = facetIndexOf(Y3, y3);\n if (i > 0) return facetEmpty(facets, x3, Y3[i - 1]);\n}\nfunction facetAnchorBottomEmpty(facets, { y: Y3 }, { x: x3, y: y3, empty: empty4 }) {\n if (empty4) return false;\n if (!Y3) return;\n const i = facetIndexOf(Y3, y3);\n if (i < Y3.length - 1) return facetEmpty(facets, x3, Y3[i + 1]);\n}\nfunction facetAnchorLeftEmpty(facets, { x: X3 }, { x: x3, y: y3, empty: empty4 }) {\n if (empty4) return false;\n if (!X3) return;\n const i = facetIndexOf(X3, x3);\n if (i > 0) return facetEmpty(facets, X3[i - 1], y3);\n}\nfunction facetAnchorRightEmpty(facets, { x: X3 }, { x: x3, y: y3, empty: empty4 }) {\n if (empty4) return false;\n if (!X3) return;\n const i = facetIndexOf(X3, x3);\n if (i < X3.length - 1) return facetEmpty(facets, X3[i + 1], y3);\n}\nfunction facetAnchorEmpty(facets, channels, { empty: empty4 }) {\n return empty4;\n}\nfunction and2(a2, b) {\n return function() {\n return a2.apply(null, arguments) && b.apply(null, arguments);\n };\n}\nfunction facetFilter(facets, { channels: { fx, fy }, groups: groups2 }) {\n return fx && fy ? facets.map(({ x: x3, y: y3 }) => groups2.get(x3)?.get(y3) ?? []) : fx ? facets.map(({ x: x3 }) => groups2.get(x3) ?? []) : facets.map(({ y: y3 }) => groups2.get(y3) ?? []);\n}\n\n// ../../node_modules/@observablehq/plot/src/projection.js\nvar pi4 = Math.PI;\nvar tau5 = 2 * pi4;\nvar defaultAspectRatio = 0.618;\nfunction createProjection({\n projection: projection3,\n inset: globalInset = 0,\n insetTop = globalInset,\n insetRight = globalInset,\n insetBottom = globalInset,\n insetLeft = globalInset\n} = {}, dimensions) {\n if (projection3 == null) return;\n if (typeof projection3.stream === \"function\") return projection3;\n let options;\n let domain;\n let clip = \"frame\";\n if (isObject(projection3)) {\n let inset2;\n ({\n type: projection3,\n domain,\n inset: inset2,\n insetTop = inset2 !== void 0 ? inset2 : insetTop,\n insetRight = inset2 !== void 0 ? inset2 : insetRight,\n insetBottom = inset2 !== void 0 ? inset2 : insetBottom,\n insetLeft = inset2 !== void 0 ? inset2 : insetLeft,\n clip = clip,\n ...options\n } = projection3);\n if (projection3 == null) return;\n }\n if (typeof projection3 !== \"function\") ({ type: projection3 } = namedProjection(projection3));\n const { width: width2, height: height2, marginLeft: marginLeft2, marginRight: marginRight2, marginTop: marginTop2, marginBottom: marginBottom2 } = dimensions;\n const dx = width2 - marginLeft2 - marginRight2 - insetLeft - insetRight;\n const dy = height2 - marginTop2 - marginBottom2 - insetTop - insetBottom;\n projection3 = projection3?.({ width: dx, height: dy, clip, ...options });\n if (projection3 == null) return;\n clip = maybePostClip(clip, marginLeft2, marginTop2, width2 - marginRight2, height2 - marginBottom2);\n let tx = marginLeft2 + insetLeft;\n let ty = marginTop2 + insetTop;\n let transform3;\n if (domain != null) {\n const [[x06, y06], [x12, y12]] = path_default(projection3).bounds(domain);\n const k2 = Math.min(dx / (x12 - x06), dy / (y12 - y06));\n if (k2 > 0) {\n tx -= (k2 * (x06 + x12) - dx) / 2;\n ty -= (k2 * (y06 + y12) - dy) / 2;\n transform3 = transform_default({\n point(x3, y3) {\n this.stream.point(x3 * k2 + tx, y3 * k2 + ty);\n }\n });\n } else {\n warn(`Warning: the projection could not be fit to the specified domain; using the default scale.`);\n }\n }\n transform3 ??= tx === 0 && ty === 0 ? identity8() : transform_default({\n point(x3, y3) {\n this.stream.point(x3 + tx, y3 + ty);\n }\n });\n return { stream: (s2) => projection3.stream(transform3.stream(clip(s2))) };\n}\nfunction namedProjection(projection3) {\n switch (`${projection3}`.toLowerCase()) {\n case \"albers-usa\":\n return scaleProjection(albersUsa_default, 0.7463, 0.4673);\n case \"albers\":\n return conicProjection2(albers_default, 0.7463, 0.4673);\n case \"azimuthal-equal-area\":\n return scaleProjection(azimuthalEqualArea_default, 4, 4);\n case \"azimuthal-equidistant\":\n return scaleProjection(azimuthalEquidistant_default, tau5, tau5);\n case \"conic-conformal\":\n return conicProjection2(conicConformal_default, tau5, tau5);\n case \"conic-equal-area\":\n return conicProjection2(conicEqualArea_default, 6.1702, 2.9781);\n case \"conic-equidistant\":\n return conicProjection2(conicEquidistant_default, 7.312, 3.6282);\n case \"equal-earth\":\n return scaleProjection(equalEarth_default, 5.4133, 2.6347);\n case \"equirectangular\":\n return scaleProjection(equirectangular_default, tau5, pi4);\n case \"gnomonic\":\n return scaleProjection(gnomonic_default, 3.4641, 3.4641);\n case \"identity\":\n return { type: identity8 };\n case \"reflect-y\":\n return { type: reflectY };\n case \"mercator\":\n return scaleProjection(mercator_default, tau5, tau5);\n case \"orthographic\":\n return scaleProjection(orthographic_default, 2, 2);\n case \"stereographic\":\n return scaleProjection(stereographic_default, 2, 2);\n case \"transverse-mercator\":\n return scaleProjection(transverseMercator_default, tau5, tau5);\n default:\n throw new Error(`unknown projection type: ${projection3}`);\n }\n}\nfunction maybePostClip(clip, x12, y12, x22, y22) {\n if (clip === false || clip == null || typeof clip === \"number\") return (s2) => s2;\n if (clip === true) clip = \"frame\";\n switch (`${clip}`.toLowerCase()) {\n case \"frame\":\n return clipRectangle(x12, y12, x22, y22);\n default:\n throw new Error(`unknown projection clip type: ${clip}`);\n }\n}\nfunction scaleProjection(createProjection2, kx2, ky2) {\n return {\n type: ({ width: width2, height: height2, rotate, precision = 0.15, clip }) => {\n const projection3 = createProjection2();\n if (precision != null) projection3.precision?.(precision);\n if (rotate != null) projection3.rotate?.(rotate);\n if (typeof clip === \"number\") projection3.clipAngle?.(clip);\n if (width2 != null) {\n projection3.scale(Math.min(width2 / kx2, height2 / ky2));\n projection3.translate([width2 / 2, height2 / 2]);\n }\n return projection3;\n },\n aspectRatio: ky2 / kx2\n };\n}\nfunction conicProjection2(createProjection2, kx2, ky2) {\n const { type: type2, aspectRatio: aspectRatio2 } = scaleProjection(createProjection2, kx2, ky2);\n return {\n type: (options) => {\n const { parallels, domain, width: width2, height: height2 } = options;\n const projection3 = type2(options);\n if (parallels != null) {\n projection3.parallels(parallels);\n if (domain === void 0 && width2 != null) {\n projection3.fitSize([width2, height2], { type: \"Sphere\" });\n }\n }\n return projection3;\n },\n aspectRatio: aspectRatio2\n };\n}\nvar identity8 = constant({ stream: (stream) => stream });\nvar reflectY = constant(\n transform_default({\n point(x3, y3) {\n this.stream.point(x3, -y3);\n }\n })\n);\nfunction project(cx, cy, values2, projection3) {\n const x3 = values2[cx];\n const y3 = values2[cy];\n const n = x3.length;\n const X3 = values2[cx] = new Float64Array(n).fill(NaN);\n const Y3 = values2[cy] = new Float64Array(n).fill(NaN);\n let i;\n const stream = projection3.stream({\n point(x4, y4) {\n X3[i] = x4;\n Y3[i] = y4;\n }\n });\n for (i = 0; i < n; ++i) {\n stream.point(x3[i], y3[i]);\n }\n}\nfunction hasProjection({ projection: projection3 } = {}) {\n if (projection3 == null) return false;\n if (typeof projection3.stream === \"function\") return true;\n if (isObject(projection3)) projection3 = projection3.type;\n return projection3 != null;\n}\nfunction projectionAspectRatio(projection3) {\n if (typeof projection3?.stream === \"function\") return defaultAspectRatio;\n if (isObject(projection3)) {\n let domain, options;\n ({ domain, type: projection3, ...options } = projection3);\n if (domain != null && projection3 != null) {\n const type2 = typeof projection3 === \"string\" ? namedProjection(projection3).type : projection3;\n const [[x06, y06], [x12, y12]] = path_default(type2({ ...options, width: 100, height: 100 })).bounds(domain);\n const r = (y12 - y06) / (x12 - x06);\n return r && isFinite(r) ? r < 0.2 ? 0.2 : r > 5 ? 5 : r : defaultAspectRatio;\n }\n }\n if (projection3 == null) return;\n if (typeof projection3 !== \"function\") {\n const { aspectRatio: aspectRatio2 } = namedProjection(projection3);\n if (aspectRatio2) return aspectRatio2;\n }\n return defaultAspectRatio;\n}\nfunction applyPosition(channels, scales2, { projection: projection3 }) {\n const { x: x3, y: y3 } = channels;\n let position3 = {};\n if (x3) position3.x = x3;\n if (y3) position3.y = y3;\n position3 = valueObject(position3, scales2);\n if (projection3 && x3?.scale === \"x\" && y3?.scale === \"y\") project(\"x\", \"y\", position3, projection3);\n if (x3) position3.x = coerceNumbers(position3.x);\n if (y3) position3.y = coerceNumbers(position3.y);\n return position3;\n}\nfunction getGeometryChannels(channel) {\n const X3 = [];\n const Y3 = [];\n const x3 = { scale: \"x\", value: X3 };\n const y3 = { scale: \"y\", value: Y3 };\n const sink = {\n point(x4, y4) {\n X3.push(x4);\n Y3.push(y4);\n },\n lineStart() {\n },\n lineEnd() {\n },\n polygonStart() {\n },\n polygonEnd() {\n },\n sphere() {\n }\n };\n for (const object of channel.value) stream_default(object, sink);\n return [x3, y3];\n}\n\n// ../../node_modules/@observablehq/plot/src/context.js\nfunction createContext(options = {}) {\n const { document: document2 = typeof window !== \"undefined\" ? window.document : void 0, clip } = options;\n return { document: document2, clip: maybeClip(clip) };\n}\nfunction create4(name2, { document: document2 }) {\n return select_default2(creator_default(name2).call(document2.documentElement));\n}\n\n// ../../node_modules/@observablehq/plot/src/memoize.js\nvar unset = Symbol(\"unset\");\nfunction memoize1(compute) {\n return (compute.length === 1 ? memoize1Arg : memoize1Args)(compute);\n}\nfunction memoize1Arg(compute) {\n let cacheValue;\n let cacheKey = unset;\n return (key) => {\n if (!Object.is(cacheKey, key)) {\n cacheKey = key;\n cacheValue = compute(key);\n }\n return cacheValue;\n };\n}\nfunction memoize1Args(compute) {\n let cacheValue, cacheKeys;\n return (...keys) => {\n if (cacheKeys?.length !== keys.length || cacheKeys.some((k2, i) => !Object.is(k2, keys[i]))) {\n cacheKeys = keys;\n cacheValue = compute(...keys);\n }\n return cacheValue;\n };\n}\n\n// ../../node_modules/@observablehq/plot/src/format.js\nvar numberFormat = memoize1((locale3) => {\n return new Intl.NumberFormat(locale3);\n});\nvar monthFormat = memoize1((locale3, month) => {\n return new Intl.DateTimeFormat(locale3, { timeZone: \"UTC\", ...month && { month } });\n});\nvar weekdayFormat = memoize1((locale3, weekday) => {\n return new Intl.DateTimeFormat(locale3, { timeZone: \"UTC\", ...weekday && { weekday } });\n});\nfunction formatNumber(locale3 = \"en-US\") {\n const format3 = numberFormat(locale3);\n return (i) => i != null && !isNaN(i) ? format3.format(i) : void 0;\n}\nfunction formatMonth(locale3 = \"en-US\", format3 = \"short\") {\n const fmt = monthFormat(locale3, format3);\n return (i) => i != null && !isNaN(i = +new Date(Date.UTC(2e3, +i))) ? fmt.format(i) : void 0;\n}\nfunction formatWeekday(locale3 = \"en-US\", format3 = \"short\") {\n const fmt = weekdayFormat(locale3, format3);\n return (i) => i != null && !isNaN(i = +new Date(Date.UTC(2001, 0, +i))) ? fmt.format(i) : void 0;\n}\nfunction formatIsoDate(date3) {\n return format2(date3, \"Invalid Date\");\n}\nfunction formatAuto(locale3 = \"en-US\") {\n const number7 = formatNumber(locale3);\n return (v2) => (v2 instanceof Date ? formatIsoDate : typeof v2 === \"number\" ? number7 : string)(v2);\n}\nvar formatDefault = formatAuto();\n\n// ../../node_modules/@observablehq/plot/src/style.js\nvar offset = (typeof window !== \"undefined\" ? window.devicePixelRatio > 1 : typeof it === \"undefined\") ? 0 : 0.5;\nvar nextClipId = 0;\nvar nextPatternId = 0;\nfunction getClipId() {\n return `plot-clip-${++nextClipId}`;\n}\nfunction getPatternId() {\n return `plot-pattern-${++nextPatternId}`;\n}\nfunction styles(mark2, {\n title,\n href,\n ariaLabel: variaLabel,\n ariaDescription,\n ariaHidden,\n target,\n fill,\n fillOpacity,\n stroke,\n strokeWidth,\n strokeOpacity,\n strokeLinejoin,\n strokeLinecap,\n strokeMiterlimit,\n strokeDasharray,\n strokeDashoffset,\n opacity: opacity2,\n mixBlendMode,\n imageFilter,\n paintOrder,\n pointerEvents,\n shapeRendering,\n channels\n}, {\n ariaLabel: cariaLabel,\n fill: defaultFill = \"currentColor\",\n fillOpacity: defaultFillOpacity,\n stroke: defaultStroke = \"none\",\n strokeOpacity: defaultStrokeOpacity,\n strokeWidth: defaultStrokeWidth,\n strokeLinecap: defaultStrokeLinecap,\n strokeLinejoin: defaultStrokeLinejoin,\n strokeMiterlimit: defaultStrokeMiterlimit,\n paintOrder: defaultPaintOrder\n}) {\n if (defaultFill === null) {\n fill = null;\n fillOpacity = null;\n }\n if (defaultStroke === null) {\n stroke = null;\n strokeOpacity = null;\n }\n if (isNoneish(defaultFill)) {\n if (!isNoneish(defaultStroke) && (!isNoneish(fill) || channels?.fill)) defaultStroke = \"none\";\n } else {\n if (isNoneish(defaultStroke) && (!isNoneish(stroke) || channels?.stroke)) defaultFill = \"none\";\n }\n const [vfill, cfill] = maybeColorChannel(fill, defaultFill);\n const [vfillOpacity, cfillOpacity] = maybeNumberChannel(fillOpacity, defaultFillOpacity);\n const [vstroke, cstroke] = maybeColorChannel(stroke, defaultStroke);\n const [vstrokeOpacity, cstrokeOpacity] = maybeNumberChannel(strokeOpacity, defaultStrokeOpacity);\n const [vopacity, copacity] = maybeNumberChannel(opacity2);\n if (!isNone(cstroke)) {\n if (strokeWidth === void 0) strokeWidth = defaultStrokeWidth;\n if (strokeLinecap === void 0) strokeLinecap = defaultStrokeLinecap;\n if (strokeLinejoin === void 0) strokeLinejoin = defaultStrokeLinejoin;\n if (strokeMiterlimit === void 0 && !isRound(strokeLinejoin)) strokeMiterlimit = defaultStrokeMiterlimit;\n if (!isNone(cfill) && paintOrder === void 0) paintOrder = defaultPaintOrder;\n }\n const [vstrokeWidth, cstrokeWidth] = maybeNumberChannel(strokeWidth);\n if (defaultFill !== null) {\n mark2.fill = impliedString(cfill, \"currentColor\");\n mark2.fillOpacity = impliedNumber(cfillOpacity, 1);\n }\n if (defaultStroke !== null) {\n mark2.stroke = impliedString(cstroke, \"none\");\n mark2.strokeWidth = impliedNumber(cstrokeWidth, 1);\n mark2.strokeOpacity = impliedNumber(cstrokeOpacity, 1);\n mark2.strokeLinejoin = impliedString(strokeLinejoin, \"miter\");\n mark2.strokeLinecap = impliedString(strokeLinecap, \"butt\");\n mark2.strokeMiterlimit = impliedNumber(strokeMiterlimit, 4);\n mark2.strokeDasharray = impliedString(strokeDasharray, \"none\");\n mark2.strokeDashoffset = impliedString(strokeDashoffset, \"0\");\n }\n mark2.target = string(target);\n mark2.ariaLabel = string(cariaLabel);\n mark2.ariaDescription = string(ariaDescription);\n mark2.ariaHidden = string(ariaHidden);\n mark2.opacity = impliedNumber(copacity, 1);\n mark2.mixBlendMode = impliedString(mixBlendMode, \"normal\");\n mark2.imageFilter = impliedString(imageFilter, \"none\");\n mark2.paintOrder = impliedString(paintOrder, \"normal\");\n mark2.pointerEvents = impliedString(pointerEvents, \"auto\");\n mark2.shapeRendering = impliedString(shapeRendering, \"auto\");\n return {\n title: { value: title, optional: true, filter: null },\n href: { value: href, optional: true, filter: null },\n ariaLabel: { value: variaLabel, optional: true, filter: null },\n fill: { value: vfill, scale: \"auto\", optional: true },\n fillOpacity: { value: vfillOpacity, scale: \"auto\", optional: true },\n stroke: { value: vstroke, scale: \"auto\", optional: true },\n strokeOpacity: { value: vstrokeOpacity, scale: \"auto\", optional: true },\n strokeWidth: { value: vstrokeWidth, optional: true },\n opacity: { value: vopacity, scale: \"auto\", optional: true }\n };\n}\nfunction applyTitle(selection2, L) {\n if (L)\n selection2.filter((i) => nonempty(L[i])).append(\"title\").call(applyText, L);\n}\nfunction applyTitleGroup(selection2, L) {\n if (L)\n selection2.filter(([i]) => nonempty(L[i])).append(\"title\").call(applyTextGroup, L);\n}\nfunction applyText(selection2, T) {\n if (T) selection2.text((i) => formatDefault(T[i]));\n}\nfunction applyTextGroup(selection2, T) {\n if (T) selection2.text(([i]) => formatDefault(T[i]));\n}\nfunction applyChannelStyles(selection2, { target, tip: tip2 }, {\n ariaLabel: AL,\n title: T,\n fill: F,\n fillOpacity: FO,\n stroke: S,\n strokeOpacity: SO,\n strokeWidth: SW,\n opacity: O,\n href: H\n}) {\n if (AL) applyAttr(selection2, \"aria-label\", (i) => AL[i]);\n if (F) applyAttr(selection2, \"fill\", (i) => F[i]);\n if (FO) applyAttr(selection2, \"fill-opacity\", (i) => FO[i]);\n if (S) applyAttr(selection2, \"stroke\", (i) => S[i]);\n if (SO) applyAttr(selection2, \"stroke-opacity\", (i) => SO[i]);\n if (SW) applyAttr(selection2, \"stroke-width\", (i) => SW[i]);\n if (O) applyAttr(selection2, \"opacity\", (i) => O[i]);\n if (H) applyHref(selection2, (i) => H[i], target);\n if (!tip2) applyTitle(selection2, T);\n}\nfunction applyGroupedChannelStyles(selection2, { target, tip: tip2 }, {\n ariaLabel: AL,\n title: T,\n fill: F,\n fillOpacity: FO,\n stroke: S,\n strokeOpacity: SO,\n strokeWidth: SW,\n opacity: O,\n href: H\n}) {\n if (AL) applyAttr(selection2, \"aria-label\", ([i]) => AL[i]);\n if (F) applyAttr(selection2, \"fill\", ([i]) => F[i]);\n if (FO) applyAttr(selection2, \"fill-opacity\", ([i]) => FO[i]);\n if (S) applyAttr(selection2, \"stroke\", ([i]) => S[i]);\n if (SO) applyAttr(selection2, \"stroke-opacity\", ([i]) => SO[i]);\n if (SW) applyAttr(selection2, \"stroke-width\", ([i]) => SW[i]);\n if (O) applyAttr(selection2, \"opacity\", ([i]) => O[i]);\n if (H) applyHref(selection2, ([i]) => H[i], target);\n if (!tip2) applyTitleGroup(selection2, T);\n}\nfunction groupAesthetics({\n ariaLabel: AL,\n title: T,\n fill: F,\n fillOpacity: FO,\n stroke: S,\n strokeOpacity: SO,\n strokeWidth: SW,\n opacity: O,\n href: H\n}, { tip: tip2 }) {\n return [AL, tip2 ? void 0 : T, F, FO, S, SO, SW, O, H].filter((c4) => c4 !== void 0);\n}\nfunction groupZ2(I, Z, z) {\n const G = group(I, (i) => Z[i]);\n if (z === void 0 && G.size > 1 + I.length >> 1) {\n warn(\n `Warning: the implicit z channel has high cardinality. This may occur when the fill or stroke channel is associated with quantitative data rather than ordinal or categorical data. You can suppress this warning by setting the z option explicitly; if this data represents a single series, set z to null.`\n );\n }\n return G.values();\n}\nfunction* groupIndex(I, position3, mark2, channels) {\n const { z } = mark2;\n const { z: Z } = channels;\n const A5 = groupAesthetics(channels, mark2);\n const C3 = [...position3, ...A5];\n for (const G of Z ? groupZ2(I, Z, z) : [I]) {\n let Ag;\n let Gg;\n out: for (const i of G) {\n for (const c4 of C3) {\n if (!defined(c4[i])) {\n if (Gg) Gg.push(-1);\n continue out;\n }\n }\n if (Ag === void 0) {\n if (Gg) yield Gg;\n Ag = A5.map((c4) => keyof2(c4[i])), Gg = [i];\n continue;\n }\n Gg.push(i);\n for (let j = 0; j < A5.length; ++j) {\n const k2 = keyof2(A5[j][i]);\n if (k2 !== Ag[j]) {\n yield Gg;\n Ag = A5.map((c4) => keyof2(c4[i])), Gg = [i];\n continue out;\n }\n }\n }\n if (Gg) yield Gg;\n }\n}\nfunction applyClip(selection2, mark2, dimensions, context) {\n let clipUrl;\n const { clip = context.clip } = mark2;\n switch (clip) {\n case \"frame\": {\n selection2 = create4(\"svg:g\", context).each(function() {\n this.appendChild(selection2.node());\n selection2.node = () => this;\n });\n clipUrl = getFrameClip(context, dimensions);\n break;\n }\n case \"sphere\": {\n clipUrl = getProjectionClip(context);\n break;\n }\n }\n applyAttr(selection2, \"aria-label\", mark2.ariaLabel);\n applyAttr(selection2, \"aria-description\", mark2.ariaDescription);\n applyAttr(selection2, \"aria-hidden\", mark2.ariaHidden);\n applyAttr(selection2, \"clip-path\", clipUrl);\n}\nfunction memoizeClip(clip) {\n const cache = /* @__PURE__ */ new WeakMap();\n return (context, dimensions) => {\n let url = cache.get(context);\n if (!url) {\n const id2 = getClipId();\n select_default2(context.ownerSVGElement).append(\"clipPath\").attr(\"id\", id2).call(clip, context, dimensions);\n cache.set(context, url = `url(#${id2})`);\n }\n return url;\n };\n}\nvar getFrameClip = memoizeClip((clipPath, context, dimensions) => {\n const { width: width2, height: height2, marginLeft: marginLeft2, marginRight: marginRight2, marginTop: marginTop2, marginBottom: marginBottom2 } = dimensions;\n clipPath.append(\"rect\").attr(\"x\", marginLeft2).attr(\"y\", marginTop2).attr(\"width\", width2 - marginRight2 - marginLeft2).attr(\"height\", height2 - marginTop2 - marginBottom2);\n});\nvar getProjectionClip = memoizeClip((clipPath, context) => {\n const { projection: projection3 } = context;\n if (!projection3) throw new Error(`the \"sphere\" clip option requires a projection`);\n clipPath.append(\"path\").attr(\"d\", path_default(projection3)({ type: \"Sphere\" }));\n});\nfunction applyIndirectStyles(selection2, mark2, dimensions, context) {\n applyClip(selection2, mark2, dimensions, context);\n applyAttr(selection2, \"class\", mark2.className);\n applyAttr(selection2, \"fill\", mark2.fill);\n applyAttr(selection2, \"fill-opacity\", mark2.fillOpacity);\n applyAttr(selection2, \"stroke\", mark2.stroke);\n applyAttr(selection2, \"stroke-width\", mark2.strokeWidth);\n applyAttr(selection2, \"stroke-opacity\", mark2.strokeOpacity);\n applyAttr(selection2, \"stroke-linejoin\", mark2.strokeLinejoin);\n applyAttr(selection2, \"stroke-linecap\", mark2.strokeLinecap);\n applyAttr(selection2, \"stroke-miterlimit\", mark2.strokeMiterlimit);\n applyAttr(selection2, \"stroke-dasharray\", mark2.strokeDasharray);\n applyAttr(selection2, \"stroke-dashoffset\", mark2.strokeDashoffset);\n applyAttr(selection2, \"shape-rendering\", mark2.shapeRendering);\n applyAttr(selection2, \"filter\", mark2.imageFilter);\n applyAttr(selection2, \"paint-order\", mark2.paintOrder);\n const { pointerEvents = context.pointerSticky === false ? \"none\" : void 0 } = mark2;\n applyAttr(selection2, \"pointer-events\", pointerEvents);\n}\nfunction applyDirectStyles(selection2, mark2) {\n applyStyle(selection2, \"mix-blend-mode\", mark2.mixBlendMode);\n applyAttr(selection2, \"opacity\", mark2.opacity);\n}\nfunction applyHref(selection2, href, target) {\n selection2.each(function(i) {\n const h = href(i);\n if (h != null) {\n const a2 = this.ownerDocument.createElementNS(namespaces_default.svg, \"a\");\n a2.setAttribute(\"fill\", \"inherit\");\n a2.setAttributeNS(namespaces_default.xlink, \"href\", h);\n if (target != null) a2.setAttribute(\"target\", target);\n this.parentNode.insertBefore(a2, this).appendChild(this);\n }\n });\n}\nfunction applyAttr(selection2, name2, value) {\n if (value != null) selection2.attr(name2, value);\n}\nfunction applyStyle(selection2, name2, value) {\n if (value != null) selection2.style(name2, value);\n}\nfunction applyTransform(selection2, mark2, { x: x3, y: y3 }, tx = offset, ty = offset) {\n tx += mark2.dx;\n ty += mark2.dy;\n if (x3?.bandwidth) tx += x3.bandwidth() / 2;\n if (y3?.bandwidth) ty += y3.bandwidth() / 2;\n if (tx || ty) selection2.attr(\"transform\", `translate(${tx},${ty})`);\n}\nfunction impliedString(value, impliedValue) {\n if ((value = string(value)) !== impliedValue) return value;\n}\nfunction impliedNumber(value, impliedValue) {\n if ((value = number5(value)) !== impliedValue) return value;\n}\nvar validClassName = /^-?([_a-z]|[\\240-\\377]|\\\\[0-9a-f]{1,6}(\\r\\n|[ \\t\\r\\n\\f])?|\\\\[^\\r\\n\\f0-9a-f])([_a-z0-9-]|[\\240-\\377]|\\\\[0-9a-f]{1,6}(\\r\\n|[ \\t\\r\\n\\f])?|\\\\[^\\r\\n\\f0-9a-f])*$/i;\nfunction maybeClassName(name2) {\n if (name2 === void 0) return \"plot-d6a7b5\";\n name2 = `${name2}`;\n if (!validClassName.test(name2)) throw new Error(`invalid class name: ${name2}`);\n return name2;\n}\nfunction applyInlineStyles(selection2, style2) {\n if (typeof style2 === \"string\") {\n selection2.property(\"style\", style2);\n } else if (style2 != null) {\n for (const element of selection2) {\n Object.assign(element.style, style2);\n }\n }\n}\nfunction applyFrameAnchor({ frameAnchor }, { width: width2, height: height2, marginTop: marginTop2, marginRight: marginRight2, marginBottom: marginBottom2, marginLeft: marginLeft2 }) {\n return [\n /left$/.test(frameAnchor) ? marginLeft2 : /right$/.test(frameAnchor) ? width2 - marginRight2 : (marginLeft2 + width2 - marginRight2) / 2,\n /^top/.test(frameAnchor) ? marginTop2 : /^bottom/.test(frameAnchor) ? height2 - marginBottom2 : (marginTop2 + height2 - marginBottom2) / 2\n ];\n}\n\n// ../../node_modules/@observablehq/plot/src/mark.js\nvar Mark = class {\n constructor(data, channels = {}, options = {}, defaults22) {\n const {\n facet = \"auto\",\n facetAnchor,\n fx,\n fy,\n sort: sort3,\n dx = 0,\n dy = 0,\n margin: margin2 = 0,\n marginTop: marginTop2 = margin2,\n marginRight: marginRight2 = margin2,\n marginBottom: marginBottom2 = margin2,\n marginLeft: marginLeft2 = margin2,\n className,\n clip = defaults22?.clip,\n channels: extraChannels,\n tip: tip2,\n render\n } = options;\n this.data = data;\n this.sort = isDomainSort(sort3) ? sort3 : null;\n this.initializer = initializer(options).initializer;\n this.transform = this.initializer ? options.transform : basic(options).transform;\n if (facet === null || facet === false) {\n this.facet = null;\n } else {\n this.facet = keyword(facet === true ? \"include\" : facet, \"facet\", [\"auto\", \"include\", \"exclude\", \"super\"]);\n this.fx = data === singleton && typeof fx === \"string\" ? [fx] : fx;\n this.fy = data === singleton && typeof fy === \"string\" ? [fy] : fy;\n }\n this.facetAnchor = maybeFacetAnchor(facetAnchor);\n channels = maybeNamed(channels);\n if (extraChannels !== void 0) channels = { ...maybeChannels(extraChannels), ...channels };\n if (defaults22 !== void 0) channels = { ...styles(this, options, defaults22), ...channels };\n this.channels = Object.fromEntries(\n Object.entries(channels).map(([name2, channel]) => {\n if (isOptions(channel.value)) {\n const { value, label: label2 = channel.label, scale: scale3 = channel.scale } = channel.value;\n channel = { ...channel, label: label2, scale: scale3, value };\n }\n if (data === singleton && typeof channel.value === \"string\") {\n const { value } = channel;\n channel = { ...channel, value: [value] };\n }\n return [name2, channel];\n }).filter(([name2, { value, optional: optional2 }]) => {\n if (value != null) return true;\n if (optional2) return false;\n throw new Error(`missing channel value: ${name2}`);\n })\n );\n this.dx = +dx;\n this.dy = +dy;\n this.marginTop = +marginTop2;\n this.marginRight = +marginRight2;\n this.marginBottom = +marginBottom2;\n this.marginLeft = +marginLeft2;\n this.clip = maybeClip(clip);\n this.tip = maybeTip(tip2);\n this.className = className ? maybeClassName(className) : null;\n if (this.facet === \"super\") {\n if (fx || fy) throw new Error(`super-faceting cannot use fx or fy`);\n for (const name2 in this.channels) {\n const { scale: scale3 } = channels[name2];\n if (scale3 !== \"x\" && scale3 !== \"y\") continue;\n throw new Error(`super-faceting cannot use x or y`);\n }\n }\n if (render != null) {\n this.render = composeRender(render, this.render);\n }\n }\n initialize(facets, facetChannels, plotOptions) {\n let data = dataify(this.data);\n if (facets === void 0 && data != null) facets = [range2(data)];\n const originalFacets = facets;\n if (this.transform != null) ({ facets, data } = this.transform(data, facets, plotOptions)), data = dataify(data);\n if (facets !== void 0) facets.original = originalFacets;\n const channels = createChannels(this.channels, data);\n if (this.sort != null) channelDomain(data, facets, channels, facetChannels, this.sort);\n return { data, facets, channels };\n }\n filter(index2, channels, values2) {\n for (const name2 in channels) {\n const { filter: filter3 = defined } = channels[name2];\n if (filter3 !== null) {\n const value = values2[name2];\n index2 = index2.filter((i) => filter3(value[i]));\n }\n }\n return index2;\n }\n // If there is a projection, and there are paired x and y channels associated\n // with the x and y scale respectively (and not already in screen coordinates\n // as with an initializer), then apply the projection, replacing the x and y\n // values. Note that the x and y scales themselves don’t exist if there is a\n // projection, but whether the channels are associated with scales still\n // determines whether the projection should apply; think of the projection as\n // a combination xy-scale.\n project(channels, values2, context) {\n for (const cx in channels) {\n if (channels[cx].scale === \"x\" && /^x|x$/.test(cx)) {\n const cy = cx.replace(/^x|x$/, \"y\");\n if (cy in channels && channels[cy].scale === \"y\") {\n project(cx, cy, values2, context.projection);\n }\n }\n }\n }\n scale(channels, scales2, context) {\n const values2 = valueObject(channels, scales2);\n if (context.projection) this.project(channels, values2, context);\n return values2;\n }\n};\nfunction marks(...marks2) {\n marks2.plot = Mark.prototype.plot;\n return marks2;\n}\nfunction composeRender(r1, r2) {\n if (r1 == null) return r2 === null ? void 0 : r2;\n if (r2 == null) return r1 === null ? void 0 : r1;\n if (typeof r1 !== \"function\") throw new TypeError(`invalid render transform: ${r1}`);\n if (typeof r2 !== \"function\") throw new TypeError(`invalid render transform: ${r2}`);\n return function(i, s2, v2, d, c4, next) {\n return r1.call(this, i, s2, v2, d, c4, (i2, s3, v3, d2, c5) => {\n return r2.call(this, i2, s3, v3, d2, c5, next);\n });\n };\n}\nfunction maybeChannels(channels) {\n return Object.fromEntries(\n Object.entries(maybeNamed(channels)).map(([name2, channel]) => {\n channel = typeof channel === \"string\" ? { value: channel, label: name2 } : maybeValue(channel);\n if (channel.filter === void 0 && channel.scale == null) channel = { ...channel, filter: null };\n return [name2, channel];\n })\n );\n}\nfunction maybeTip(tip2) {\n return tip2 === true ? \"xy\" : tip2 === false || tip2 == null ? null : typeof tip2 === \"string\" ? keyword(tip2, \"tip\", [\"x\", \"y\", \"xy\"]) : tip2;\n}\nfunction withTip(options, pointer2) {\n return options?.tip === true ? { ...options, tip: pointer2 } : isObject(options?.tip) && options.tip.pointer === void 0 ? { ...options, tip: { ...options.tip, pointer: pointer2 } } : options;\n}\n\n// ../../node_modules/@observablehq/plot/src/dimensions.js\nfunction createDimensions(scales2, marks2, options = {}) {\n let marginTopDefault = 0.5 - offset, marginRightDefault = 0.5 + offset, marginBottomDefault = 0.5 + offset, marginLeftDefault = 0.5 - offset;\n for (const { marginTop: marginTop3, marginRight: marginRight3, marginBottom: marginBottom3, marginLeft: marginLeft3 } of marks2) {\n if (marginTop3 > marginTopDefault) marginTopDefault = marginTop3;\n if (marginRight3 > marginRightDefault) marginRightDefault = marginRight3;\n if (marginBottom3 > marginBottomDefault) marginBottomDefault = marginBottom3;\n if (marginLeft3 > marginLeftDefault) marginLeftDefault = marginLeft3;\n }\n let {\n margin: margin2,\n marginTop: marginTop2 = margin2 !== void 0 ? margin2 : marginTopDefault,\n marginRight: marginRight2 = margin2 !== void 0 ? margin2 : marginRightDefault,\n marginBottom: marginBottom2 = margin2 !== void 0 ? margin2 : marginBottomDefault,\n marginLeft: marginLeft2 = margin2 !== void 0 ? margin2 : marginLeftDefault\n } = options;\n marginTop2 = +marginTop2;\n marginRight2 = +marginRight2;\n marginBottom2 = +marginBottom2;\n marginLeft2 = +marginLeft2;\n let {\n width: width2 = 640,\n height: height2 = autoHeight(scales2, options, {\n width: width2,\n marginTopDefault,\n marginRightDefault,\n marginBottomDefault,\n marginLeftDefault\n }) + Math.max(0, marginTop2 - marginTopDefault + marginBottom2 - marginBottomDefault)\n } = options;\n width2 = +width2;\n height2 = +height2;\n const dimensions = {\n width: width2,\n height: height2,\n marginTop: marginTop2,\n marginRight: marginRight2,\n marginBottom: marginBottom2,\n marginLeft: marginLeft2\n };\n if (scales2.fx || scales2.fy) {\n let {\n margin: facetMargin2,\n marginTop: facetMarginTop2 = facetMargin2 !== void 0 ? facetMargin2 : marginTop2,\n marginRight: facetMarginRight2 = facetMargin2 !== void 0 ? facetMargin2 : marginRight2,\n marginBottom: facetMarginBottom2 = facetMargin2 !== void 0 ? facetMargin2 : marginBottom2,\n marginLeft: facetMarginLeft2 = facetMargin2 !== void 0 ? facetMargin2 : marginLeft2\n } = options.facet ?? {};\n facetMarginTop2 = +facetMarginTop2;\n facetMarginRight2 = +facetMarginRight2;\n facetMarginBottom2 = +facetMarginBottom2;\n facetMarginLeft2 = +facetMarginLeft2;\n dimensions.facet = {\n marginTop: facetMarginTop2,\n marginRight: facetMarginRight2,\n marginBottom: facetMarginBottom2,\n marginLeft: facetMarginLeft2\n };\n }\n return dimensions;\n}\nfunction autoHeight({ x: x3, y: y3, fy, fx }, { projection: projection3, aspectRatio: aspectRatio2 }, { width: width2, marginTopDefault, marginRightDefault, marginBottomDefault, marginLeftDefault }) {\n const nfy = fy ? fy.scale.domain().length || 1 : 1;\n const ar = projectionAspectRatio(projection3);\n if (ar) {\n const nfx = fx ? fx.scale.domain().length : 1;\n const far = (1.1 * nfy - 0.1) / (1.1 * nfx - 0.1) * ar;\n const lar = Math.max(0.1, Math.min(10, far));\n return Math.round((width2 - marginLeftDefault - marginRightDefault) * lar + marginTopDefault + marginBottomDefault);\n }\n const ny = y3 ? isOrdinalScale(y3) ? y3.scale.domain().length || 1 : Math.max(7, 17 / nfy) : 1;\n if (aspectRatio2 != null) {\n aspectRatio2 = +aspectRatio2;\n if (!(isFinite(aspectRatio2) && aspectRatio2 > 0)) throw new Error(`invalid aspectRatio: ${aspectRatio2}`);\n const ratio = aspectRatioLength(\"y\", y3) / (aspectRatioLength(\"x\", x3) * aspectRatio2);\n const fxb = fx ? fx.scale.bandwidth() : 1;\n const fyb = fy ? fy.scale.bandwidth() : 1;\n const w = fxb * (width2 - marginLeftDefault - marginRightDefault) - x3.insetLeft - x3.insetRight;\n return (ratio * w + y3.insetTop + y3.insetBottom) / fyb + marginTopDefault + marginBottomDefault;\n }\n return !!(y3 || fy) * Math.max(1, Math.min(60, ny * nfy)) * 20 + !!fx * 30 + 60;\n}\nfunction aspectRatioLength(k2, scale3) {\n if (!scale3) throw new Error(`aspectRatio requires ${k2} scale`);\n const { type: type2, domain } = scale3;\n let transform3;\n switch (type2) {\n case \"linear\":\n case \"utc\":\n case \"time\":\n transform3 = Number;\n break;\n case \"pow\": {\n const exponent = scale3.scale.exponent();\n transform3 = (x3) => Math.pow(x3, exponent);\n break;\n }\n case \"log\":\n transform3 = Math.log;\n break;\n case \"point\":\n case \"band\":\n return domain.length;\n default:\n throw new Error(`unsupported ${k2} scale for aspectRatio: ${type2}`);\n }\n const [min5, max4] = extent(domain);\n return Math.abs(transform3(max4) - transform3(min5));\n}\n\n// ../../node_modules/@observablehq/plot/src/interactions/pointer.js\nvar states = /* @__PURE__ */ new WeakMap();\nfunction pointerK(kx2, ky2, { x: x3, y: y3, px, py, maxRadius = 40, channels, render, ...options } = {}) {\n maxRadius = +maxRadius;\n if (px != null) x3 ??= null, channels = { ...channels, px: { value: px, scale: \"x\" } };\n if (py != null) y3 ??= null, channels = { ...channels, py: { value: py, scale: \"y\" } };\n return {\n x: x3,\n y: y3,\n channels,\n ...options,\n // Unlike other composed transforms, the render transform must be the\n // outermost render function because it will re-render dynamically in\n // response to pointer events.\n render: composeRender(function(index2, scales2, values2, dimensions, context, next) {\n context = { ...context, pointerSticky: false };\n const svg = context.ownerSVGElement;\n const { data } = context.getMarkState(this);\n let state = states.get(svg);\n if (!state) states.set(svg, state = { sticky: false, roots: [], renders: [] });\n let renderIndex = state.renders.push(render2) - 1;\n const { x: x4, y: y4, fx, fy } = scales2;\n let tx = fx ? fx(index2.fx) - dimensions.marginLeft : 0;\n let ty = fy ? fy(index2.fy) - dimensions.marginTop : 0;\n if (x4?.bandwidth) tx += x4.bandwidth() / 2;\n if (y4?.bandwidth) ty += y4.bandwidth() / 2;\n const faceted = index2.fi != null;\n let facetState;\n if (faceted) {\n let facetStates = state.facetStates;\n if (!facetStates) state.facetStates = facetStates = /* @__PURE__ */ new Map();\n facetState = facetStates.get(this);\n if (!facetState) facetStates.set(this, facetState = /* @__PURE__ */ new Map());\n }\n const [cx, cy] = applyFrameAnchor(this, dimensions);\n const { px: PX, py: PY } = values2;\n const px2 = PX ? (i2) => PX[i2] : anchorX(values2, cx);\n const py2 = PY ? (i2) => PY[i2] : anchorY(values2, cy);\n let i;\n let g;\n let s2;\n let f;\n function update2(ii, ri) {\n if (faceted) {\n if (f) f = cancelAnimationFrame(f);\n if (ii == null) facetState.delete(index2.fi);\n else {\n facetState.set(index2.fi, ri);\n f = requestAnimationFrame(() => {\n f = null;\n for (const [fi, r] of facetState) {\n if (r < ri || r === ri && fi < index2.fi) {\n ii = null;\n break;\n }\n }\n render2(ii);\n });\n return;\n }\n }\n render2(ii);\n }\n function render2(ii) {\n if (i === ii && s2 === state.sticky) return;\n i = ii;\n s2 = context.pointerSticky = state.sticky;\n const I = i == null ? [] : [i];\n if (faceted) I.fx = index2.fx, I.fy = index2.fy, I.fi = index2.fi;\n const r = next(I, scales2, values2, dimensions, context);\n if (g) {\n if (faceted) {\n const p = g.parentNode;\n const ft = g.getAttribute(\"transform\");\n const mt = r.getAttribute(\"transform\");\n ft ? r.setAttribute(\"transform\", ft) : r.removeAttribute(\"transform\");\n mt ? p.setAttribute(\"transform\", mt) : p.removeAttribute(\"transform\");\n r.removeAttribute(\"aria-label\");\n r.removeAttribute(\"aria-description\");\n r.removeAttribute(\"aria-hidden\");\n }\n g.replaceWith(r);\n }\n state.roots[renderIndex] = g = r;\n if (!(i == null && facetState?.size > 1)) {\n const value = i == null ? null : isArray2(data) ? data[i] : data.get(i);\n context.dispatchValue(value);\n }\n return r;\n }\n function pointermove(event) {\n if (state.sticky || event.pointerType === \"mouse\" && event.buttons === 1) return;\n let [xp, yp] = pointer_default(event);\n xp -= tx, yp -= ty;\n const kpx = xp < dimensions.marginLeft || xp > dimensions.width - dimensions.marginRight ? 1 : kx2;\n const kpy = yp < dimensions.marginTop || yp > dimensions.height - dimensions.marginBottom ? 1 : ky2;\n let ii = null;\n let ri = maxRadius * maxRadius;\n for (const j of index2) {\n const dx = kpx * (px2(j) - xp);\n const dy = kpy * (py2(j) - yp);\n const rj = dx * dx + dy * dy;\n if (rj <= ri) ii = j, ri = rj;\n }\n if (ii != null && (kx2 !== 1 || ky2 !== 1)) {\n const dx = px2(ii) - xp;\n const dy = py2(ii) - yp;\n ri = dx * dx + dy * dy;\n }\n update2(ii, ri);\n }\n function pointerdown(event) {\n if (event.pointerType !== \"mouse\") return;\n if (i == null) return;\n if (state.sticky && state.roots.some((r) => r?.contains(event.target))) return;\n if (state.sticky) state.sticky = false, state.renders.forEach((r) => r(null));\n else state.sticky = true, render2(i);\n event.stopImmediatePropagation();\n }\n function pointerleave(event) {\n if (event.pointerType !== \"mouse\") return;\n if (!state.sticky) update2(null);\n }\n svg.addEventListener(\"pointerenter\", pointermove);\n svg.addEventListener(\"pointermove\", pointermove);\n svg.addEventListener(\"pointerdown\", pointerdown);\n svg.addEventListener(\"pointerleave\", pointerleave);\n return render2(null);\n }, render)\n };\n}\nfunction pointer(options) {\n return pointerK(1, 1, options);\n}\nfunction pointerX(options) {\n return pointerK(1, 0.01, options);\n}\nfunction pointerY(options) {\n return pointerK(0.01, 1, options);\n}\nfunction anchorX({ x1: X13, x2: X23, x: X3 = X13 }, cx) {\n return X13 && X23 ? (i) => (X13[i] + X23[i]) / 2 : X3 ? (i) => X3[i] : () => cx;\n}\nfunction anchorY({ y1: Y13, y2: Y23, y: Y3 = Y13 }, cy) {\n return Y13 && Y23 ? (i) => (Y13[i] + Y23[i]) / 2 : Y3 ? (i) => Y3[i] : () => cy;\n}\n\n// ../../node_modules/@observablehq/plot/src/axes.js\nfunction inferFontVariant(scale3) {\n return isOrdinalScale(scale3) && scale3.interval === void 0 ? void 0 : \"tabular-nums\";\n}\n\n// ../../node_modules/@observablehq/plot/src/legends/ramp.js\nfunction legendRamp(color3, options) {\n let {\n label: label2 = color3.label,\n tickSize = 6,\n width: width2 = 240,\n height: height2 = 44 + tickSize,\n marginTop: marginTop2 = 18,\n marginRight: marginRight2 = 0,\n marginBottom: marginBottom2 = 16 + tickSize,\n marginLeft: marginLeft2 = 0,\n style: style2,\n ticks: ticks2 = (width2 - marginLeft2 - marginRight2) / 64,\n tickFormat: tickFormat2,\n fontVariant = inferFontVariant(color3),\n round: round2 = true,\n opacity: opacity2,\n className\n } = options;\n const context = createContext(options);\n className = maybeClassName(className);\n opacity2 = maybeNumberChannel(opacity2)[1];\n if (tickFormat2 === null) tickFormat2 = () => null;\n const svg = create4(\"svg\", context).attr(\"class\", `${className}-ramp`).attr(\"font-family\", \"system-ui, sans-serif\").attr(\"font-size\", 10).attr(\"width\", width2).attr(\"height\", height2).attr(\"viewBox\", `0 0 ${width2} ${height2}`).call(\n (svg2) => (\n // Warning: if you edit this, change defaultClassName.\n svg2.append(\"style\").text(\n `:where(.${className}-ramp) {\n display: block;\n height: auto;\n height: intrinsic;\n max-width: 100%;\n overflow: visible;\n}\n:where(.${className}-ramp text) {\n white-space: pre;\n}`\n )\n )\n ).call(applyInlineStyles, style2);\n let tickAdjust = (g) => g.selectAll(\".tick line\").attr(\"y1\", marginTop2 + marginBottom2 - height2);\n let x3;\n const applyRange = round2 ? (x4, range4) => x4.rangeRound(range4) : (x4, range4) => x4.range(range4);\n const { type: type2, domain, range: range3, interpolate, scale: scale3, pivot } = color3;\n if (interpolate) {\n const interpolator = range3 === void 0 ? interpolate : piecewise(interpolate.length === 1 ? interpolatePiecewise(interpolate) : interpolate, range3);\n x3 = applyRange(\n scale3.copy(),\n quantize_default(\n number_default(marginLeft2, width2 - marginRight2),\n Math.min(domain.length + (pivot !== void 0), range3 === void 0 ? Infinity : range3.length)\n )\n );\n const n = 256;\n const canvas = context.document.createElement(\"canvas\");\n canvas.width = n;\n canvas.height = 1;\n const context2 = canvas.getContext(\"2d\");\n for (let i = 0, j = n - 1; i < n; ++i) {\n context2.fillStyle = interpolator(i / j);\n context2.fillRect(i, 0, 1, 1);\n }\n svg.append(\"image\").attr(\"opacity\", opacity2).attr(\"x\", marginLeft2).attr(\"y\", marginTop2).attr(\"width\", width2 - marginLeft2 - marginRight2).attr(\"height\", height2 - marginTop2 - marginBottom2).attr(\"preserveAspectRatio\", \"none\").attr(\"xlink:href\", canvas.toDataURL());\n } else if (type2 === \"threshold\") {\n const thresholds = domain;\n const thresholdFormat = tickFormat2 === void 0 ? (d) => d : typeof tickFormat2 === \"string\" ? format(tickFormat2) : tickFormat2;\n x3 = applyRange(linear2().domain([-1, range3.length - 1]), [marginLeft2, width2 - marginRight2]);\n svg.append(\"g\").attr(\"fill-opacity\", opacity2).selectAll().data(range3).enter().append(\"rect\").attr(\"x\", (d, i) => x3(i - 1)).attr(\"y\", marginTop2).attr(\"width\", (d, i) => x3(i) - x3(i - 1)).attr(\"height\", height2 - marginTop2 - marginBottom2).attr(\"fill\", (d) => d);\n ticks2 = map3(thresholds, (_, i) => i);\n tickFormat2 = (i) => thresholdFormat(thresholds[i], i);\n } else {\n x3 = applyRange(band().domain(domain), [marginLeft2, width2 - marginRight2]);\n svg.append(\"g\").attr(\"fill-opacity\", opacity2).selectAll().data(domain).enter().append(\"rect\").attr(\"x\", x3).attr(\"y\", marginTop2).attr(\"width\", Math.max(0, x3.bandwidth() - 1)).attr(\"height\", height2 - marginTop2 - marginBottom2).attr(\"fill\", scale3);\n tickAdjust = () => {\n };\n }\n svg.append(\"g\").attr(\"transform\", `translate(0,${height2 - marginBottom2})`).call(\n axisBottom(x3).ticks(Array.isArray(ticks2) ? null : ticks2, typeof tickFormat2 === \"string\" ? tickFormat2 : void 0).tickFormat(typeof tickFormat2 === \"function\" ? tickFormat2 : void 0).tickSize(tickSize).tickValues(Array.isArray(ticks2) ? ticks2 : null)\n ).attr(\"font-size\", null).attr(\"font-family\", null).attr(\"font-variant\", impliedString(fontVariant, \"normal\")).call(tickAdjust).call((g) => g.select(\".domain\").remove());\n if (label2 !== void 0) {\n svg.append(\"text\").attr(\"x\", marginLeft2).attr(\"y\", marginTop2 - 6).attr(\"fill\", \"currentColor\").attr(\"font-weight\", \"bold\").text(label2);\n }\n return svg.node();\n}\n\n// ../../node_modules/@observablehq/plot/src/math.js\nvar radians3 = Math.PI / 180;\n\n// ../../node_modules/@observablehq/plot/src/marker.js\nfunction markers(mark2, { marker, markerStart = marker, markerMid = marker, markerEnd = marker } = {}) {\n mark2.markerStart = maybeMarker(markerStart);\n mark2.markerMid = maybeMarker(markerMid);\n mark2.markerEnd = maybeMarker(markerEnd);\n}\nfunction maybeMarker(marker) {\n if (marker == null || marker === false) return null;\n if (marker === true) return markerCircleFill;\n if (typeof marker === \"function\") return marker;\n switch (`${marker}`.toLowerCase()) {\n case \"none\":\n return null;\n case \"arrow\":\n return markerArrow(\"auto\");\n case \"arrow-reverse\":\n return markerArrow(\"auto-start-reverse\");\n case \"dot\":\n return markerDot;\n case \"circle\":\n case \"circle-fill\":\n return markerCircleFill;\n case \"circle-stroke\":\n return markerCircleStroke;\n case \"tick\":\n return markerTick(\"auto\");\n case \"tick-x\":\n return markerTick(90);\n case \"tick-y\":\n return markerTick(0);\n }\n throw new Error(`invalid marker: ${marker}`);\n}\nfunction markerArrow(orient) {\n return (color3, context) => create4(\"svg:marker\", context).attr(\"viewBox\", \"-5 -5 10 10\").attr(\"markerWidth\", 6.67).attr(\"markerHeight\", 6.67).attr(\"orient\", orient).attr(\"fill\", \"none\").attr(\"stroke\", color3).attr(\"stroke-width\", 1.5).attr(\"stroke-linecap\", \"round\").attr(\"stroke-linejoin\", \"round\").call((marker) => marker.append(\"path\").attr(\"d\", \"M-1.5,-3l3,3l-3,3\")).node();\n}\nfunction markerDot(color3, context) {\n return create4(\"svg:marker\", context).attr(\"viewBox\", \"-5 -5 10 10\").attr(\"markerWidth\", 6.67).attr(\"markerHeight\", 6.67).attr(\"fill\", color3).attr(\"stroke\", \"none\").call((marker) => marker.append(\"circle\").attr(\"r\", 2.5)).node();\n}\nfunction markerCircleFill(color3, context) {\n return create4(\"svg:marker\", context).attr(\"viewBox\", \"-5 -5 10 10\").attr(\"markerWidth\", 6.67).attr(\"markerHeight\", 6.67).attr(\"fill\", color3).attr(\"stroke\", \"var(--plot-background)\").attr(\"stroke-width\", 1.5).call((marker) => marker.append(\"circle\").attr(\"r\", 3)).node();\n}\nfunction markerCircleStroke(color3, context) {\n return create4(\"svg:marker\", context).attr(\"viewBox\", \"-5 -5 10 10\").attr(\"markerWidth\", 6.67).attr(\"markerHeight\", 6.67).attr(\"fill\", \"var(--plot-background)\").attr(\"stroke\", color3).attr(\"stroke-width\", 1.5).call((marker) => marker.append(\"circle\").attr(\"r\", 3)).node();\n}\nfunction markerTick(orient) {\n return (color3, context) => create4(\"svg:marker\", context).attr(\"viewBox\", \"-3 -3 6 6\").attr(\"markerWidth\", 6).attr(\"markerHeight\", 6).attr(\"orient\", orient).attr(\"stroke\", color3).call((marker) => marker.append(\"path\").attr(\"d\", \"M0,-3v6\")).node();\n}\nvar nextMarkerId = 0;\nfunction applyMarkers(path2, mark2, { stroke: S }, context) {\n return applyMarkersColor(path2, mark2, S && ((i) => S[i]), null, context);\n}\nfunction applyGroupedMarkers(path2, mark2, { stroke: S, z: Z }, context) {\n return applyMarkersColor(path2, mark2, S && (([i]) => S[i]), Z, context);\n}\nvar START = 1;\nvar END = 2;\nfunction getGroupedOrientation(path2, Z) {\n const O = new Uint8Array(Z.length);\n const D3 = path2.data().filter((I) => I.length > 1);\n const n = D3.length;\n for (let i = 0, z = unset; i < n; ++i) {\n const I = D3[i];\n if (I.length > 1) {\n const i2 = I[0];\n if (z !== (z = keyof2(Z[i2]))) O[i2] |= START;\n }\n }\n for (let i = n - 1, z = unset; i >= 0; --i) {\n const I = D3[i];\n if (I.length > 1) {\n const i2 = I[0];\n if (z !== (z = keyof2(Z[i2]))) O[i2] |= END;\n }\n }\n return ([i]) => O[i];\n}\nfunction applyMarkersColor(path2, { markerStart, markerMid, markerEnd, stroke }, strokeof = () => stroke, Z, context) {\n if (!markerStart && !markerMid && !markerEnd) return;\n const iriByMarkerColor = /* @__PURE__ */ new Map();\n const orient = Z && getGroupedOrientation(path2, Z);\n function applyMarker(name2, marker, filter3) {\n return function(i) {\n if (filter3 && !filter3(i)) return;\n const color3 = strokeof(i);\n let iriByColor = iriByMarkerColor.get(marker);\n if (!iriByColor) iriByMarkerColor.set(marker, iriByColor = /* @__PURE__ */ new Map());\n let iri = iriByColor.get(color3);\n if (!iri) {\n const node = this.parentNode.insertBefore(marker(color3, context), this);\n const id2 = `plot-marker-${++nextMarkerId}`;\n node.setAttribute(\"id\", id2);\n iriByColor.set(color3, iri = `url(#${id2})`);\n }\n this.setAttribute(name2, iri);\n };\n }\n if (markerStart) path2.each(applyMarker(\"marker-start\", markerStart, orient && ((i) => orient(i) & START)));\n if (markerMid && orient) path2.each(applyMarker(\"marker-start\", markerMid, (i) => !(orient(i) & START)));\n if (markerMid) path2.each(applyMarker(\"marker-mid\", markerMid));\n if (markerEnd) path2.each(applyMarker(\"marker-end\", markerEnd, orient && ((i) => orient(i) & END)));\n}\n\n// ../../node_modules/@observablehq/plot/src/transforms/inset.js\nfunction maybeInsetX({ inset: inset2, insetLeft, insetRight, ...options } = {}) {\n [insetLeft, insetRight] = maybeInset(inset2, insetLeft, insetRight);\n return { inset: inset2, insetLeft, insetRight, ...options };\n}\nfunction maybeInsetY({ inset: inset2, insetTop, insetBottom, ...options } = {}) {\n [insetTop, insetBottom] = maybeInset(inset2, insetTop, insetBottom);\n return { inset: inset2, insetTop, insetBottom, ...options };\n}\nfunction maybeInset(inset2, inset1, inset22) {\n return inset2 === void 0 && inset1 === void 0 && inset22 === void 0 ? offset ? [1, 0] : [0.5, 0.5] : [inset1, inset22];\n}\n\n// ../../node_modules/@observablehq/plot/src/transforms/interval.js\nfunction maybeIntervalValue(value, { interval: interval3 }) {\n value = { ...maybeValue(value) };\n value.interval = maybeInterval(value.interval === void 0 ? interval3 : value.interval);\n return value;\n}\nfunction maybeIntervalK(k2, maybeInsetK, options, trivial) {\n const { [k2]: v2, [`${k2}1`]: v1, [`${k2}2`]: v22 } = options;\n const { value, interval: interval3 } = maybeIntervalValue(v2, options);\n if (value == null || interval3 == null && !trivial) return options;\n const label2 = labelof(v2);\n if (interval3 == null) {\n let V;\n const kv = { transform: (data) => V || (V = valueof(data, value)), label: label2 };\n return {\n ...options,\n [k2]: void 0,\n [`${k2}1`]: v1 === void 0 ? kv : v1,\n [`${k2}2`]: v22 === void 0 && !(v1 === v22 && trivial) ? kv : v22\n };\n }\n let D1, V1;\n function transform3(data) {\n if (V1 !== void 0 && data === D1) return V1;\n return V1 = map3(valueof(D1 = data, value), (v3) => interval3.floor(v3));\n }\n return maybeInsetK({\n ...options,\n [k2]: void 0,\n [`${k2}1`]: v1 === void 0 ? { transform: transform3, label: label2 } : v1,\n [`${k2}2`]: v22 === void 0 ? { transform: (data) => transform3(data).map((v3) => interval3.offset(v3)), label: label2 } : v22\n });\n}\nfunction maybeIntervalMidK(k2, maybeInsetK, options) {\n const { [k2]: v2 } = options;\n const { value, interval: interval3 } = maybeIntervalValue(v2, options);\n if (value == null || interval3 == null) return options;\n return maybeInsetK({\n ...options,\n [k2]: {\n label: labelof(v2),\n transform: (data) => {\n const V1 = map3(valueof(data, value), (v3) => interval3.floor(v3));\n const V2 = V1.map((v3) => interval3.offset(v3));\n return V1.map(\n isTemporal(V1) ? (v1, v22) => v1 == null || isNaN(v1 = +v1) || (v22 = V2[v22], v22 == null) || isNaN(v22 = +v22) ? void 0 : new Date((v1 + v22) / 2) : (v1, v22) => v1 == null || (v22 = V2[v22], v22 == null) ? NaN : (+v1 + +v22) / 2\n );\n }\n }\n });\n}\nfunction maybeTrivialIntervalX(options = {}) {\n return maybeIntervalK(\"x\", maybeInsetX, options, true);\n}\nfunction maybeTrivialIntervalY(options = {}) {\n return maybeIntervalK(\"y\", maybeInsetY, options, true);\n}\nfunction maybeIntervalX(options = {}) {\n return maybeIntervalK(\"x\", maybeInsetX, options);\n}\nfunction maybeIntervalY(options = {}) {\n return maybeIntervalK(\"y\", maybeInsetY, options);\n}\nfunction maybeIntervalMidX(options = {}) {\n return maybeIntervalMidK(\"x\", maybeInsetX, options);\n}\nfunction maybeIntervalMidY(options = {}) {\n return maybeIntervalMidK(\"y\", maybeInsetY, options);\n}\n\n// ../../node_modules/@observablehq/plot/src/marks/rule.js\nvar defaults = {\n ariaLabel: \"rule\",\n fill: null,\n stroke: \"currentColor\"\n};\nvar RuleX = class extends Mark {\n constructor(data, options = {}) {\n const { x: x3, y1: y12, y2: y22, inset: inset2 = 0, insetTop = inset2, insetBottom = inset2 } = options;\n super(\n data,\n {\n x: { value: x3, scale: \"x\", optional: true },\n y1: { value: y12, scale: \"y\", optional: true },\n y2: { value: y22, scale: \"y\", optional: true }\n },\n withTip(options, \"x\"),\n defaults\n );\n this.insetTop = number5(insetTop);\n this.insetBottom = number5(insetBottom);\n markers(this, options);\n }\n render(index2, scales2, channels, dimensions, context) {\n const { x: x3, y: y3 } = scales2;\n const { x: X3, y1: Y13, y2: Y23 } = channels;\n const { width: width2, height: height2, marginTop: marginTop2, marginRight: marginRight2, marginLeft: marginLeft2, marginBottom: marginBottom2 } = dimensions;\n const { insetTop, insetBottom } = this;\n return create4(\"svg:g\", context).call(applyIndirectStyles, this, dimensions, context).call(applyTransform, this, { x: X3 && x3 }, offset, 0).call(\n (g) => g.selectAll().data(index2).enter().append(\"line\").call(applyDirectStyles, this).attr(\"x1\", X3 ? (i) => X3[i] : (marginLeft2 + width2 - marginRight2) / 2).attr(\"x2\", X3 ? (i) => X3[i] : (marginLeft2 + width2 - marginRight2) / 2).attr(\"y1\", Y13 && !isCollapsed(y3) ? (i) => Y13[i] + insetTop : marginTop2 + insetTop).attr(\n \"y2\",\n Y23 && !isCollapsed(y3) ? y3.bandwidth ? (i) => Y23[i] + y3.bandwidth() - insetBottom : (i) => Y23[i] - insetBottom : height2 - marginBottom2 - insetBottom\n ).call(applyChannelStyles, this, channels).call(applyMarkers, this, channels, context)\n ).node();\n }\n};\nvar RuleY = class extends Mark {\n constructor(data, options = {}) {\n const { x1: x12, x2: x22, y: y3, inset: inset2 = 0, insetRight = inset2, insetLeft = inset2 } = options;\n super(\n data,\n {\n y: { value: y3, scale: \"y\", optional: true },\n x1: { value: x12, scale: \"x\", optional: true },\n x2: { value: x22, scale: \"x\", optional: true }\n },\n withTip(options, \"y\"),\n defaults\n );\n this.insetRight = number5(insetRight);\n this.insetLeft = number5(insetLeft);\n markers(this, options);\n }\n render(index2, scales2, channels, dimensions, context) {\n const { x: x3, y: y3 } = scales2;\n const { y: Y3, x1: X13, x2: X23 } = channels;\n const { width: width2, height: height2, marginTop: marginTop2, marginRight: marginRight2, marginLeft: marginLeft2, marginBottom: marginBottom2 } = dimensions;\n const { insetLeft, insetRight } = this;\n return create4(\"svg:g\", context).call(applyIndirectStyles, this, dimensions, context).call(applyTransform, this, { y: Y3 && y3 }, 0, offset).call(\n (g) => g.selectAll().data(index2).enter().append(\"line\").call(applyDirectStyles, this).attr(\"x1\", X13 && !isCollapsed(x3) ? (i) => X13[i] + insetLeft : marginLeft2 + insetLeft).attr(\n \"x2\",\n X23 && !isCollapsed(x3) ? x3.bandwidth ? (i) => X23[i] + x3.bandwidth() - insetRight : (i) => X23[i] - insetRight : width2 - marginRight2 - insetRight\n ).attr(\"y1\", Y3 ? (i) => Y3[i] : (marginTop2 + height2 - marginBottom2) / 2).attr(\"y2\", Y3 ? (i) => Y3[i] : (marginTop2 + height2 - marginBottom2) / 2).call(applyChannelStyles, this, channels).call(applyMarkers, this, channels, context)\n ).node();\n }\n};\nfunction ruleX(data, options) {\n let { x: x3 = identity7, y: y3, y1: y12, y2: y22, ...rest } = maybeIntervalY(options);\n [y12, y22] = maybeOptionalZero(y3, y12, y22);\n return new RuleX(data, { ...rest, x: x3, y1: y12, y2: y22 });\n}\nfunction ruleY(data, options) {\n let { y: y3 = identity7, x: x3, x1: x12, x2: x22, ...rest } = maybeIntervalX(options);\n [x12, x22] = maybeOptionalZero(x3, x12, x22);\n return new RuleY(data, { ...rest, y: y3, x1: x12, x2: x22 });\n}\nfunction maybeOptionalZero(x3, x12, x22) {\n if (x3 == null) {\n if (x12 === void 0) {\n if (x22 !== void 0) return [0, x22];\n } else {\n if (x22 === void 0) return [0, x12];\n }\n } else if (x12 === void 0) {\n return x22 === void 0 ? [0, x3] : [x3, x22];\n } else if (x22 === void 0) {\n return [x3, x12];\n }\n return [x12, x22];\n}\n\n// ../../node_modules/@observablehq/plot/src/template.js\nfunction template(strings, ...parts) {\n let n = parts.length;\n for (let j = 0, copy4 = true; j < n; ++j) {\n if (typeof parts[j] !== \"function\") {\n if (copy4) {\n strings = strings.slice();\n copy4 = false;\n }\n strings.splice(j, 2, strings[j] + parts[j] + strings[j + 1]);\n parts.splice(j, 1);\n --j, --n;\n }\n }\n return (i) => {\n let s2 = strings[0];\n for (let j = 0; j < n; ++j) {\n s2 += parts[j](i) + strings[j + 1];\n }\n return s2;\n };\n}\n\n// ../../node_modules/@observablehq/plot/src/marks/text.js\nvar defaults2 = {\n ariaLabel: \"text\",\n strokeLinejoin: \"round\",\n strokeWidth: 3,\n paintOrder: \"stroke\"\n};\nvar softHyphen = \"\\xAD\";\nvar Text = class extends Mark {\n constructor(data, options = {}) {\n const {\n x: x3,\n y: y3,\n text: text3 = isIterable(data) && isTextual(data) ? identity7 : indexOf,\n frameAnchor,\n textAnchor = /right$/i.test(frameAnchor) ? \"end\" : /left$/i.test(frameAnchor) ? \"start\" : \"middle\",\n lineAnchor = /^top/i.test(frameAnchor) ? \"top\" : /^bottom/i.test(frameAnchor) ? \"bottom\" : \"middle\",\n lineHeight = 1,\n lineWidth = Infinity,\n textOverflow,\n monospace,\n fontFamily = monospace ? \"ui-monospace, monospace\" : void 0,\n fontSize,\n fontStyle,\n fontVariant,\n fontWeight,\n rotate\n } = options;\n const [vrotate, crotate] = maybeNumberChannel(rotate, 0);\n const [vfontSize, cfontSize] = maybeFontSizeChannel(fontSize);\n super(\n data,\n {\n x: { value: x3, scale: \"x\", optional: true },\n y: { value: y3, scale: \"y\", optional: true },\n fontSize: { value: vfontSize, optional: true },\n rotate: { value: numberChannel(vrotate), optional: true },\n text: { value: text3, filter: nonempty, optional: true }\n },\n options,\n defaults2\n );\n this.rotate = crotate;\n this.textAnchor = impliedString(textAnchor, \"middle\");\n this.lineAnchor = keyword(lineAnchor, \"lineAnchor\", [\"top\", \"middle\", \"bottom\"]);\n this.lineHeight = +lineHeight;\n this.lineWidth = +lineWidth;\n this.textOverflow = maybeTextOverflow(textOverflow);\n this.monospace = !!monospace;\n this.fontFamily = string(fontFamily);\n this.fontSize = cfontSize;\n this.fontStyle = string(fontStyle);\n this.fontVariant = string(fontVariant);\n this.fontWeight = string(fontWeight);\n this.frameAnchor = maybeFrameAnchor(frameAnchor);\n if (!(this.lineWidth >= 0)) throw new Error(`invalid lineWidth: ${lineWidth}`);\n this.splitLines = splitter2(this);\n this.clipLine = clipper(this);\n }\n render(index2, scales2, channels, dimensions, context) {\n const { x: x3, y: y3 } = scales2;\n const { x: X3, y: Y3, rotate: R, text: T, title: TL, fontSize: FS } = channels;\n const { rotate } = this;\n const [cx, cy] = applyFrameAnchor(this, dimensions);\n return create4(\"svg:g\", context).call(applyIndirectStyles, this, dimensions, context).call(applyIndirectTextStyles, this, T, dimensions).call(applyTransform, this, { x: X3 && x3, y: Y3 && y3 }).call(\n (g) => g.selectAll().data(index2).enter().append(\"text\").call(applyDirectStyles, this).call(applyMultilineText, this, T, TL).attr(\n \"transform\",\n template`translate(${X3 ? (i) => X3[i] : cx},${Y3 ? (i) => Y3[i] : cy})${R ? (i) => ` rotate(${R[i]})` : rotate ? ` rotate(${rotate})` : ``}`\n ).call(applyAttr, \"font-size\", FS && ((i) => FS[i])).call(applyChannelStyles, this, channels)\n ).node();\n }\n};\nfunction maybeTextOverflow(textOverflow) {\n return textOverflow == null ? null : keyword(textOverflow, \"textOverflow\", [\n \"clip\",\n // shorthand for clip-end\n \"ellipsis\",\n // … ellipsis-end\n \"clip-start\",\n \"clip-end\",\n \"ellipsis-start\",\n \"ellipsis-middle\",\n \"ellipsis-end\"\n ]).replace(/^(clip|ellipsis)$/, \"$1-end\");\n}\nfunction applyMultilineText(selection2, mark2, T, TL) {\n if (!T) return;\n const { lineAnchor, lineHeight, textOverflow, splitLines, clipLine } = mark2;\n selection2.each(function(i) {\n const lines = splitLines(formatDefault(T[i]) ?? \"\").map(clipLine);\n const n = lines.length;\n const y3 = lineAnchor === \"top\" ? 0.71 : lineAnchor === \"bottom\" ? 1 - n : (164 - n * 100) / 200;\n if (n > 1) {\n let m = 0;\n for (let i2 = 0; i2 < n; ++i2) {\n ++m;\n if (!lines[i2]) continue;\n const tspan = this.ownerDocument.createElementNS(namespaces_default.svg, \"tspan\");\n tspan.setAttribute(\"x\", 0);\n if (i2 === m - 1) tspan.setAttribute(\"y\", `${(y3 + i2) * lineHeight}em`);\n else tspan.setAttribute(\"dy\", `${m * lineHeight}em`);\n tspan.textContent = lines[i2];\n this.appendChild(tspan);\n m = 0;\n }\n } else {\n if (y3) this.setAttribute(\"y\", `${y3 * lineHeight}em`);\n this.textContent = lines[0];\n }\n if (textOverflow && !TL && lines[0] !== T[i]) {\n const title = this.ownerDocument.createElementNS(namespaces_default.svg, \"title\");\n title.textContent = T[i];\n this.appendChild(title);\n }\n });\n}\nfunction text(data, { x: x3, y: y3, ...options } = {}) {\n if (options.frameAnchor === void 0) [x3, y3] = maybeTuple(x3, y3);\n return new Text(data, { ...options, x: x3, y: y3 });\n}\nfunction textX(data, { x: x3 = identity7, ...options } = {}) {\n return new Text(data, maybeIntervalMidY({ ...options, x: x3 }));\n}\nfunction textY(data, { y: y3 = identity7, ...options } = {}) {\n return new Text(data, maybeIntervalMidX({ ...options, y: y3 }));\n}\nfunction applyIndirectTextStyles(selection2, mark2, T) {\n applyAttr(selection2, \"text-anchor\", mark2.textAnchor);\n applyAttr(selection2, \"font-family\", mark2.fontFamily);\n applyAttr(selection2, \"font-size\", mark2.fontSize);\n applyAttr(selection2, \"font-style\", mark2.fontStyle);\n applyAttr(selection2, \"font-variant\", mark2.fontVariant === void 0 ? inferFontVariant2(T) : mark2.fontVariant);\n applyAttr(selection2, \"font-weight\", mark2.fontWeight);\n}\nfunction inferFontVariant2(T) {\n return T && (isNumeric(T) || isTemporal(T)) ? \"tabular-nums\" : void 0;\n}\nvar fontSizes = /* @__PURE__ */ new Set([\n // global keywords\n \"inherit\",\n \"initial\",\n \"revert\",\n \"unset\",\n // absolute keywords\n \"xx-small\",\n \"x-small\",\n \"small\",\n \"medium\",\n \"large\",\n \"x-large\",\n \"xx-large\",\n \"xxx-large\",\n // relative keywords\n \"larger\",\n \"smaller\"\n]);\nfunction maybeFontSizeChannel(fontSize) {\n if (fontSize == null || typeof fontSize === \"number\") return [void 0, fontSize];\n if (typeof fontSize !== \"string\") return [fontSize, void 0];\n fontSize = fontSize.trim().toLowerCase();\n return fontSizes.has(fontSize) || /^[+-]?\\d*\\.?\\d+(e[+-]?\\d+)?(\\w*|%)$/.test(fontSize) ? [void 0, fontSize] : [fontSize, void 0];\n}\nfunction lineWrap(input3, maxWidth, widthof2) {\n const lines = [];\n let lineStart, lineEnd = 0;\n for (const [wordStart, wordEnd, required2] of lineBreaks(input3)) {\n if (lineStart === void 0) lineStart = wordStart;\n if (lineEnd > lineStart && widthof2(input3, lineStart, wordEnd) > maxWidth) {\n lines.push(input3.slice(lineStart, lineEnd) + (input3[lineEnd - 1] === softHyphen ? \"-\" : \"\"));\n lineStart = wordStart;\n }\n if (required2) {\n lines.push(input3.slice(lineStart, wordEnd));\n lineStart = void 0;\n continue;\n }\n lineEnd = wordEnd;\n }\n return lines;\n}\nfunction* lineBreaks(input3) {\n let i = 0, j = 0;\n const n = input3.length;\n while (j < n) {\n let k2 = 1;\n switch (input3[j]) {\n case softHyphen:\n case \"-\":\n ++j;\n yield [i, j, false];\n i = j;\n break;\n case \" \":\n yield [i, j, false];\n while (input3[++j] === \" \") ;\n i = j;\n break;\n case \"\\r\":\n if (input3[j + 1] === \"\\n\") ++k2;\n // falls through\n case \"\\n\":\n yield [i, j, true];\n j += k2;\n i = j;\n break;\n default:\n ++j;\n break;\n }\n }\n yield [i, j, true];\n}\nvar defaultWidthMap = {\n a: 56,\n b: 63,\n c: 57,\n d: 63,\n e: 58,\n f: 37,\n g: 62,\n h: 60,\n i: 26,\n j: 26,\n k: 55,\n l: 26,\n m: 88,\n n: 60,\n o: 60,\n p: 62,\n q: 62,\n r: 39,\n s: 54,\n t: 38,\n u: 60,\n v: 55,\n w: 79,\n x: 54,\n y: 55,\n z: 55,\n A: 69,\n B: 67,\n C: 73,\n D: 74,\n E: 61,\n F: 58,\n G: 76,\n H: 75,\n I: 28,\n J: 55,\n K: 67,\n L: 58,\n M: 89,\n N: 75,\n O: 78,\n P: 65,\n Q: 78,\n R: 67,\n S: 65,\n T: 65,\n U: 75,\n V: 69,\n W: 98,\n X: 69,\n Y: 67,\n Z: 67,\n 0: 64,\n 1: 48,\n 2: 62,\n 3: 64,\n 4: 66,\n 5: 63,\n 6: 65,\n 7: 58,\n 8: 65,\n 9: 65,\n \" \": 29,\n \"!\": 32,\n '\"': 49,\n \"'\": 31,\n \"(\": 39,\n \")\": 39,\n \",\": 31,\n \"-\": 48,\n \".\": 31,\n \"/\": 32,\n \":\": 31,\n \";\": 31,\n \"?\": 52,\n \"\\u2018\": 31,\n \"\\u2019\": 31,\n \"\\u201C\": 47,\n \"\\u201D\": 47,\n \"\\u2026\": 82\n};\nfunction defaultWidth(text3, start2 = 0, end = text3.length) {\n let sum4 = 0;\n for (let i = start2; i < end; i = readCharacter(text3, i)) {\n sum4 += defaultWidthMap[text3[i]] ?? (isPictographic(text3, i) ? 120 : defaultWidthMap.e);\n }\n return sum4;\n}\nfunction monospaceWidth(text3, start2 = 0, end = text3.length) {\n let sum4 = 0;\n for (let i = start2; i < end; i = readCharacter(text3, i)) {\n sum4 += isPictographic(text3, i) ? 126 : 63;\n }\n return sum4;\n}\nfunction splitter2({ monospace, lineWidth, textOverflow }) {\n if (textOverflow != null || lineWidth == Infinity) return (text3) => text3.split(/\\r\\n?|\\n/g);\n const widthof2 = monospace ? monospaceWidth : defaultWidth;\n const maxWidth = lineWidth * 100;\n return (text3) => lineWrap(text3, maxWidth, widthof2);\n}\nfunction clipper({ monospace, lineWidth, textOverflow }) {\n if (textOverflow == null || lineWidth == Infinity) return (text3) => text3;\n const widthof2 = monospace ? monospaceWidth : defaultWidth;\n const maxWidth = lineWidth * 100;\n switch (textOverflow) {\n case \"clip-start\":\n return (text3) => clipStart(text3, maxWidth, widthof2, \"\");\n case \"clip-end\":\n return (text3) => clipEnd(text3, maxWidth, widthof2, \"\");\n case \"ellipsis-start\":\n return (text3) => clipStart(text3, maxWidth, widthof2, ellipsis);\n case \"ellipsis-middle\":\n return (text3) => clipMiddle(text3, maxWidth, widthof2, ellipsis);\n case \"ellipsis-end\":\n return (text3) => clipEnd(text3, maxWidth, widthof2, ellipsis);\n }\n}\nvar ellipsis = \"\\u2026\";\nfunction cut(text3, width2, widthof2, inset2) {\n const I = [];\n let w = 0;\n for (let i = 0, j = 0, n = text3.length; i < n; i = j) {\n j = readCharacter(text3, i);\n const l = widthof2(text3, i, j);\n if (w + l > width2) {\n w += inset2;\n while (w > width2 && i > 0) j = i, i = I.pop(), w -= widthof2(text3, i, j);\n return [i, width2 - w];\n }\n w += l;\n I.push(i);\n }\n return [-1, 0];\n}\nfunction clipEnd(text3, width2, widthof2, ellipsis2) {\n text3 = text3.trim();\n const e = widthof2(ellipsis2);\n const [i] = cut(text3, width2, widthof2, e);\n return i < 0 ? text3 : text3.slice(0, i).trimEnd() + ellipsis2;\n}\nfunction clipMiddle(text3, width2, widthof2, ellipsis2) {\n text3 = text3.trim();\n const w = widthof2(text3);\n if (w <= width2) return text3;\n const e = widthof2(ellipsis2) / 2;\n const [i, ei] = cut(text3, width2 / 2, widthof2, e);\n const [j] = cut(text3, w - width2 / 2 - ei + e, widthof2, -e);\n return j < 0 ? ellipsis2 : text3.slice(0, i).trimEnd() + ellipsis2 + text3.slice(readCharacter(text3, j)).trimStart();\n}\nfunction clipStart(text3, width2, widthof2, ellipsis2) {\n text3 = text3.trim();\n const w = widthof2(text3);\n if (w <= width2) return text3;\n const e = widthof2(ellipsis2);\n const [j] = cut(text3, w - width2 + e, widthof2, -e);\n return j < 0 ? ellipsis2 : ellipsis2 + text3.slice(readCharacter(text3, j)).trimStart();\n}\nvar reCombiner = /[\\p{Combining_Mark}\\p{Emoji_Modifier}]+/uy;\nvar rePictographic = /\\p{Extended_Pictographic}/uy;\nfunction readCharacter(text3, i) {\n i += isSurrogatePair(text3, i) ? 2 : 1;\n if (isCombiner(text3, i)) i = reCombiner.lastIndex;\n if (isZeroWidthJoiner(text3, i)) return readCharacter(text3, i + 1);\n return i;\n}\nfunction isAscii(text3, i) {\n return text3.charCodeAt(i) < 128;\n}\nfunction isSurrogatePair(text3, i) {\n const hi = text3.charCodeAt(i);\n if (hi >= 55296 && hi < 56320) {\n const lo = text3.charCodeAt(i + 1);\n return lo >= 56320 && lo < 57344;\n }\n return false;\n}\nfunction isZeroWidthJoiner(text3, i) {\n return text3.charCodeAt(i) === 8205;\n}\nfunction isCombiner(text3, i) {\n return isAscii(text3, i) ? false : (reCombiner.lastIndex = i, reCombiner.test(text3));\n}\nfunction isPictographic(text3, i) {\n return isAscii(text3, i) ? false : (rePictographic.lastIndex = i, rePictographic.test(text3));\n}\n\n// ../../node_modules/@observablehq/plot/src/marks/vector.js\nvar defaults3 = {\n ariaLabel: \"vector\",\n fill: \"none\",\n stroke: \"currentColor\",\n strokeWidth: 1.5,\n strokeLinejoin: \"round\",\n strokeLinecap: \"round\"\n};\nvar defaultRadius = 3.5;\nvar wingRatio = defaultRadius * 5;\nvar shapeArrow = {\n draw(context, l, r) {\n const wing = l * r / wingRatio;\n context.moveTo(0, 0);\n context.lineTo(0, -l);\n context.moveTo(-wing, wing - l);\n context.lineTo(0, -l);\n context.lineTo(wing, wing - l);\n }\n};\nvar shapeSpike = {\n draw(context, l, r) {\n context.moveTo(-r, 0);\n context.lineTo(0, -l);\n context.lineTo(r, 0);\n }\n};\nvar shapes = /* @__PURE__ */ new Map([\n [\"arrow\", shapeArrow],\n [\"spike\", shapeSpike]\n]);\nfunction isShapeObject(value) {\n return value && typeof value.draw === \"function\";\n}\nfunction maybeShape(shape) {\n if (isShapeObject(shape)) return shape;\n const value = shapes.get(`${shape}`.toLowerCase());\n if (value) return value;\n throw new Error(`invalid shape: ${shape}`);\n}\nvar Vector = class extends Mark {\n constructor(data, options = {}) {\n const { x: x3, y: y3, r = defaultRadius, length: length4, rotate, shape = shapeArrow, anchor = \"middle\", frameAnchor } = options;\n const [vl, cl] = maybeNumberChannel(length4, 12);\n const [vr, cr] = maybeNumberChannel(rotate, 0);\n super(\n data,\n {\n x: { value: x3, scale: \"x\", optional: true },\n y: { value: y3, scale: \"y\", optional: true },\n length: { value: vl, scale: \"length\", optional: true },\n rotate: { value: vr, optional: true }\n },\n options,\n defaults3\n );\n this.r = +r;\n this.length = cl;\n this.rotate = cr;\n this.shape = maybeShape(shape);\n this.anchor = keyword(anchor, \"anchor\", [\"start\", \"middle\", \"end\"]);\n this.frameAnchor = maybeFrameAnchor(frameAnchor);\n }\n render(index2, scales2, channels, dimensions, context) {\n const { x: x3, y: y3 } = scales2;\n const { x: X3, y: Y3, length: L, rotate: A5 } = channels;\n const { length: length4, rotate, anchor, shape, r } = this;\n const [cx, cy] = applyFrameAnchor(this, dimensions);\n return create4(\"svg:g\", context).call(applyIndirectStyles, this, dimensions, context).call(applyTransform, this, { x: X3 && x3, y: Y3 && y3 }).call(\n (g) => g.selectAll().data(index2).enter().append(\"path\").call(applyDirectStyles, this).attr(\n \"transform\",\n template`translate(${X3 ? (i) => X3[i] : cx},${Y3 ? (i) => Y3[i] : cy})${A5 ? (i) => ` rotate(${A5[i]})` : rotate ? ` rotate(${rotate})` : ``}${anchor === \"start\" ? `` : anchor === \"end\" ? L ? (i) => ` translate(0,${L[i]})` : ` translate(0,${length4})` : L ? (i) => ` translate(0,${L[i] / 2})` : ` translate(0,${length4 / 2})`}`\n ).attr(\n \"d\",\n L ? (i) => {\n const p = pathRound();\n shape.draw(p, L[i], r);\n return p;\n } : (() => {\n const p = pathRound();\n shape.draw(p, length4, r);\n return p;\n })()\n ).call(applyChannelStyles, this, channels)\n ).node();\n }\n};\nfunction vector(data, options = {}) {\n let { x: x3, y: y3, ...rest } = options;\n if (options.frameAnchor === void 0) [x3, y3] = maybeTuple(x3, y3);\n return new Vector(data, { ...rest, x: x3, y: y3 });\n}\nfunction vectorX(data, options = {}) {\n const { x: x3 = identity7, ...rest } = options;\n return new Vector(data, { ...rest, x: x3 });\n}\nfunction vectorY(data, options = {}) {\n const { y: y3 = identity7, ...rest } = options;\n return new Vector(data, { ...rest, y: y3 });\n}\nfunction spike(data, options = {}) {\n const {\n shape = shapeSpike,\n stroke = defaults3.stroke,\n strokeWidth = 1,\n fill = stroke,\n fillOpacity = 0.3,\n anchor = \"start\",\n ...rest\n } = options;\n return vector(data, { ...rest, shape, stroke, strokeWidth, fill, fillOpacity, anchor });\n}\n\n// ../../node_modules/@observablehq/plot/src/marks/axis.js\nfunction maybeData(data, options) {\n if (arguments.length < 2 && !isIterable(data)) options = data, data = null;\n if (options === void 0) options = {};\n return [data, options];\n}\nfunction maybeAnchor2({ anchor } = {}, anchors) {\n return anchor === void 0 ? anchors[0] : keyword(anchor, \"anchor\", anchors);\n}\nfunction anchorY2(options) {\n return maybeAnchor2(options, [\"left\", \"right\"]);\n}\nfunction anchorFy(options) {\n return maybeAnchor2(options, [\"right\", \"left\"]);\n}\nfunction anchorX2(options) {\n return maybeAnchor2(options, [\"bottom\", \"top\"]);\n}\nfunction anchorFx(options) {\n return maybeAnchor2(options, [\"top\", \"bottom\"]);\n}\nfunction axisY() {\n const [data, options] = maybeData(...arguments);\n return axisKy(\"y\", anchorY2(options), data, options);\n}\nfunction axisFy() {\n const [data, options] = maybeData(...arguments);\n return axisKy(\"fy\", anchorFy(options), data, options);\n}\nfunction axisX() {\n const [data, options] = maybeData(...arguments);\n return axisKx(\"x\", anchorX2(options), data, options);\n}\nfunction axisFx() {\n const [data, options] = maybeData(...arguments);\n return axisKx(\"fx\", anchorFx(options), data, options);\n}\nfunction axisKy(k2, anchor, data, {\n color: color3 = \"currentColor\",\n opacity: opacity2 = 1,\n stroke = color3,\n strokeOpacity = opacity2,\n strokeWidth = 1,\n fill = color3,\n fillOpacity = opacity2,\n textAnchor,\n textStroke,\n textStrokeOpacity,\n textStrokeWidth,\n tickSize = k2 === \"y\" ? 6 : 0,\n tickPadding,\n tickRotate,\n x: x3,\n margin: margin2,\n marginTop: marginTop2 = margin2 === void 0 ? 20 : margin2,\n marginRight: marginRight2 = margin2 === void 0 ? anchor === \"right\" ? 40 : 0 : margin2,\n marginBottom: marginBottom2 = margin2 === void 0 ? 20 : margin2,\n marginLeft: marginLeft2 = margin2 === void 0 ? anchor === \"left\" ? 40 : 0 : margin2,\n label: label2,\n labelAnchor,\n labelArrow,\n labelOffset,\n ...options\n}) {\n tickSize = number5(tickSize);\n tickPadding = number5(tickPadding);\n tickRotate = number5(tickRotate);\n if (labelAnchor !== void 0) labelAnchor = keyword(labelAnchor, \"labelAnchor\", [\"center\", \"top\", \"bottom\"]);\n labelArrow = maybeLabelArrow(labelArrow);\n return marks(\n tickSize && !isNoneish(stroke) ? axisTickKy(k2, anchor, data, {\n stroke,\n strokeOpacity,\n strokeWidth,\n tickSize,\n tickPadding,\n tickRotate,\n x: x3,\n ...options\n }) : null,\n !isNoneish(fill) ? axisTextKy(k2, anchor, data, {\n fill,\n fillOpacity,\n stroke: textStroke,\n strokeOpacity: textStrokeOpacity,\n strokeWidth: textStrokeWidth,\n textAnchor,\n tickSize,\n tickPadding,\n tickRotate,\n x: x3,\n marginTop: marginTop2,\n marginRight: marginRight2,\n marginBottom: marginBottom2,\n marginLeft: marginLeft2,\n ...options\n }) : null,\n !isNoneish(fill) && label2 !== null ? text(\n [],\n labelOptions({ fill, fillOpacity, ...options }, function(data2, facets, channels, scales2, dimensions) {\n const scale3 = scales2[k2];\n const { marginTop: marginTop3, marginRight: marginRight3, marginBottom: marginBottom3, marginLeft: marginLeft3 } = k2 === \"y\" && dimensions.inset || dimensions;\n const cla = labelAnchor ?? (scale3.bandwidth ? \"center\" : \"top\");\n const clo = labelOffset ?? (anchor === \"right\" ? marginRight3 : marginLeft3) - 3;\n if (cla === \"center\") {\n this.textAnchor = void 0;\n this.lineAnchor = anchor === \"right\" ? \"bottom\" : \"top\";\n this.frameAnchor = anchor;\n this.rotate = -90;\n } else {\n this.textAnchor = anchor === \"right\" ? \"end\" : \"start\";\n this.lineAnchor = cla;\n this.frameAnchor = `${cla}-${anchor}`;\n this.rotate = 0;\n }\n this.dy = cla === \"top\" ? 3 - marginTop3 : cla === \"bottom\" ? marginBottom3 - 3 : 0;\n this.dx = anchor === \"right\" ? clo : -clo;\n this.ariaLabel = `${k2}-axis label`;\n return {\n facets: [[0]],\n channels: { text: { value: [formatAxisLabel(k2, scale3, { anchor, label: label2, labelAnchor: cla, labelArrow })] } }\n };\n })\n ) : null\n );\n}\nfunction axisKx(k2, anchor, data, {\n color: color3 = \"currentColor\",\n opacity: opacity2 = 1,\n stroke = color3,\n strokeOpacity = opacity2,\n strokeWidth = 1,\n fill = color3,\n fillOpacity = opacity2,\n textAnchor,\n textStroke,\n textStrokeOpacity,\n textStrokeWidth,\n tickSize = k2 === \"x\" ? 6 : 0,\n tickPadding,\n tickRotate,\n y: y3,\n margin: margin2,\n marginTop: marginTop2 = margin2 === void 0 ? anchor === \"top\" ? 30 : 0 : margin2,\n marginRight: marginRight2 = margin2 === void 0 ? 20 : margin2,\n marginBottom: marginBottom2 = margin2 === void 0 ? anchor === \"bottom\" ? 30 : 0 : margin2,\n marginLeft: marginLeft2 = margin2 === void 0 ? 20 : margin2,\n label: label2,\n labelAnchor,\n labelArrow,\n labelOffset,\n ...options\n}) {\n tickSize = number5(tickSize);\n tickPadding = number5(tickPadding);\n tickRotate = number5(tickRotate);\n if (labelAnchor !== void 0) labelAnchor = keyword(labelAnchor, \"labelAnchor\", [\"center\", \"left\", \"right\"]);\n labelArrow = maybeLabelArrow(labelArrow);\n return marks(\n tickSize && !isNoneish(stroke) ? axisTickKx(k2, anchor, data, {\n stroke,\n strokeOpacity,\n strokeWidth,\n tickSize,\n tickPadding,\n tickRotate,\n y: y3,\n ...options\n }) : null,\n !isNoneish(fill) ? axisTextKx(k2, anchor, data, {\n fill,\n fillOpacity,\n stroke: textStroke,\n strokeOpacity: textStrokeOpacity,\n strokeWidth: textStrokeWidth,\n textAnchor,\n tickSize,\n tickPadding,\n tickRotate,\n y: y3,\n marginTop: marginTop2,\n marginRight: marginRight2,\n marginBottom: marginBottom2,\n marginLeft: marginLeft2,\n ...options\n }) : null,\n !isNoneish(fill) && label2 !== null ? text(\n [],\n labelOptions({ fill, fillOpacity, ...options }, function(data2, facets, channels, scales2, dimensions) {\n const scale3 = scales2[k2];\n const { marginTop: marginTop3, marginRight: marginRight3, marginBottom: marginBottom3, marginLeft: marginLeft3 } = k2 === \"x\" && dimensions.inset || dimensions;\n const cla = labelAnchor ?? (scale3.bandwidth ? \"center\" : \"right\");\n const clo = labelOffset ?? (anchor === \"top\" ? marginTop3 : marginBottom3) - 3;\n if (cla === \"center\") {\n this.frameAnchor = anchor;\n this.textAnchor = void 0;\n } else {\n this.frameAnchor = `${anchor}-${cla}`;\n this.textAnchor = cla === \"right\" ? \"end\" : \"start\";\n }\n this.lineAnchor = anchor;\n this.dy = anchor === \"top\" ? -clo : clo;\n this.dx = cla === \"right\" ? marginRight3 - 3 : cla === \"left\" ? 3 - marginLeft3 : 0;\n this.ariaLabel = `${k2}-axis label`;\n return {\n facets: [[0]],\n channels: { text: { value: [formatAxisLabel(k2, scale3, { anchor, label: label2, labelAnchor: cla, labelArrow })] } }\n };\n })\n ) : null\n );\n}\nfunction axisTickKy(k2, anchor, data, {\n strokeWidth = 1,\n strokeLinecap = null,\n strokeLinejoin = null,\n facetAnchor = anchor + (k2 === \"y\" ? \"-empty\" : \"\"),\n frameAnchor = anchor,\n tickSize,\n inset: inset2 = 0,\n insetLeft = inset2,\n insetRight = inset2,\n dx = 0,\n y: y3 = k2 === \"y\" ? void 0 : null,\n ...options\n}) {\n return axisMark(\n vectorY,\n k2,\n data,\n {\n ariaLabel: `${k2}-axis tick`,\n ariaHidden: true\n },\n {\n strokeWidth,\n strokeLinecap,\n strokeLinejoin,\n facetAnchor,\n frameAnchor,\n y: y3,\n ...options,\n dx: anchor === \"left\" ? +dx - offset + +insetLeft : +dx + offset - insetRight,\n anchor: \"start\",\n length: tickSize,\n shape: anchor === \"left\" ? shapeTickLeft : shapeTickRight\n }\n );\n}\nfunction axisTickKx(k2, anchor, data, {\n strokeWidth = 1,\n strokeLinecap = null,\n strokeLinejoin = null,\n facetAnchor = anchor + (k2 === \"x\" ? \"-empty\" : \"\"),\n frameAnchor = anchor,\n tickSize,\n inset: inset2 = 0,\n insetTop = inset2,\n insetBottom = inset2,\n dy = 0,\n x: x3 = k2 === \"x\" ? void 0 : null,\n ...options\n}) {\n return axisMark(\n vectorX,\n k2,\n data,\n {\n ariaLabel: `${k2}-axis tick`,\n ariaHidden: true\n },\n {\n strokeWidth,\n strokeLinejoin,\n strokeLinecap,\n facetAnchor,\n frameAnchor,\n x: x3,\n ...options,\n dy: anchor === \"bottom\" ? +dy - offset - insetBottom : +dy + offset + +insetTop,\n anchor: \"start\",\n length: tickSize,\n shape: anchor === \"bottom\" ? shapeTickBottom : shapeTickTop\n }\n );\n}\nfunction axisTextKy(k2, anchor, data, {\n facetAnchor = anchor + (k2 === \"y\" ? \"-empty\" : \"\"),\n frameAnchor = anchor,\n tickSize,\n tickRotate = 0,\n tickPadding = Math.max(3, 9 - tickSize) + (Math.abs(tickRotate) > 60 ? 4 * Math.cos(tickRotate * radians3) : 0),\n text: text3,\n textAnchor = Math.abs(tickRotate) > 60 ? \"middle\" : anchor === \"left\" ? \"end\" : \"start\",\n lineAnchor = tickRotate > 60 ? \"top\" : tickRotate < -60 ? \"bottom\" : \"middle\",\n fontVariant,\n inset: inset2 = 0,\n insetLeft = inset2,\n insetRight = inset2,\n dx = 0,\n y: y3 = k2 === \"y\" ? void 0 : null,\n ...options\n}) {\n return axisMark(\n textY,\n k2,\n data,\n { ariaLabel: `${k2}-axis tick label` },\n {\n facetAnchor,\n frameAnchor,\n text: text3,\n textAnchor,\n lineAnchor,\n fontVariant,\n rotate: tickRotate,\n y: y3,\n ...options,\n dx: anchor === \"left\" ? +dx - tickSize - tickPadding + +insetLeft : +dx + +tickSize + +tickPadding - insetRight\n },\n function(scale3, data2, ticks2, tickFormat2, channels) {\n if (fontVariant === void 0) this.fontVariant = inferFontVariant3(scale3);\n if (text3 === void 0) channels.text = inferTextChannel(scale3, data2, ticks2, tickFormat2, anchor);\n }\n );\n}\nfunction axisTextKx(k2, anchor, data, {\n facetAnchor = anchor + (k2 === \"x\" ? \"-empty\" : \"\"),\n frameAnchor = anchor,\n tickSize,\n tickRotate = 0,\n tickPadding = Math.max(3, 9 - tickSize) + (Math.abs(tickRotate) >= 10 ? 4 * Math.cos(tickRotate * radians3) : 0),\n text: text3,\n textAnchor = Math.abs(tickRotate) >= 10 ? tickRotate < 0 ^ anchor === \"bottom\" ? \"start\" : \"end\" : \"middle\",\n lineAnchor = Math.abs(tickRotate) >= 10 ? \"middle\" : anchor === \"bottom\" ? \"top\" : \"bottom\",\n fontVariant,\n inset: inset2 = 0,\n insetTop = inset2,\n insetBottom = inset2,\n dy = 0,\n x: x3 = k2 === \"x\" ? void 0 : null,\n ...options\n}) {\n return axisMark(\n textX,\n k2,\n data,\n { ariaLabel: `${k2}-axis tick label` },\n {\n facetAnchor,\n frameAnchor,\n text: text3 === void 0 ? null : text3,\n textAnchor,\n lineAnchor,\n fontVariant,\n rotate: tickRotate,\n x: x3,\n ...options,\n dy: anchor === \"bottom\" ? +dy + +tickSize + +tickPadding - insetBottom : +dy - tickSize - tickPadding + +insetTop\n },\n function(scale3, data2, ticks2, tickFormat2, channels) {\n if (fontVariant === void 0) this.fontVariant = inferFontVariant3(scale3);\n if (text3 === void 0) channels.text = inferTextChannel(scale3, data2, ticks2, tickFormat2, anchor);\n }\n );\n}\nfunction gridY() {\n const [data, options] = maybeData(...arguments);\n return gridKy(\"y\", anchorY2(options), data, options);\n}\nfunction gridFy() {\n const [data, options] = maybeData(...arguments);\n return gridKy(\"fy\", anchorFy(options), data, options);\n}\nfunction gridX() {\n const [data, options] = maybeData(...arguments);\n return gridKx(\"x\", anchorX2(options), data, options);\n}\nfunction gridFx() {\n const [data, options] = maybeData(...arguments);\n return gridKx(\"fx\", anchorFx(options), data, options);\n}\nfunction gridKy(k2, anchor, data, {\n y: y3 = k2 === \"y\" ? void 0 : null,\n x: x3 = null,\n x1: x12 = anchor === \"left\" ? x3 : null,\n x2: x22 = anchor === \"right\" ? x3 : null,\n ...options\n}) {\n return axisMark(ruleY, k2, data, { ariaLabel: `${k2}-grid`, ariaHidden: true }, { y: y3, x1: x12, x2: x22, ...gridDefaults(options) });\n}\nfunction gridKx(k2, anchor, data, {\n x: x3 = k2 === \"x\" ? void 0 : null,\n y: y3 = null,\n y1: y12 = anchor === \"top\" ? y3 : null,\n y2: y22 = anchor === \"bottom\" ? y3 : null,\n ...options\n}) {\n return axisMark(ruleX, k2, data, { ariaLabel: `${k2}-grid`, ariaHidden: true }, { x: x3, y1: y12, y2: y22, ...gridDefaults(options) });\n}\nfunction gridDefaults({\n color: color3 = \"currentColor\",\n opacity: opacity2 = 0.1,\n stroke = color3,\n strokeOpacity = opacity2,\n strokeWidth = 1,\n ...options\n}) {\n return { stroke, strokeOpacity, strokeWidth, ...options };\n}\nfunction labelOptions({\n fill,\n fillOpacity,\n fontFamily,\n fontSize,\n fontStyle,\n fontVariant,\n fontWeight,\n monospace,\n pointerEvents,\n shapeRendering,\n clip = false\n}, initializer2) {\n [, fill] = maybeColorChannel(fill);\n [, fillOpacity] = maybeNumberChannel(fillOpacity);\n return {\n facet: \"super\",\n x: null,\n y: null,\n fill,\n fillOpacity,\n fontFamily,\n fontSize,\n fontStyle,\n fontVariant,\n fontWeight,\n monospace,\n pointerEvents,\n shapeRendering,\n clip,\n initializer: initializer2\n };\n}\nfunction axisMark(mark2, k2, data, properties, options, initialize) {\n let channels;\n function axisInitializer(data2, facets, _channels, scales2, dimensions, context) {\n const initializeFacets = data2 == null && (k2 === \"fx\" || k2 === \"fy\");\n const { [k2]: scale3 } = scales2;\n if (!scale3) throw new Error(`missing scale: ${k2}`);\n const domain = scale3.domain();\n let { interval: interval3, ticks: ticks2, tickFormat: tickFormat2, tickSpacing = k2 === \"x\" ? 80 : 35 } = options;\n if (typeof ticks2 === \"string\" && hasTemporalDomain(scale3)) interval3 = ticks2, ticks2 = void 0;\n if (ticks2 === void 0) ticks2 = maybeRangeInterval(interval3, scale3.type) ?? inferTickCount(scale3, tickSpacing);\n if (data2 == null) {\n if (isIterable(ticks2)) {\n data2 = arrayify2(ticks2);\n } else if (isInterval(ticks2)) {\n data2 = inclusiveRange(ticks2, ...extent(domain));\n } else if (scale3.interval) {\n let interval4 = scale3.interval;\n if (scale3.ticks) {\n const [min5, max4] = extent(domain);\n const n = (max4 - min5) / interval4[intervalDuration];\n interval4 = generalizeTimeInterval(interval4, n / ticks2) ?? interval4;\n data2 = inclusiveRange(interval4, min5, max4);\n } else {\n data2 = domain;\n const n = data2.length;\n interval4 = generalizeTimeInterval(interval4, n / ticks2) ?? interval4;\n if (interval4 !== scale3.interval) data2 = inclusiveRange(interval4, ...extent(data2));\n }\n if (interval4 === scale3.interval) {\n const n = Math.round(data2.length / ticks2);\n if (n > 1) data2 = data2.filter((d, i) => i % n === 0);\n }\n } else if (scale3.ticks) {\n data2 = scale3.ticks(ticks2);\n } else {\n data2 = domain;\n }\n if (!scale3.ticks && data2.length && data2 !== domain) {\n const domainSet = new InternSet(domain);\n data2 = data2.filter((d) => domainSet.has(d));\n if (!data2.length) warn(`Warning: the ${k2}-axis ticks appear to not align with the scale domain, resulting in no ticks. Try different ticks?`);\n }\n if (k2 === \"y\" || k2 === \"x\") {\n facets = [range2(data2)];\n } else {\n channels[k2] = { scale: k2, value: identity7 };\n }\n }\n initialize?.call(this, scale3, data2, ticks2, tickFormat2, channels);\n const initializedChannels = Object.fromEntries(\n Object.entries(channels).map(([name2, channel]) => {\n return [name2, { ...channel, value: valueof(data2, channel.value) }];\n })\n );\n if (initializeFacets) facets = context.filterFacets(data2, initializedChannels);\n return { data: data2, facets, channels: initializedChannels };\n }\n const basicInitializer = initializer(options).initializer;\n const m = mark2(data, initializer({ ...options, initializer: axisInitializer }, basicInitializer));\n if (data == null) {\n channels = m.channels;\n m.channels = {};\n } else {\n channels = {};\n }\n if (properties !== void 0) Object.assign(m, properties);\n if (m.clip === void 0) m.clip = false;\n return m;\n}\nfunction inferTickCount(scale3, tickSpacing) {\n const [min5, max4] = extent(scale3.range());\n return (max4 - min5) / tickSpacing;\n}\nfunction inferTextChannel(scale3, data, ticks2, tickFormat2, anchor) {\n return { value: inferTickFormat(scale3, data, ticks2, tickFormat2, anchor) };\n}\nfunction inferTickFormat(scale3, data, ticks2, tickFormat2, anchor) {\n return typeof tickFormat2 === \"function\" && !(scale3.type === \"log\" && scale3.tickFormat) ? tickFormat2 : tickFormat2 === void 0 && data && isTemporal(data) ? inferTimeFormat(scale3.type, data, anchor) ?? formatDefault : scale3.tickFormat ? scale3.tickFormat(typeof ticks2 === \"number\" ? ticks2 : null, tickFormat2) : tickFormat2 === void 0 ? formatDefault : typeof tickFormat2 === \"string\" ? (isTemporal(scale3.domain()) ? utcFormat : format)(tickFormat2) : constant(tickFormat2);\n}\nfunction inclusiveRange(interval3, min5, max4) {\n return interval3.range(min5, interval3.offset(interval3.floor(max4)));\n}\nvar shapeTickBottom = {\n draw(context, l) {\n context.moveTo(0, 0);\n context.lineTo(0, l);\n }\n};\nvar shapeTickTop = {\n draw(context, l) {\n context.moveTo(0, 0);\n context.lineTo(0, -l);\n }\n};\nvar shapeTickLeft = {\n draw(context, l) {\n context.moveTo(0, 0);\n context.lineTo(-l, 0);\n }\n};\nvar shapeTickRight = {\n draw(context, l) {\n context.moveTo(0, 0);\n context.lineTo(l, 0);\n }\n};\nfunction inferFontVariant3(scale3) {\n return scale3.bandwidth && !scale3.interval ? void 0 : \"tabular-nums\";\n}\nfunction formatAxisLabel(k2, scale3, { anchor, label: label2 = scale3.label, labelAnchor, labelArrow } = {}) {\n if (label2 == null || label2.inferred && hasTemporalDomain(scale3) && /^(date|time|year)$/i.test(label2)) return;\n label2 = String(label2);\n if (labelArrow === \"auto\") labelArrow = (!scale3.bandwidth || scale3.interval) && !/[↑↓→←]/.test(label2);\n if (!labelArrow) return label2;\n if (labelArrow === true) {\n const order = inferScaleOrder(scale3);\n if (order)\n labelArrow = /x$/.test(k2) || labelAnchor === \"center\" ? /x$/.test(k2) === order < 0 ? \"left\" : \"right\" : order < 0 ? \"up\" : \"down\";\n }\n switch (labelArrow) {\n case \"left\":\n return `\\u2190 ${label2}`;\n case \"right\":\n return `${label2} \\u2192`;\n case \"up\":\n return anchor === \"right\" ? `${label2} \\u2191` : `\\u2191 ${label2}`;\n case \"down\":\n return anchor === \"right\" ? `${label2} \\u2193` : `\\u2193 ${label2}`;\n }\n return label2;\n}\nfunction maybeLabelArrow(labelArrow = \"auto\") {\n return isNoneish(labelArrow) ? false : typeof labelArrow === \"boolean\" ? labelArrow : keyword(labelArrow, \"labelArrow\", [\"auto\", \"up\", \"right\", \"down\", \"left\"]);\n}\nfunction hasTemporalDomain(scale3) {\n return isTemporal(scale3.domain());\n}\n\n// ../../node_modules/@observablehq/plot/src/legends/swatches.js\nfunction maybeScale(scale3, key) {\n if (key == null) return key;\n const s2 = scale3(key);\n if (!s2) throw new Error(`scale not found: ${key}`);\n return s2;\n}\nfunction legendSwatches(color3, { opacity: opacity2, ...options } = {}) {\n if (!isOrdinalScale(color3) && !isThresholdScale(color3))\n throw new Error(`swatches legend requires ordinal or threshold color scale (not ${color3.type})`);\n return legendItems(\n color3,\n options,\n (selection2, scale3, width2, height2) => selection2.append(\"svg\").attr(\"width\", width2).attr(\"height\", height2).attr(\"fill\", scale3.scale).attr(\"fill-opacity\", maybeNumberChannel(opacity2)[1]).append(\"rect\").attr(\"width\", \"100%\").attr(\"height\", \"100%\")\n );\n}\nfunction legendSymbols(symbol2, {\n fill = symbol2.hint?.fill !== void 0 ? symbol2.hint.fill : \"none\",\n fillOpacity = 1,\n stroke = symbol2.hint?.stroke !== void 0 ? symbol2.hint.stroke : isNoneish(fill) ? \"currentColor\" : \"none\",\n strokeOpacity = 1,\n strokeWidth = 1.5,\n r = 4.5,\n ...options\n} = {}, scale3) {\n const [vf, cf] = maybeColorChannel(fill);\n const [vs, cs] = maybeColorChannel(stroke);\n const sf = maybeScale(scale3, vf);\n const ss = maybeScale(scale3, vs);\n const size = r * r * Math.PI;\n fillOpacity = maybeNumberChannel(fillOpacity)[1];\n strokeOpacity = maybeNumberChannel(strokeOpacity)[1];\n strokeWidth = maybeNumberChannel(strokeWidth)[1];\n return legendItems(\n symbol2,\n options,\n (selection2, scale4, width2, height2) => selection2.append(\"svg\").attr(\"viewBox\", \"-8 -8 16 16\").attr(\"width\", width2).attr(\"height\", height2).attr(\"fill\", vf === \"color\" ? (d) => sf.scale(d) : cf).attr(\"fill-opacity\", fillOpacity).attr(\"stroke\", vs === \"color\" ? (d) => ss.scale(d) : cs).attr(\"stroke-opacity\", strokeOpacity).attr(\"stroke-width\", strokeWidth).append(\"path\").attr(\"d\", (d) => {\n const p = pathRound();\n symbol2.scale(d).draw(p, size);\n return p;\n })\n );\n}\nfunction legendItems(scale3, options = {}, swatch) {\n let {\n columns,\n tickFormat: tickFormat2,\n fontVariant = inferFontVariant(scale3),\n // TODO label,\n swatchSize = 15,\n swatchWidth = swatchSize,\n swatchHeight = swatchSize,\n marginLeft: marginLeft2 = 0,\n className,\n style: style2,\n width: width2\n } = options;\n const context = createContext(options);\n className = maybeClassName(className);\n tickFormat2 = inferTickFormat(scale3.scale, scale3.domain, void 0, tickFormat2);\n const swatches = create4(\"div\", context).attr(\n \"class\",\n `${className}-swatches ${className}-swatches-${columns != null ? \"columns\" : \"wrap\"}`\n );\n let extraStyle;\n if (columns != null) {\n extraStyle = `:where(.${className}-swatches-columns .${className}-swatch) {\n display: flex;\n align-items: center;\n break-inside: avoid;\n padding-bottom: 1px;\n}\n:where(.${className}-swatches-columns .${className}-swatch::before) {\n flex-shrink: 0;\n}\n:where(.${className}-swatches-columns .${className}-swatch-label) {\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}`;\n swatches.style(\"columns\", columns).selectAll().data(scale3.domain).enter().append(\"div\").attr(\"class\", `${className}-swatch`).call(swatch, scale3, swatchWidth, swatchHeight).call(\n (item) => item.append(\"div\").attr(\"class\", `${className}-swatch-label`).attr(\"title\", tickFormat2).text(tickFormat2)\n );\n } else {\n extraStyle = `:where(.${className}-swatches-wrap) {\n display: flex;\n align-items: center;\n min-height: 33px;\n flex-wrap: wrap;\n}\n:where(.${className}-swatches-wrap .${className}-swatch) {\n display: inline-flex;\n align-items: center;\n margin-right: 1em;\n}`;\n swatches.selectAll().data(scale3.domain).enter().append(\"span\").attr(\"class\", `${className}-swatch`).call(swatch, scale3, swatchWidth, swatchHeight).append(function() {\n return this.ownerDocument.createTextNode(tickFormat2.apply(this, arguments));\n });\n }\n return swatches.call(\n (div) => div.insert(\"style\", \"*\").text(\n `:where(.${className}-swatches) {\n font-family: system-ui, sans-serif;\n font-size: 10px;\n margin-bottom: 0.5em;\n}\n:where(.${className}-swatch > svg) {\n margin-right: 0.5em;\n overflow: visible;\n}\n${extraStyle}`\n )\n ).style(\"margin-left\", marginLeft2 ? `${+marginLeft2}px` : null).style(\"width\", width2 === void 0 ? null : `${+width2}px`).style(\"font-variant\", impliedString(fontVariant, \"normal\")).call(applyInlineStyles, style2).node();\n}\n\n// ../../node_modules/@observablehq/plot/src/legends.js\nvar legendRegistry = /* @__PURE__ */ new Map([\n [\"symbol\", legendSymbols],\n [\"color\", legendColor],\n [\"opacity\", legendOpacity]\n]);\nfunction legend(options = {}) {\n for (const [key, value] of legendRegistry) {\n const scale3 = options[key];\n if (isScaleOptions(scale3)) {\n const context = createContext(options);\n let hint;\n if (key === \"symbol\") {\n const { fill, stroke = fill === void 0 && isScaleOptions(options.color) ? \"color\" : void 0 } = options;\n hint = { fill, stroke };\n }\n return value(\n normalizeScale(key, scale3, hint),\n legendOptions(context, scale3, options),\n (key2) => isScaleOptions(options[key2]) ? normalizeScale(key2, options[key2]) : null\n );\n }\n }\n throw new Error(\"unknown legend type; no scale found\");\n}\nfunction exposeLegends(scales2, context, defaults22 = {}) {\n return (key, options) => {\n if (!legendRegistry.has(key)) throw new Error(`unknown legend type: ${key}`);\n if (!(key in scales2)) return;\n return legendRegistry.get(key)(scales2[key], legendOptions(context, defaults22[key], options), (key2) => scales2[key2]);\n };\n}\nfunction legendOptions({ className, ...context }, { label: label2, ticks: ticks2, tickFormat: tickFormat2 } = {}, options) {\n return inherit2(options, { className, ...context }, { label: label2, ticks: ticks2, tickFormat: tickFormat2 });\n}\nfunction legendColor(color3, { legend: legend3 = true, ...options }) {\n if (legend3 === true) legend3 = color3.type === \"ordinal\" ? \"swatches\" : \"ramp\";\n if (color3.domain === void 0) return;\n switch (`${legend3}`.toLowerCase()) {\n case \"swatches\":\n return legendSwatches(color3, options);\n case \"ramp\":\n return legendRamp(color3, options);\n default:\n throw new Error(`unknown legend type: ${legend3}`);\n }\n}\nfunction legendOpacity({ type: type2, interpolate, ...scale3 }, { legend: legend3 = true, color: color3 = rgb(0, 0, 0), ...options }) {\n if (!interpolate) throw new Error(`${type2} opacity scales are not supported`);\n if (legend3 === true) legend3 = \"ramp\";\n if (`${legend3}`.toLowerCase() !== \"ramp\") throw new Error(`${legend3} opacity legends are not supported`);\n return legendColor({ type: type2, ...scale3, interpolate: interpolateOpacity(color3) }, { legend: legend3, ...options });\n}\nfunction interpolateOpacity(color3) {\n const { r, g, b } = rgb(color3) || rgb(0, 0, 0);\n return (t) => `rgba(${r},${g},${b},${t})`;\n}\nfunction createLegends(scales2, context, options) {\n const legends = [];\n for (const [key, value] of legendRegistry) {\n const o = options[key];\n if (o?.legend && key in scales2) {\n const legend3 = value(scales2[key], legendOptions(context, scales2[key], o), (key2) => scales2[key2]);\n if (legend3 != null) legends.push(legend3);\n }\n }\n return legends;\n}\n\n// ../../node_modules/@observablehq/plot/src/transforms/identity.js\nfunction maybeIdentityX(options = {}) {\n return hasX(options) ? options : { ...options, x: identity7 };\n}\nfunction maybeIdentityY(options = {}) {\n return hasY(options) ? options : { ...options, y: identity7 };\n}\n\n// ../../node_modules/@observablehq/plot/src/transforms/exclusiveFacets.js\nfunction exclusiveFacets(data, facets) {\n if (facets.length === 1) return { data, facets };\n const n = lengthof(data);\n const O = new Uint8Array(n);\n let overlaps = 0;\n for (const facet of facets) {\n for (const i of facet) {\n if (O[i]) ++overlaps;\n O[i] = 1;\n }\n }\n if (overlaps === 0) return { data, facets };\n data = slice3(data);\n const R = data[reindex] = new Uint32Array(n + overlaps);\n facets = facets.map((facet) => slice3(facet, Uint32Array));\n let j = n;\n O.fill(0);\n for (const facet of facets) {\n for (let k2 = 0, m = facet.length; k2 < m; ++k2) {\n const i = facet[k2];\n if (O[i]) facet[k2] = j, data[j] = data[i], R[j] = i, ++j;\n else R[i] = i;\n O[i] = 1;\n }\n }\n return { data, facets };\n}\n\n// ../../node_modules/@observablehq/plot/src/transforms/stack.js\nfunction stackX(stackOptions = {}, options = {}) {\n if (arguments.length === 1) [stackOptions, options] = mergeOptions(stackOptions);\n const { y1: y12, y: y3 = y12, x: x3, ...rest } = options;\n const [transform3, Y3, x12, x22] = stack(y3, x3, \"y\", \"x\", stackOptions, rest);\n return { ...transform3, y1: y12, y: Y3, x1: x12, x2: x22, x: mid(x12, x22) };\n}\nfunction stackX1(stackOptions = {}, options = {}) {\n if (arguments.length === 1) [stackOptions, options] = mergeOptions(stackOptions);\n const { y1: y12, y: y3 = y12, x: x3 } = options;\n const [transform3, Y3, X3] = stack(y3, x3, \"y\", \"x\", stackOptions, options);\n return { ...transform3, y1: y12, y: Y3, x: X3 };\n}\nfunction stackX2(stackOptions = {}, options = {}) {\n if (arguments.length === 1) [stackOptions, options] = mergeOptions(stackOptions);\n const { y1: y12, y: y3 = y12, x: x3 } = options;\n const [transform3, Y3, , X3] = stack(y3, x3, \"y\", \"x\", stackOptions, options);\n return { ...transform3, y1: y12, y: Y3, x: X3 };\n}\nfunction stackY(stackOptions = {}, options = {}) {\n if (arguments.length === 1) [stackOptions, options] = mergeOptions(stackOptions);\n const { x1: x12, x: x3 = x12, y: y3, ...rest } = options;\n const [transform3, X3, y12, y22] = stack(x3, y3, \"x\", \"y\", stackOptions, rest);\n return { ...transform3, x1: x12, x: X3, y1: y12, y2: y22, y: mid(y12, y22) };\n}\nfunction stackY1(stackOptions = {}, options = {}) {\n if (arguments.length === 1) [stackOptions, options] = mergeOptions(stackOptions);\n const { x1: x12, x: x3 = x12, y: y3 } = options;\n const [transform3, X3, Y3] = stack(x3, y3, \"x\", \"y\", stackOptions, options);\n return { ...transform3, x1: x12, x: X3, y: Y3 };\n}\nfunction stackY2(stackOptions = {}, options = {}) {\n if (arguments.length === 1) [stackOptions, options] = mergeOptions(stackOptions);\n const { x1: x12, x: x3 = x12, y: y3 } = options;\n const [transform3, X3, , Y3] = stack(x3, y3, \"x\", \"y\", stackOptions, options);\n return { ...transform3, x1: x12, x: X3, y: Y3 };\n}\nfunction maybeStackX({ x: x3, x1: x12, x2: x22, ...options } = {}) {\n options = withTip(options, \"y\");\n if (x12 === void 0 && x22 === void 0) return stackX({ x: x3, ...options });\n [x12, x22] = maybeZero(x3, x12, x22);\n return { ...options, x1: x12, x2: x22 };\n}\nfunction maybeStackY({ y: y3, y1: y12, y2: y22, ...options } = {}) {\n options = withTip(options, \"x\");\n if (y12 === void 0 && y22 === void 0) return stackY({ y: y3, ...options });\n [y12, y22] = maybeZero(y3, y12, y22);\n return { ...options, y1: y12, y2: y22 };\n}\nfunction mergeOptions(options) {\n const { offset: offset2, order, reverse: reverse3, ...rest } = options;\n return [{ offset: offset2, order, reverse: reverse3 }, rest];\n}\nvar lengthy = { length: true };\nfunction stack(x3, y3 = one2, kx2, ky2, { offset: offset2, order, reverse: reverse3 }, options) {\n if (y3 === null) throw new Error(`stack requires ${ky2}`);\n const z = maybeZ(options);\n const [X3, setX] = maybeColumn(x3);\n const [Y13, setY1] = column2(y3);\n const [Y23, setY2] = column2(y3);\n Y13.hint = Y23.hint = lengthy;\n offset2 = maybeOffset(offset2);\n order = maybeOrder2(order, offset2, ky2);\n return [\n basic(options, (data, facets, plotOptions) => {\n ({ data, facets } = exclusiveFacets(data, facets));\n const X4 = x3 == null ? void 0 : setX(maybeApplyInterval(valueof(data, x3), plotOptions?.[kx2]));\n const Y3 = valueof(data, y3, Float64Array);\n const Z = valueof(data, z);\n const compare = order && order(data, X4, Y3, Z);\n const n = lengthof(data);\n const Y14 = setY1(new Float64Array(n));\n const Y24 = setY2(new Float64Array(n));\n const facetstacks = [];\n for (const facet of facets) {\n const stacks = X4 ? Array.from(group(facet, (i) => X4[i]).values()) : [facet];\n if (compare) for (const stack2 of stacks) stack2.sort(compare);\n for (const stack2 of stacks) {\n let yn = 0;\n let yp = 0;\n if (reverse3) stack2.reverse();\n for (const i of stack2) {\n const y4 = Y3[i];\n if (y4 < 0) yn = Y24[i] = (Y14[i] = yn) + y4;\n else if (y4 > 0) yp = Y24[i] = (Y14[i] = yp) + y4;\n else Y24[i] = Y14[i] = yp;\n }\n }\n facetstacks.push(stacks);\n }\n if (offset2) offset2(facetstacks, Y14, Y24, Z);\n return { data, facets };\n }),\n X3,\n Y13,\n Y23\n ];\n}\nfunction maybeOffset(offset2) {\n if (offset2 == null) return;\n if (typeof offset2 === \"function\") return offset2;\n switch (`${offset2}`.toLowerCase()) {\n case \"expand\":\n case \"normalize\":\n return offsetExpand;\n case \"center\":\n case \"silhouette\":\n return offsetCenter;\n case \"wiggle\":\n return offsetWiggle;\n }\n throw new Error(`unknown offset: ${offset2}`);\n}\nfunction extent2(stack2, Y23) {\n let min5 = 0, max4 = 0;\n for (const i of stack2) {\n const y3 = Y23[i];\n if (y3 < min5) min5 = y3;\n if (y3 > max4) max4 = y3;\n }\n return [min5, max4];\n}\nfunction offsetExpand(facetstacks, Y13, Y23) {\n for (const stacks of facetstacks) {\n for (const stack2 of stacks) {\n const [yn, yp] = extent2(stack2, Y23);\n for (const i of stack2) {\n const m = 1 / (yp - yn || 1);\n Y13[i] = m * (Y13[i] - yn);\n Y23[i] = m * (Y23[i] - yn);\n }\n }\n }\n}\nfunction offsetCenter(facetstacks, Y13, Y23) {\n for (const stacks of facetstacks) {\n for (const stack2 of stacks) {\n const [yn, yp] = extent2(stack2, Y23);\n for (const i of stack2) {\n const m = (yp + yn) / 2;\n Y13[i] -= m;\n Y23[i] -= m;\n }\n }\n offsetZero(stacks, Y13, Y23);\n }\n offsetCenterFacets(facetstacks, Y13, Y23);\n}\nfunction offsetWiggle(facetstacks, Y13, Y23, Z) {\n for (const stacks of facetstacks) {\n const prev = new InternMap();\n let y3 = 0;\n for (const stack2 of stacks) {\n let j = -1;\n const Fi = stack2.map((i) => Math.abs(Y23[i] - Y13[i]));\n const Df = stack2.map((i) => {\n j = Z ? Z[i] : ++j;\n const value = Y23[i] - Y13[i];\n const diff = prev.has(j) ? value - prev.get(j) : 0;\n prev.set(j, value);\n return diff;\n });\n const Cf1 = [0, ...cumsum(Df)];\n for (const i of stack2) {\n Y13[i] += y3;\n Y23[i] += y3;\n }\n const s1 = sum2(Fi);\n if (s1) y3 -= sum2(Fi, (d, i) => (Df[i] / 2 + Cf1[i]) * d) / s1;\n }\n offsetZero(stacks, Y13, Y23);\n }\n offsetCenterFacets(facetstacks, Y13, Y23);\n}\nfunction offsetZero(stacks, Y13, Y23) {\n const m = min2(stacks, (stack2) => min2(stack2, (i) => Y13[i]));\n for (const stack2 of stacks) {\n for (const i of stack2) {\n Y13[i] -= m;\n Y23[i] -= m;\n }\n }\n}\nfunction offsetCenterFacets(facetstacks, Y13, Y23) {\n const n = facetstacks.length;\n if (n === 1) return;\n const facets = facetstacks.map((stacks) => stacks.flat());\n const m = facets.map((I) => (min2(I, (i) => Y13[i]) + max2(I, (i) => Y23[i])) / 2);\n const m0 = min2(m);\n for (let j = 0; j < n; j++) {\n const p = m0 - m[j];\n for (const i of facets[j]) {\n Y13[i] += p;\n Y23[i] += p;\n }\n }\n}\nfunction maybeOrder2(order, offset2, ky2) {\n if (order === void 0 && offset2 === offsetWiggle) return orderInsideOut(ascendingDefined2);\n if (order == null) return;\n if (typeof order === \"string\") {\n const negate2 = order.startsWith(\"-\");\n const compare = negate2 ? descendingDefined : ascendingDefined2;\n switch ((negate2 ? order.slice(1) : order).toLowerCase()) {\n case \"value\":\n case ky2:\n return orderY(compare);\n case \"z\":\n return orderZ(compare);\n case \"sum\":\n return orderSum(compare);\n case \"appearance\":\n return orderAppearance(compare);\n case \"inside-out\":\n return orderInsideOut(compare);\n }\n return orderAccessor(field2(order));\n }\n if (typeof order === \"function\") return (order.length === 1 ? orderAccessor : orderComparator)(order);\n if (isArray2(order)) return orderGiven(order);\n throw new Error(`invalid order: ${order}`);\n}\nfunction orderY(compare) {\n return (data, X3, Y3) => (i, j) => compare(Y3[i], Y3[j]);\n}\nfunction orderZ(compare) {\n return (data, X3, Y3, Z) => (i, j) => compare(Z[i], Z[j]);\n}\nfunction orderSum(compare) {\n return orderZDomain(\n compare,\n (data, X3, Y3, Z) => groupSort(\n range2(data),\n (I) => sum2(I, (i) => Y3[i]),\n (i) => Z[i]\n )\n );\n}\nfunction orderAppearance(compare) {\n return orderZDomain(\n compare,\n (data, X3, Y3, Z) => groupSort(\n range2(data),\n (I) => X3[greatest(I, (i) => Y3[i])],\n (i) => Z[i]\n )\n );\n}\nfunction orderInsideOut(compare) {\n return orderZDomain(compare, (data, X3, Y3, Z) => {\n const I = range2(data);\n const K2 = groupSort(\n I,\n (I2) => X3[greatest(I2, (i) => Y3[i])],\n (i) => Z[i]\n );\n const sums = rollup(\n I,\n (I2) => sum2(I2, (i) => Y3[i]),\n (i) => Z[i]\n );\n const Kp = [], Kn = [];\n let s2 = 0;\n for (const k2 of K2) {\n if (s2 < 0) {\n s2 += sums.get(k2);\n Kp.push(k2);\n } else {\n s2 -= sums.get(k2);\n Kn.push(k2);\n }\n }\n return Kn.reverse().concat(Kp);\n });\n}\nfunction orderAccessor(f) {\n return (data) => {\n const O = valueof(data, f);\n return (i, j) => ascendingDefined2(O[i], O[j]);\n };\n}\nfunction orderComparator(f) {\n return (data) => {\n return isArray2(data) ? (i, j) => f(data[i], data[j]) : (i, j) => f(data.get(i), data.get(j));\n };\n}\nfunction orderGiven(domain) {\n return orderZDomain(ascendingDefined2, () => domain);\n}\nfunction orderZDomain(compare, domain) {\n return (data, X3, Y3, Z) => {\n if (!Z) throw new Error(\"missing channel: z\");\n const map5 = new InternMap(domain(data, X3, Y3, Z).map((d, i) => [d, i]));\n return (i, j) => compare(map5.get(Z[i]), map5.get(Z[j]));\n };\n}\n\n// ../../node_modules/@observablehq/plot/src/marks/rect.js\nvar defaults4 = {\n ariaLabel: \"rect\"\n};\nvar Rect = class extends Mark {\n constructor(data, options = {}) {\n const { x1: x12, y1: y12, x2: x22, y2: y22 } = options;\n super(\n data,\n {\n x1: { value: x12, scale: \"x\", type: x12 != null && x22 == null ? \"band\" : void 0, optional: true },\n y1: { value: y12, scale: \"y\", type: y12 != null && y22 == null ? \"band\" : void 0, optional: true },\n x2: { value: x22, scale: \"x\", optional: true },\n y2: { value: y22, scale: \"y\", optional: true }\n },\n options,\n defaults4\n );\n rectInsets(this, options);\n rectRadii(this, options);\n }\n render(index2, scales2, channels, dimensions, context) {\n const { x: x3, y: y3 } = scales2;\n let { x1: X13, y1: Y13, x2: X23, y2: Y23 } = channels;\n const { marginTop: marginTop2, marginRight: marginRight2, marginBottom: marginBottom2, marginLeft: marginLeft2, width: width2, height: height2 } = dimensions;\n const { projection: projection3 } = context;\n const { insetTop, insetRight, insetBottom, insetLeft } = this;\n const { rx, ry, rx1y1, rx1y2, rx2y1, rx2y2 } = this;\n if ((X13 || X23) && !projection3 && isCollapsed(x3)) X13 = X23 = null;\n if ((Y13 || Y23) && !projection3 && isCollapsed(y3)) Y13 = Y23 = null;\n const bx = x3?.bandwidth ? x3.bandwidth() : 0;\n const by = y3?.bandwidth ? y3.bandwidth() : 0;\n return create4(\"svg:g\", context).call(applyIndirectStyles, this, dimensions, context).call(applyTransform, this, {}, 0, 0).call(\n (g) => g.selectAll().data(index2).enter().call(\n rx1y1 || rx1y2 || rx2y1 || rx2y2 ? (g2) => g2.append(\"path\").call(applyDirectStyles, this).call(\n applyRoundedRect,\n X13 && X23 ? (i) => X13[i] + (X23[i] < X13[i] ? -insetRight : insetLeft) : X13 ? (i) => X13[i] + insetLeft : marginLeft2 + insetLeft,\n Y13 && Y23 ? (i) => Y13[i] + (Y23[i] < Y13[i] ? -insetBottom : insetTop) : Y13 ? (i) => Y13[i] + insetTop : marginTop2 + insetTop,\n X13 && X23 ? (i) => X23[i] - (X23[i] < X13[i] ? -insetLeft : insetRight) : X13 ? (i) => X13[i] + bx - insetRight : width2 - marginRight2 - insetRight,\n Y13 && Y23 ? (i) => Y23[i] - (Y23[i] < Y13[i] ? -insetTop : insetBottom) : Y13 ? (i) => Y13[i] + by - insetBottom : height2 - marginBottom2 - insetBottom,\n this\n ).call(applyChannelStyles, this, channels) : (g2) => g2.append(\"rect\").call(applyDirectStyles, this).attr(\n \"x\",\n X13 ? X23 ? (i) => Math.min(X13[i], X23[i]) + insetLeft : (i) => X13[i] + insetLeft : marginLeft2 + insetLeft\n ).attr(\n \"y\",\n Y13 ? Y23 ? (i) => Math.min(Y13[i], Y23[i]) + insetTop : (i) => Y13[i] + insetTop : marginTop2 + insetTop\n ).attr(\n \"width\",\n X13 ? X23 ? (i) => Math.max(0, Math.abs(X23[i] - X13[i]) + bx - insetLeft - insetRight) : bx - insetLeft - insetRight : width2 - marginRight2 - marginLeft2 - insetRight - insetLeft\n ).attr(\n \"height\",\n Y13 ? Y23 ? (i) => Math.max(0, Math.abs(Y13[i] - Y23[i]) + by - insetTop - insetBottom) : by - insetTop - insetBottom : height2 - marginTop2 - marginBottom2 - insetTop - insetBottom\n ).call(applyAttr, \"rx\", rx).call(applyAttr, \"ry\", ry).call(applyChannelStyles, this, channels)\n )\n ).node();\n }\n};\nfunction rectInsets(mark2, { inset: inset2 = 0, insetTop = inset2, insetRight = inset2, insetBottom = inset2, insetLeft = inset2 } = {}) {\n mark2.insetTop = number5(insetTop);\n mark2.insetRight = number5(insetRight);\n mark2.insetBottom = number5(insetBottom);\n mark2.insetLeft = number5(insetLeft);\n}\nfunction rectRadii(mark2, {\n r,\n rx,\n // for elliptic corners\n ry,\n // for elliptic corners\n rx1 = r,\n ry1 = r,\n rx2 = r,\n ry2 = r,\n rx1y1 = rx1 !== void 0 ? +rx1 : ry1 !== void 0 ? +ry1 : 0,\n rx1y2 = rx1 !== void 0 ? +rx1 : ry2 !== void 0 ? +ry2 : 0,\n rx2y1 = rx2 !== void 0 ? +rx2 : ry1 !== void 0 ? +ry1 : 0,\n rx2y2 = rx2 !== void 0 ? +rx2 : ry2 !== void 0 ? +ry2 : 0\n} = {}) {\n if (rx1y1 || rx1y2 || rx2y1 || rx2y2) {\n mark2.rx1y1 = rx1y1;\n mark2.rx1y2 = rx1y2;\n mark2.rx2y1 = rx2y1;\n mark2.rx2y2 = rx2y2;\n } else {\n mark2.rx = impliedString(rx, \"auto\");\n mark2.ry = impliedString(ry, \"auto\");\n }\n}\nfunction applyRoundedRect(selection2, X13, Y13, X23, Y23, mark2) {\n const { rx1y1: r11, rx1y2: r12, rx2y1: r21, rx2y2: r22 } = mark2;\n if (typeof X13 !== \"function\") X13 = constant(X13);\n if (typeof Y13 !== \"function\") Y13 = constant(Y13);\n if (typeof X23 !== \"function\") X23 = constant(X23);\n if (typeof Y23 !== \"function\") Y23 = constant(Y23);\n const rx = Math.max(Math.abs(r11 + r21), Math.abs(r12 + r22));\n const ry = Math.max(Math.abs(r11 + r12), Math.abs(r21 + r22));\n selection2.attr(\"d\", (i) => {\n const x12 = X13(i);\n const y12 = Y13(i);\n const x22 = X23(i);\n const y22 = Y23(i);\n const ix = x12 > x22;\n const iy = y12 > y22;\n const l = ix ? x22 : x12;\n const r = ix ? x12 : x22;\n const t = iy ? y22 : y12;\n const b = iy ? y12 : y22;\n const k2 = Math.min(1, (r - l) / rx, (b - t) / ry);\n const tl = k2 * (ix ? iy ? r22 : r21 : iy ? r12 : r11);\n const tr = k2 * (ix ? iy ? r12 : r11 : iy ? r22 : r21);\n const br = k2 * (ix ? iy ? r11 : r12 : iy ? r21 : r22);\n const bl = k2 * (ix ? iy ? r21 : r22 : iy ? r11 : r12);\n return `M${l},${t + biasY(tl, bl)}A${tl},${tl} 0 0 ${tl < 0 ? 0 : 1} ${l + biasX(tl, bl)},${t}H${r - biasX(tr, br)}A${tr},${tr} 0 0 ${tr < 0 ? 0 : 1} ${r},${t + biasY(tr, br)}V${b - biasY(br, tr)}A${br},${br} 0 0 ${br < 0 ? 0 : 1} ${r - biasX(br, tr)},${b}H${l + biasX(bl, tl)}A${bl},${bl} 0 0 ${bl < 0 ? 0 : 1} ${l},${b - biasY(bl, tl)}Z`;\n });\n}\nfunction biasX(r1, r2) {\n return r2 < 0 ? r1 : Math.abs(r1);\n}\nfunction biasY(r1, r2) {\n return r2 < 0 ? Math.abs(r1) : r1;\n}\nfunction rect(data, options) {\n return new Rect(data, maybeTrivialIntervalX(maybeTrivialIntervalY(options)));\n}\nfunction rectX(data, options = {}) {\n if (!hasXY(options)) options = { ...options, y: indexOf, x2: identity7, interval: 1 };\n return new Rect(data, maybeStackX(maybeTrivialIntervalY(maybeIdentityX(options))));\n}\nfunction rectY(data, options = {}) {\n if (!hasXY(options)) options = { ...options, x: indexOf, y2: identity7, interval: 1 };\n return new Rect(data, maybeStackY(maybeTrivialIntervalX(maybeIdentityY(options))));\n}\n\n// ../../node_modules/@observablehq/plot/src/marks/frame.js\nvar defaults5 = {\n ariaLabel: \"frame\",\n fill: \"none\",\n stroke: \"currentColor\",\n clip: false\n};\nvar lineDefaults = {\n ariaLabel: \"frame\",\n fill: null,\n stroke: \"currentColor\",\n strokeLinecap: \"square\",\n clip: false\n};\nvar Frame = class extends Mark {\n constructor(options = {}) {\n const { anchor = null } = options;\n super(singleton, void 0, options, anchor == null ? defaults5 : lineDefaults);\n this.anchor = maybeKeyword(anchor, \"anchor\", [\"top\", \"right\", \"bottom\", \"left\"]);\n rectInsets(this, options);\n if (!anchor) rectRadii(this, options);\n }\n render(index2, scales2, channels, dimensions, context) {\n const { marginTop: marginTop2, marginRight: marginRight2, marginBottom: marginBottom2, marginLeft: marginLeft2, width: width2, height: height2 } = dimensions;\n const { anchor, insetTop, insetRight, insetBottom, insetLeft } = this;\n const { rx, ry, rx1y1, rx1y2, rx2y1, rx2y2 } = this;\n const x12 = marginLeft2 + insetLeft;\n const x22 = width2 - marginRight2 - insetRight;\n const y12 = marginTop2 + insetTop;\n const y22 = height2 - marginBottom2 - insetBottom;\n return create4(anchor ? \"svg:line\" : rx1y1 || rx1y2 || rx2y1 || rx2y2 ? \"svg:path\" : \"svg:rect\", context).datum(0).call(applyIndirectStyles, this, dimensions, context).call(applyDirectStyles, this).call(applyChannelStyles, this, channels).call(applyTransform, this, {}).call(\n anchor === \"left\" ? (line3) => line3.attr(\"x1\", x12).attr(\"x2\", x12).attr(\"y1\", y12).attr(\"y2\", y22) : anchor === \"right\" ? (line3) => line3.attr(\"x1\", x22).attr(\"x2\", x22).attr(\"y1\", y12).attr(\"y2\", y22) : anchor === \"top\" ? (line3) => line3.attr(\"x1\", x12).attr(\"x2\", x22).attr(\"y1\", y12).attr(\"y2\", y12) : anchor === \"bottom\" ? (line3) => line3.attr(\"x1\", x12).attr(\"x2\", x22).attr(\"y1\", y22).attr(\"y2\", y22) : rx1y1 || rx1y2 || rx2y1 || rx2y2 ? (path2) => path2.call(applyRoundedRect, x12, y12, x22, y22, this) : (rect3) => rect3.attr(\"x\", x12).attr(\"y\", y12).attr(\"width\", x22 - x12).attr(\"height\", y22 - y12).attr(\"rx\", rx).attr(\"ry\", ry)\n ).node();\n }\n};\nfunction frame2(options) {\n return new Frame(options);\n}\n\n// ../../node_modules/@observablehq/plot/src/marks/tip.js\nvar defaults6 = {\n ariaLabel: \"tip\",\n fill: \"var(--plot-background)\",\n stroke: \"currentColor\"\n};\nvar ignoreChannels = /* @__PURE__ */ new Set([\"geometry\", \"href\", \"src\", \"ariaLabel\", \"scales\"]);\nvar Tip = class extends Mark {\n constructor(data, options = {}) {\n if (options.tip) options = { ...options, tip: false };\n if (options.title === void 0 && isIterable(data) && isTextual(data)) options = { ...options, title: identity7 };\n const {\n x: x3,\n y: y3,\n x1: x12,\n x2: x22,\n y1: y12,\n y2: y22,\n anchor,\n preferredAnchor = \"bottom\",\n monospace,\n fontFamily = monospace ? \"ui-monospace, monospace\" : void 0,\n fontSize,\n fontStyle,\n fontVariant,\n fontWeight,\n lineHeight = 1,\n lineWidth = 20,\n frameAnchor,\n format: format3,\n textAnchor = \"start\",\n textOverflow,\n textPadding = 8,\n title,\n pointerSize = 12,\n pathFilter = \"drop-shadow(0 3px 4px rgba(0,0,0,0.2))\"\n } = options;\n super(\n data,\n {\n x: { value: x12 != null && x22 != null ? null : x3, scale: \"x\", optional: true },\n // ignore midpoint\n y: { value: y12 != null && y22 != null ? null : y3, scale: \"y\", optional: true },\n // ignore midpoint\n x1: { value: x12, scale: \"x\", optional: x22 == null },\n y1: { value: y12, scale: \"y\", optional: y22 == null },\n x2: { value: x22, scale: \"x\", optional: x12 == null },\n y2: { value: y22, scale: \"y\", optional: y12 == null },\n title: { value: title, optional: true }\n // filter: defined\n },\n options,\n defaults6\n );\n this.anchor = maybeAnchor(anchor, \"anchor\");\n this.preferredAnchor = maybeAnchor(preferredAnchor, \"preferredAnchor\");\n this.frameAnchor = maybeFrameAnchor(frameAnchor);\n this.textAnchor = impliedString(textAnchor, \"middle\");\n this.textPadding = +textPadding;\n this.pointerSize = +pointerSize;\n this.pathFilter = string(pathFilter);\n this.lineHeight = +lineHeight;\n this.lineWidth = +lineWidth;\n this.textOverflow = maybeTextOverflow(textOverflow);\n this.monospace = !!monospace;\n this.fontFamily = string(fontFamily);\n this.fontSize = number5(fontSize);\n this.fontStyle = string(fontStyle);\n this.fontVariant = string(fontVariant);\n this.fontWeight = string(fontWeight);\n for (const key in defaults6) if (key in this.channels) this[key] = defaults6[key];\n this.splitLines = splitter2(this);\n this.clipLine = clipper(this);\n this.format = typeof format3 === \"string\" || typeof format3 === \"function\" ? { title: format3 } : { ...format3 };\n }\n render(index2, scales2, values2, dimensions, context) {\n const mark2 = this;\n const { x: x3, y: y3, fx, fy } = scales2;\n const { ownerSVGElement: svg, document: document2 } = context;\n const { anchor, monospace, lineHeight, lineWidth } = this;\n const { textPadding: r, pointerSize: m, pathFilter } = this;\n const { marginTop: marginTop2, marginLeft: marginLeft2 } = dimensions;\n const { x1: X13, y1: Y13, x2: X23, y2: Y23, x: X3 = X13 ?? X23, y: Y3 = Y13 ?? Y23 } = values2;\n const ox2 = fx ? fx(index2.fx) - marginLeft2 : 0;\n const oy2 = fy ? fy(index2.fy) - marginTop2 : 0;\n const [cx, cy] = applyFrameAnchor(this, dimensions);\n const px = anchorX(values2, cx);\n const py = anchorY(values2, cy);\n const widthof2 = monospace ? monospaceWidth : defaultWidth;\n const ee = widthof2(ellipsis);\n let sources, format3;\n if (\"title\" in values2) {\n sources = getSourceChannels.call(this, { title: values2.channels.title }, scales2);\n format3 = formatTitle;\n } else {\n sources = getSourceChannels.call(this, values2.channels, scales2);\n format3 = formatChannels;\n }\n const g = create4(\"svg:g\", context).call(applyIndirectStyles, this, dimensions, context).call(applyIndirectTextStyles, this).call(applyTransform, this, { x: X3 && x3, y: Y3 && y3 }).call(\n (g2) => g2.selectAll().data(index2).enter().append(\"g\").attr(\"transform\", (i) => `translate(${Math.round(px(i))},${Math.round(py(i))})`).call(applyDirectStyles, this).call((g3) => g3.append(\"path\").attr(\"filter\", pathFilter)).call(\n (g3) => g3.append(\"text\").each(function(i) {\n const that = select_default2(this);\n this.setAttribute(\"fill\", \"currentColor\");\n this.setAttribute(\"fill-opacity\", 1);\n this.setAttribute(\"stroke\", \"none\");\n const lines = format3.call(mark2, i, index2, sources, scales2, values2);\n if (typeof lines === \"string\") {\n for (const line3 of mark2.splitLines(lines)) {\n renderLine(that, { value: mark2.clipLine(line3) });\n }\n } else {\n const labels = /* @__PURE__ */ new Set();\n for (const line3 of lines) {\n const { label: label2 = \"\" } = line3;\n if (label2 && labels.has(label2)) continue;\n else labels.add(label2);\n renderLine(that, line3);\n }\n }\n })\n )\n );\n function renderLine(selection2, { label: label2, value, color: color3, opacity: opacity2 }) {\n label2 ??= \"\", value ??= \"\";\n const swatch = color3 != null || opacity2 != null;\n let title;\n let w = lineWidth * 100;\n const [j] = cut(label2, w, widthof2, ee);\n if (j >= 0) {\n label2 = label2.slice(0, j).trimEnd() + ellipsis;\n title = value.trim();\n value = \"\";\n } else {\n if (label2 || !value && !swatch) value = \" \" + value;\n const [k2] = cut(value, w - widthof2(label2), widthof2, ee);\n if (k2 >= 0) {\n title = value.trim();\n value = value.slice(0, k2).trimEnd() + ellipsis;\n }\n }\n const line3 = selection2.append(\"tspan\").attr(\"x\", 0).attr(\"dy\", `${lineHeight}em`).text(\"\\u200B\");\n if (label2) line3.append(\"tspan\").attr(\"font-weight\", \"bold\").text(label2);\n if (value) line3.append(() => document2.createTextNode(value));\n if (swatch) line3.append(\"tspan\").text(\" \\u25A0\").attr(\"fill\", color3).attr(\"fill-opacity\", opacity2).style(\"user-select\", \"none\");\n if (title) line3.append(\"title\").text(title);\n }\n function postrender() {\n const { width: width2, height: height2 } = dimensions.facet ?? dimensions;\n g.selectChildren().each(function(i) {\n let { x: tx, width: w, height: h } = this.getBBox();\n w = Math.round(w), h = Math.round(h);\n let a2 = anchor;\n if (a2 === void 0) {\n const x4 = px(i) + ox2;\n const y4 = py(i) + oy2;\n const fitLeft = x4 + w + m + r * 2 < width2;\n const fitRight = x4 - w - m - r * 2 > 0;\n const fitTop = y4 + h + m + r * 2 < height2;\n const fitBottom = y4 - h - m - r * 2 > 0;\n a2 = fitLeft && fitRight ? fitTop && fitBottom ? mark2.preferredAnchor : fitBottom ? \"bottom\" : \"top\" : fitTop && fitBottom ? fitLeft ? \"left\" : \"right\" : (fitLeft || fitRight) && (fitTop || fitBottom) ? `${fitBottom ? \"bottom\" : \"top\"}-${fitLeft ? \"left\" : \"right\"}` : mark2.preferredAnchor;\n }\n const path2 = this.firstChild;\n const text3 = this.lastChild;\n path2.setAttribute(\"d\", getPath(a2, m, r, w, h));\n if (tx) for (const t of text3.childNodes) t.setAttribute(\"x\", -tx);\n text3.setAttribute(\"y\", `${+getLineOffset(a2, text3.childNodes.length, lineHeight).toFixed(6)}em`);\n text3.setAttribute(\"transform\", `translate(${getTextTranslate(a2, m, r, w, h)})`);\n });\n g.attr(\"visibility\", null);\n }\n if (index2.length) {\n g.attr(\"visibility\", \"hidden\");\n if (svg.isConnected) Promise.resolve().then(postrender);\n else if (typeof requestAnimationFrame !== \"undefined\") requestAnimationFrame(postrender);\n }\n return g.node();\n }\n};\nfunction tip(data, { x: x3, y: y3, ...options } = {}) {\n if (options.frameAnchor === void 0) [x3, y3] = maybeTuple(x3, y3);\n return new Tip(data, { ...options, x: x3, y: y3 });\n}\nfunction getLineOffset(anchor, length4, lineHeight) {\n return /^top(?:-|$)/.test(anchor) ? 0.94 - lineHeight : /^bottom(?:-|$)/ ? -0.29 - length4 * lineHeight : length4 / 2 * lineHeight;\n}\nfunction getTextTranslate(anchor, m, r, width2, height2) {\n switch (anchor) {\n case \"middle\":\n return [-width2 / 2, height2 / 2];\n case \"top-left\":\n return [r, m + r];\n case \"top\":\n return [-width2 / 2, m / 2 + r];\n case \"top-right\":\n return [-width2 - r, m + r];\n case \"right\":\n return [-m / 2 - width2 - r, height2 / 2];\n case \"bottom-left\":\n return [r, -m - r];\n case \"bottom\":\n return [-width2 / 2, -m / 2 - r];\n case \"bottom-right\":\n return [-width2 - r, -m - r];\n case \"left\":\n return [r + m / 2, height2 / 2];\n }\n}\nfunction getPath(anchor, m, r, width2, height2) {\n const w = width2 + r * 2;\n const h = height2 + r * 2;\n switch (anchor) {\n case \"middle\":\n return `M${-w / 2},${-h / 2}h${w}v${h}h${-w}z`;\n case \"top-left\":\n return `M0,0l${m},${m}h${w - m}v${h}h${-w}z`;\n case \"top\":\n return `M0,0l${m / 2},${m / 2}h${(w - m) / 2}v${h}h${-w}v${-h}h${(w - m) / 2}z`;\n case \"top-right\":\n return `M0,0l${-m},${m}h${m - w}v${h}h${w}z`;\n case \"right\":\n return `M0,0l${-m / 2},${-m / 2}v${m / 2 - h / 2}h${-w}v${h}h${w}v${m / 2 - h / 2}z`;\n case \"bottom-left\":\n return `M0,0l${m},${-m}h${w - m}v${-h}h${-w}z`;\n case \"bottom\":\n return `M0,0l${m / 2},${-m / 2}h${(w - m) / 2}v${-h}h${-w}v${h}h${(w - m) / 2}z`;\n case \"bottom-right\":\n return `M0,0l${-m},${-m}h${m - w}v${-h}h${w}z`;\n case \"left\":\n return `M0,0l${m / 2},${-m / 2}v${m / 2 - h / 2}h${w}v${h}h${-w}v${m / 2 - h / 2}z`;\n }\n}\nfunction getSourceChannels(channels, scales2) {\n const sources = {};\n let format3 = this.format;\n format3 = maybeExpandPairedFormat(format3, channels, \"x\");\n format3 = maybeExpandPairedFormat(format3, channels, \"y\");\n this.format = format3;\n for (const key in format3) {\n const value = format3[key];\n if (value === null || value === false) {\n continue;\n } else if (key === \"fx\" || key === \"fy\") {\n sources[key] = true;\n } else {\n const source = getSource(channels, key);\n if (source) sources[key] = source;\n }\n }\n for (const key in channels) {\n if (key in sources || key in format3 || ignoreChannels.has(key)) continue;\n if ((key === \"x\" || key === \"y\") && channels.geometry) continue;\n const source = getSource(channels, key);\n if (source) {\n if (source.scale == null && source.defaultScale === \"color\") continue;\n sources[key] = source;\n }\n }\n if (this.facet) {\n if (scales2.fx && !(\"fx\" in format3)) sources.fx = true;\n if (scales2.fy && !(\"fy\" in format3)) sources.fy = true;\n }\n for (const key in sources) {\n const format4 = this.format[key];\n if (typeof format4 === \"string\") {\n const value = sources[key]?.value ?? scales2[key]?.domain() ?? [];\n this.format[key] = (isTemporal(value) ? utcFormat : format)(format4);\n } else if (format4 === void 0 || format4 === true) {\n const scale3 = scales2[key];\n this.format[key] = scale3?.bandwidth ? inferTickFormat(scale3, scale3.domain()) : formatDefault;\n }\n }\n return sources;\n}\nfunction maybeExpandPairedFormat(format3, channels, key) {\n if (!(key in format3)) return format3;\n const key1 = `${key}1`;\n const key2 = `${key}2`;\n if ((key1 in format3 || !(key1 in channels)) && (key2 in format3 || !(key2 in channels))) return format3;\n const entries = Object.entries(format3);\n const value = format3[key];\n entries.splice(entries.findIndex(([name2]) => name2 === key) + 1, 0, [key1, value], [key2, value]);\n return Object.fromEntries(entries);\n}\nfunction formatTitle(i, index2, { title }) {\n return this.format.title(title.value[i], i);\n}\nfunction* formatChannels(i, index2, channels, scales2, values2) {\n for (const key in channels) {\n if (key === \"fx\" || key === \"fy\") {\n yield {\n label: formatLabel(scales2, channels, key),\n value: this.format[key](index2[key], i)\n };\n continue;\n }\n if (key === \"x1\" && \"x2\" in channels) continue;\n if (key === \"y1\" && \"y2\" in channels) continue;\n const channel = channels[key];\n if (key === \"x2\" && \"x1\" in channels) {\n yield {\n label: formatPairLabel(scales2, channels, \"x\"),\n value: formatPair(this.format.x2, channels.x1, channel, i)\n };\n } else if (key === \"y2\" && \"y1\" in channels) {\n yield {\n label: formatPairLabel(scales2, channels, \"y\"),\n value: formatPair(this.format.y2, channels.y1, channel, i)\n };\n } else {\n const value = channel.value[i];\n const scale3 = channel.scale;\n if (!defined(value) && scale3 == null) continue;\n yield {\n label: formatLabel(scales2, channels, key),\n value: this.format[key](value, i),\n color: scale3 === \"color\" ? values2[key][i] : null,\n opacity: scale3 === \"opacity\" ? values2[key][i] : null\n };\n }\n }\n}\nfunction formatPair(formatValue, c1, c22, i) {\n return c22.hint?.length ? `${formatValue(c22.value[i] - c1.value[i], i)}` : `${formatValue(c1.value[i], i)}\\u2013${formatValue(c22.value[i], i)}`;\n}\nfunction formatPairLabel(scales2, channels, key) {\n const l1 = formatLabel(scales2, channels, `${key}1`, key);\n const l2 = formatLabel(scales2, channels, `${key}2`, key);\n return l1 === l2 ? l1 : `${l1}\\u2013${l2}`;\n}\nfunction formatLabel(scales2, channels, key, defaultLabel = key) {\n const channel = channels[key];\n const scale3 = scales2[channel?.scale ?? key];\n return String(scale3?.label ?? channel?.label ?? defaultLabel);\n}\n\n// ../../node_modules/@observablehq/plot/src/plot.js\nfunction plot(options = {}) {\n const { facet, style: style2, title, subtitle, caption, ariaLabel, ariaDescription } = options;\n const className = maybeClassName(options.className);\n const marks2 = options.marks === void 0 ? [] : flatMarks(options.marks);\n marks2.push(...inferTips(marks2));\n const topFacetState = maybeTopFacet(facet, options);\n const facetStateByMark = /* @__PURE__ */ new Map();\n for (const mark2 of marks2) {\n const facetState = maybeMarkFacet(mark2, topFacetState, options);\n if (facetState) facetStateByMark.set(mark2, facetState);\n }\n const channelsByScale = /* @__PURE__ */ new Map();\n if (topFacetState) addScaleChannels(channelsByScale, [topFacetState], options);\n addScaleChannels(channelsByScale, facetStateByMark, options);\n const axes = flatMarks(inferAxes(marks2, channelsByScale, options));\n for (const mark2 of axes) {\n const facetState = maybeMarkFacet(mark2, topFacetState, options);\n if (facetState) facetStateByMark.set(mark2, facetState);\n }\n marks2.unshift(...axes);\n let facets = createFacets(channelsByScale, options);\n if (facets !== void 0) {\n const topFacetsIndex = topFacetState ? facetFilter(facets, topFacetState) : void 0;\n for (const mark2 of marks2) {\n if (mark2.facet === null || mark2.facet === \"super\") continue;\n const facetState = facetStateByMark.get(mark2);\n if (facetState === void 0) continue;\n facetState.facetsIndex = mark2.fx != null || mark2.fy != null ? facetFilter(facets, facetState) : topFacetsIndex;\n }\n const nonEmpty = /* @__PURE__ */ new Set();\n for (const { facetsIndex } of facetStateByMark.values()) {\n facetsIndex?.forEach((index2, i) => {\n if (index2?.length > 0) {\n nonEmpty.add(i);\n }\n });\n }\n facets.forEach(\n 0 < nonEmpty.size && nonEmpty.size < facets.length ? (f, i) => f.empty = !nonEmpty.has(i) : (f) => f.empty = false\n );\n for (const mark2 of marks2) {\n if (mark2.facet === \"exclude\") {\n const facetState = facetStateByMark.get(mark2);\n if (facetState !== void 0) facetState.facetsIndex = facetExclude(facetState.facetsIndex);\n }\n }\n }\n for (const key of registry.keys()) {\n if (isScaleOptions(options[key]) && key !== \"fx\" && key !== \"fy\") {\n channelsByScale.set(key, []);\n }\n }\n const stateByMark = /* @__PURE__ */ new Map();\n for (const mark2 of marks2) {\n if (stateByMark.has(mark2)) throw new Error(\"duplicate mark; each mark must be unique\");\n const { facetsIndex, channels: facetChannels } = facetStateByMark.get(mark2) ?? {};\n const { data, facets: facets2, channels } = mark2.initialize(facetsIndex, facetChannels, options);\n applyScaleTransforms(channels, options);\n stateByMark.set(mark2, { data, facets: facets2, channels });\n }\n const scaleDescriptors = createScales(addScaleChannels(channelsByScale, stateByMark, options), options);\n const dimensions = createDimensions(scaleDescriptors, marks2, options);\n autoScaleRange(scaleDescriptors, dimensions);\n const scales2 = createScaleFunctions(scaleDescriptors);\n const { fx, fy } = scales2;\n const subdimensions = fx || fy ? innerDimensions(scaleDescriptors, dimensions) : dimensions;\n const superdimensions = fx || fy ? actualDimensions(scales2, dimensions) : dimensions;\n const context = createContext(options);\n const document2 = context.document;\n const svg = creator_default(\"svg\").call(document2.documentElement);\n let figure = svg;\n context.ownerSVGElement = svg;\n context.className = className;\n context.projection = createProjection(options, subdimensions);\n context.filterFacets = (data, channels) => {\n return facetFilter(facets, { channels, groups: facetGroups(data, channels) });\n };\n context.getMarkState = (mark2) => {\n const state = stateByMark.get(mark2);\n const facetState = facetStateByMark.get(mark2);\n return { ...state, channels: { ...state.channels, ...facetState?.channels } };\n };\n context.dispatchValue = (value) => {\n if (figure.value === value) return;\n figure.value = value;\n figure.dispatchEvent(new Event(\"input\", { bubbles: true }));\n };\n const newByScale = /* @__PURE__ */ new Set();\n for (const [mark2, state] of stateByMark) {\n if (mark2.initializer != null) {\n const dimensions2 = mark2.facet === \"super\" ? superdimensions : subdimensions;\n const update2 = mark2.initializer(state.data, state.facets, state.channels, scales2, dimensions2, context);\n if (update2.data !== void 0) {\n state.data = update2.data;\n }\n if (update2.facets !== void 0) {\n state.facets = update2.facets;\n }\n if (update2.channels !== void 0) {\n const { fx: fx2, fy: fy2, ...channels } = update2.channels;\n inferChannelScales(channels);\n Object.assign(state.channels, channels);\n for (const channel of Object.values(channels)) {\n const { scale: scale3 } = channel;\n if (scale3 != null && !isPosition(registry.get(scale3))) {\n applyScaleTransform(channel, options);\n newByScale.add(scale3);\n }\n }\n if (fx2 != null || fy2 != null) facetStateByMark.set(mark2, true);\n }\n }\n }\n if (newByScale.size) {\n const newChannelsByScale = /* @__PURE__ */ new Map();\n addScaleChannels(newChannelsByScale, stateByMark, options, (key) => newByScale.has(key));\n addScaleChannels(channelsByScale, stateByMark, options, (key) => newByScale.has(key));\n const newScaleDescriptors = inheritScaleLabels(createScales(newChannelsByScale, options), scaleDescriptors);\n const { scales: newExposedScales, ...newScales } = createScaleFunctions(newScaleDescriptors);\n Object.assign(scaleDescriptors, newScaleDescriptors);\n Object.assign(scales2, newScales);\n Object.assign(scales2.scales, newExposedScales);\n }\n let facetDomains, facetTranslate;\n if (facets !== void 0) {\n facetDomains = { x: fx?.domain(), y: fy?.domain() };\n facets = recreateFacets(facets, facetDomains);\n facetTranslate = facetTranslator(fx, fy, dimensions);\n }\n for (const [mark2, state] of stateByMark) {\n state.values = mark2.scale(state.channels, scales2, context);\n }\n const { width: width2, height: height2 } = dimensions;\n select_default2(svg).attr(\"class\", className).attr(\"fill\", \"currentColor\").attr(\"font-family\", \"system-ui, sans-serif\").attr(\"font-size\", 10).attr(\"text-anchor\", \"middle\").attr(\"width\", width2).attr(\"height\", height2).attr(\"viewBox\", `0 0 ${width2} ${height2}`).attr(\"aria-label\", ariaLabel).attr(\"aria-description\", ariaDescription).call(\n (svg2) => (\n // Warning: if you edit this, change defaultClassName.\n svg2.append(\"style\").text(\n `:where(.${className}) {\n --plot-background: white;\n display: block;\n height: auto;\n height: intrinsic;\n max-width: 100%;\n}\n:where(.${className} text),\n:where(.${className} tspan) {\n white-space: pre;\n}`\n )\n )\n ).call(applyInlineStyles, style2);\n for (const mark2 of marks2) {\n const { channels, values: values2, facets: indexes2 } = stateByMark.get(mark2);\n if (facets === void 0 || mark2.facet === \"super\") {\n let index2 = null;\n if (indexes2) {\n index2 = indexes2[0];\n index2 = mark2.filter(index2, channels, values2);\n if (index2.length === 0) {\n continue;\n }\n }\n const node = mark2.render(index2, scales2, values2, superdimensions, context);\n if (node == null) continue;\n svg.appendChild(node);\n } else {\n let g;\n for (const f of facets) {\n if (!(mark2.facetAnchor?.(facets, facetDomains, f) ?? !f.empty)) continue;\n let index2 = null;\n if (indexes2) {\n const faceted = facetStateByMark.has(mark2);\n index2 = indexes2[faceted ? f.i : 0];\n index2 = mark2.filter(index2, channels, values2);\n if (index2.length === 0) continue;\n if (!faceted && index2 === indexes2[0]) index2 = subarray(index2);\n index2.fx = f.x, index2.fy = f.y, index2.fi = f.i;\n }\n const node = mark2.render(index2, scales2, values2, subdimensions, context);\n if (node == null) continue;\n (g ??= select_default2(svg).append(\"g\")).append(() => node).datum(f);\n for (const name2 of [\"aria-label\", \"aria-description\", \"aria-hidden\", \"transform\"]) {\n if (node.hasAttribute(name2)) {\n g.attr(name2, node.getAttribute(name2));\n node.removeAttribute(name2);\n }\n }\n }\n g?.selectChildren().attr(\"transform\", facetTranslate);\n }\n }\n const legends = createLegends(scaleDescriptors, context, options);\n const { figure: figured = title != null || subtitle != null || caption != null || legends.length > 0 } = options;\n if (figured) {\n figure = document2.createElement(\"figure\");\n figure.className = `${className}-figure`;\n figure.style.maxWidth = \"initial\";\n if (title != null) figure.append(createTitleElement(document2, title, \"h2\"));\n if (subtitle != null) figure.append(createTitleElement(document2, subtitle, \"h3\"));\n figure.append(...legends, svg);\n if (caption != null) figure.append(createFigcaption(document2, caption));\n if (\"value\" in svg) figure.value = svg.value, delete svg.value;\n }\n figure.scale = exposeScales(scales2.scales);\n figure.legend = exposeLegends(scaleDescriptors, context, options);\n const w = consumeWarnings();\n if (w > 0) {\n select_default2(svg).append(\"text\").attr(\"x\", width2).attr(\"y\", 20).attr(\"dy\", \"-1em\").attr(\"text-anchor\", \"end\").attr(\"font-family\", \"initial\").text(\"\\u26A0\\uFE0F\").append(\"title\").text(`${w.toLocaleString(\"en-US\")} warning${w === 1 ? \"\" : \"s\"}. Please check the console.`);\n }\n return figure;\n}\nfunction createTitleElement(document2, contents, tag) {\n if (contents.ownerDocument) return contents;\n const e = document2.createElement(tag);\n e.append(contents);\n return e;\n}\nfunction createFigcaption(document2, caption) {\n const e = document2.createElement(\"figcaption\");\n e.append(caption);\n return e;\n}\nfunction flatMarks(marks2) {\n return marks2.flat(Infinity).filter((mark2) => mark2 != null).map(markify);\n}\nfunction markify(mark2) {\n return typeof mark2.render === \"function\" ? mark2 : new Render(mark2);\n}\nvar Render = class extends Mark {\n constructor(render) {\n if (typeof render !== \"function\") throw new TypeError(\"invalid mark; missing render function\");\n super();\n this.render = render;\n }\n render() {\n }\n};\nfunction applyScaleTransforms(channels, options) {\n for (const name2 in channels) applyScaleTransform(channels[name2], options);\n return channels;\n}\nfunction applyScaleTransform(channel, options) {\n const { scale: scale3, transform: t = true } = channel;\n if (scale3 == null || !t) return;\n const {\n type: type2,\n percent,\n interval: interval3,\n transform: transform3 = percent ? (x3) => x3 == null ? NaN : x3 * 100 : maybeIntervalTransform(interval3, type2)\n } = options[scale3] ?? {};\n if (transform3 == null) return;\n channel.value = map3(channel.value, transform3);\n channel.transform = false;\n}\nfunction inferChannelScales(channels) {\n for (const name2 in channels) {\n inferChannelScale(name2, channels[name2]);\n }\n}\nfunction addScaleChannels(channelsByScale, stateByMark, options, filter3 = yes) {\n for (const { channels } of stateByMark.values()) {\n for (const name2 in channels) {\n const channel = channels[name2];\n const { scale: scale3 } = channel;\n if (scale3 != null && filter3(scale3)) {\n if (scale3 === \"projection\") {\n if (!hasProjection(options)) {\n const gx = options.x?.domain === void 0;\n const gy = options.y?.domain === void 0;\n if (gx || gy) {\n const [x3, y3] = getGeometryChannels(channel);\n if (gx) addScaleChannel(channelsByScale, \"x\", x3);\n if (gy) addScaleChannel(channelsByScale, \"y\", y3);\n }\n }\n } else {\n addScaleChannel(channelsByScale, scale3, channel);\n }\n }\n }\n }\n return channelsByScale;\n}\nfunction addScaleChannel(channelsByScale, scale3, channel) {\n const scaleChannels = channelsByScale.get(scale3);\n if (scaleChannels !== void 0) scaleChannels.push(channel);\n else channelsByScale.set(scale3, [channel]);\n}\nfunction maybeTopFacet(facet, options) {\n if (facet == null) return;\n const { x: x3, y: y3 } = facet;\n if (x3 == null && y3 == null) return;\n const data = dataify(facet.data);\n if (data == null) throw new Error(\"missing facet data\");\n const channels = {};\n if (x3 != null) channels.fx = createChannel(data, { value: x3, scale: \"fx\" });\n if (y3 != null) channels.fy = createChannel(data, { value: y3, scale: \"fy\" });\n applyScaleTransforms(channels, options);\n const groups2 = facetGroups(data, channels);\n return { channels, groups: groups2, data: facet.data };\n}\nfunction maybeMarkFacet(mark2, topFacetState, options) {\n if (mark2.facet === null || mark2.facet === \"super\") return;\n const { fx, fy } = mark2;\n if (fx != null || fy != null) {\n const data2 = dataify(mark2.data ?? fx ?? fy);\n if (data2 === void 0) throw new Error(`missing facet data in ${mark2.ariaLabel}`);\n if (data2 === null) return;\n const channels2 = {};\n if (fx != null) channels2.fx = createChannel(data2, { value: fx, scale: \"fx\" });\n if (fy != null) channels2.fy = createChannel(data2, { value: fy, scale: \"fy\" });\n applyScaleTransforms(channels2, options);\n return { channels: channels2, groups: facetGroups(data2, channels2) };\n }\n if (topFacetState === void 0) return;\n const { channels, groups: groups2, data } = topFacetState;\n if (mark2.facet !== \"auto\" || mark2.data === data) return { channels, groups: groups2 };\n if (data.length > 0 && (groups2.size > 1 || groups2.size === 1 && channels.fx && channels.fy && [...groups2][0][1].size > 1) && lengthof(dataify(mark2.data)) === lengthof(data)) {\n warn(\n `Warning: the ${mark2.ariaLabel} mark appears to use faceted data, but isn\\u2019t faceted. The mark data has the same length as the facet data and the mark facet option is \"auto\", but the mark data and facet data are distinct. If this mark should be faceted, set the mark facet option to true; otherwise, suppress this warning by setting the mark facet option to false.`\n );\n }\n}\nfunction derive(mark2, options = {}) {\n return initializer({ ...options, x: null, y: null }, (data, facets, channels, scales2, dimensions, context) => {\n return context.getMarkState(mark2);\n });\n}\nfunction inferTips(marks2) {\n const tips = [];\n for (const mark2 of marks2) {\n let tipOptions = mark2.tip;\n if (tipOptions) {\n if (tipOptions === true) tipOptions = {};\n else if (typeof tipOptions === \"string\") tipOptions = { pointer: tipOptions };\n let { pointer: p, preferredAnchor: a2 } = tipOptions;\n p = /^x$/i.test(p) ? pointerX : /^y$/i.test(p) ? pointerY : pointer;\n tipOptions = p(derive(mark2, tipOptions));\n tipOptions.title = null;\n if (a2 === void 0) tipOptions.preferredAnchor = p === pointerY ? \"left\" : \"bottom\";\n const t = tip(mark2.data, tipOptions);\n t.facet = mark2.facet;\n t.facetAnchor = mark2.facetAnchor;\n tips.push(t);\n }\n }\n return tips;\n}\nfunction inferAxes(marks2, channelsByScale, options) {\n let {\n projection: projection3,\n x: x3 = {},\n y: y3 = {},\n fx = {},\n fy = {},\n axis: axis3,\n grid: grid2,\n facet = {},\n facet: { axis: facetAxis = axis3, grid: facetGrid2 } = facet,\n x: { axis: xAxis2 = axis3, grid: xGrid2 = xAxis2 === null ? null : grid2 } = x3,\n y: { axis: yAxis2 = axis3, grid: yGrid2 = yAxis2 === null ? null : grid2 } = y3,\n fx: { axis: fxAxis2 = facetAxis, grid: fxGrid2 = fxAxis2 === null ? null : facetGrid2 } = fx,\n fy: { axis: fyAxis2 = facetAxis, grid: fyGrid2 = fyAxis2 === null ? null : facetGrid2 } = fy\n } = options;\n if (projection3 || !isScaleOptions(x3) && !hasPositionChannel(\"x\", marks2)) xAxis2 = xGrid2 = null;\n if (projection3 || !isScaleOptions(y3) && !hasPositionChannel(\"y\", marks2)) yAxis2 = yGrid2 = null;\n if (!channelsByScale.has(\"fx\")) fxAxis2 = fxGrid2 = null;\n if (!channelsByScale.has(\"fy\")) fyAxis2 = fyGrid2 = null;\n if (xAxis2 === void 0) xAxis2 = !hasAxis(marks2, \"x\");\n if (yAxis2 === void 0) yAxis2 = !hasAxis(marks2, \"y\");\n if (fxAxis2 === void 0) fxAxis2 = !hasAxis(marks2, \"fx\");\n if (fyAxis2 === void 0) fyAxis2 = !hasAxis(marks2, \"fy\");\n if (xAxis2 === true) xAxis2 = \"bottom\";\n if (yAxis2 === true) yAxis2 = \"left\";\n if (fxAxis2 === true) fxAxis2 = xAxis2 === \"top\" || xAxis2 === null ? \"bottom\" : \"top\";\n if (fyAxis2 === true) fyAxis2 = yAxis2 === \"right\" || yAxis2 === null ? \"left\" : \"right\";\n const axes = [];\n maybeGrid(axes, fyGrid2, gridFy, fy);\n maybeAxis(axes, fyAxis2, axisFy, \"right\", \"left\", facet, fy);\n maybeGrid(axes, fxGrid2, gridFx, fx);\n maybeAxis(axes, fxAxis2, axisFx, \"top\", \"bottom\", facet, fx);\n maybeGrid(axes, yGrid2, gridY, y3);\n maybeAxis(axes, yAxis2, axisY, \"left\", \"right\", options, y3);\n maybeGrid(axes, xGrid2, gridX, x3);\n maybeAxis(axes, xAxis2, axisX, \"bottom\", \"top\", options, x3);\n return axes;\n}\nfunction maybeAxis(axes, axis3, axisType, primary, secondary, defaults22, options) {\n if (!axis3) return;\n const both = isBoth(axis3);\n options = axisOptions(both ? primary : axis3, defaults22, options);\n const { line: line3 } = options;\n if ((axisType === axisY || axisType === axisX) && line3 && !isNone(line3)) axes.push(frame2(lineOptions(options)));\n axes.push(axisType(options));\n if (both) axes.push(axisType({ ...options, anchor: secondary, label: null }));\n}\nfunction maybeGrid(axes, grid2, gridType, options) {\n if (!grid2 || isNone(grid2)) return;\n axes.push(gridType(gridOptions(grid2, options)));\n}\nfunction isBoth(value) {\n return /^\\s*both\\s*$/i.test(value);\n}\nfunction axisOptions(anchor, defaults22, {\n line: line3 = defaults22.line,\n ticks: ticks2,\n tickSize,\n tickSpacing,\n tickPadding,\n tickFormat: tickFormat2,\n tickRotate,\n fontVariant,\n ariaLabel,\n ariaDescription,\n label: label2 = defaults22.label,\n labelAnchor,\n labelArrow = defaults22.labelArrow,\n labelOffset\n}) {\n return {\n anchor,\n line: line3,\n ticks: ticks2,\n tickSize,\n tickSpacing,\n tickPadding,\n tickFormat: tickFormat2,\n tickRotate,\n fontVariant,\n ariaLabel,\n ariaDescription,\n label: label2,\n labelAnchor,\n labelArrow,\n labelOffset\n };\n}\nfunction lineOptions(options) {\n const { anchor, line: line3 } = options;\n return { anchor, facetAnchor: anchor + \"-empty\", stroke: line3 === true ? void 0 : line3 };\n}\nfunction gridOptions(grid2, {\n stroke = isColor(grid2) ? grid2 : void 0,\n ticks: ticks2 = isGridTicks(grid2) ? grid2 : void 0,\n tickSpacing,\n ariaLabel,\n ariaDescription\n}) {\n return {\n stroke,\n ticks: ticks2,\n tickSpacing,\n ariaLabel,\n ariaDescription\n };\n}\nfunction isGridTicks(grid2) {\n switch (typeof grid2) {\n case \"number\":\n return true;\n case \"string\":\n return !isColor(grid2);\n }\n return isIterable(grid2) || typeof grid2?.range === \"function\";\n}\nfunction hasAxis(marks2, k2) {\n const prefix2 = `${k2}-axis `;\n return marks2.some((m) => m.ariaLabel?.startsWith(prefix2));\n}\nfunction hasPositionChannel(k2, marks2) {\n for (const mark2 of marks2) {\n for (const key in mark2.channels) {\n const { scale: scale3 } = mark2.channels[key];\n if (scale3 === k2 || scale3 === \"projection\") {\n return true;\n }\n }\n }\n return false;\n}\nfunction inheritScaleLabels(newScales, scales2) {\n for (const key in newScales) {\n const newScale = newScales[key];\n const scale3 = scales2[key];\n if (newScale.label === void 0 && scale3) {\n newScale.label = scale3.label;\n }\n }\n return newScales;\n}\nfunction actualDimensions({ fx, fy }, dimensions) {\n const { marginTop: marginTop2, marginRight: marginRight2, marginBottom: marginBottom2, marginLeft: marginLeft2, width: width2, height: height2 } = outerDimensions(dimensions);\n const fxr = fx && outerRange(fx);\n const fyr = fy && outerRange(fy);\n return {\n marginTop: fy ? fyr[0] : marginTop2,\n marginRight: fx ? width2 - fxr[1] : marginRight2,\n marginBottom: fy ? height2 - fyr[1] : marginBottom2,\n marginLeft: fx ? fxr[0] : marginLeft2,\n // Some marks, namely the x- and y-axis labels, want to know what the\n // desired (rather than actual) margins are for positioning.\n inset: {\n marginTop: dimensions.marginTop,\n marginRight: dimensions.marginRight,\n marginBottom: dimensions.marginBottom,\n marginLeft: dimensions.marginLeft\n },\n width: width2,\n height: height2\n };\n}\nfunction outerRange(scale3) {\n const domain = scale3.domain();\n if (domain.length === 0) return [0, scale3.bandwidth()];\n let x12 = scale3(domain[0]);\n let x22 = scale3(domain[domain.length - 1]);\n if (x22 < x12) [x12, x22] = [x22, x12];\n return [x12, x22 + scale3.bandwidth()];\n}\n\n// ../../node_modules/@observablehq/plot/src/curve.js\nvar curves = /* @__PURE__ */ new Map([\n [\"basis\", basis_default2],\n [\"basis-closed\", basisClosed_default2],\n [\"basis-open\", basisOpen_default],\n [\"bundle\", bundle_default],\n [\"bump-x\", bumpX],\n [\"bump-y\", bumpY],\n [\"cardinal\", cardinal_default],\n [\"cardinal-closed\", cardinalClosed_default],\n [\"cardinal-open\", cardinalOpen_default],\n [\"catmull-rom\", catmullRom_default],\n [\"catmull-rom-closed\", catmullRomClosed_default],\n [\"catmull-rom-open\", catmullRomOpen_default],\n [\"linear\", linear_default],\n [\"linear-closed\", linearClosed_default],\n [\"monotone-x\", monotoneX],\n [\"monotone-y\", monotoneY],\n [\"natural\", natural_default],\n [\"step\", step_default],\n [\"step-after\", stepAfter],\n [\"step-before\", stepBefore]\n]);\nfunction maybeCurve(curve = linear_default, tension) {\n if (typeof curve === \"function\") return curve;\n const c4 = curves.get(`${curve}`.toLowerCase());\n if (!c4) throw new Error(`unknown curve: ${curve}`);\n if (tension !== void 0) {\n if (\"beta\" in c4) {\n return c4.beta(tension);\n } else if (\"tension\" in c4) {\n return c4.tension(tension);\n } else if (\"alpha\" in c4) {\n return c4.alpha(tension);\n }\n }\n return c4;\n}\nfunction maybeCurveAuto(curve = curveAuto, tension) {\n return typeof curve !== \"function\" && `${curve}`.toLowerCase() === \"auto\" ? curveAuto : maybeCurve(curve, tension);\n}\nfunction curveAuto(context) {\n return linear_default(context);\n}\n\n// ../../node_modules/@observablehq/plot/src/transforms/bin.js\nfunction binX(outputs = { y: \"count\" }, options = {}) {\n [outputs, options] = mergeOptions2(outputs, options);\n const { x: x3, y: y3 } = options;\n return binn(maybeBinValue(x3, options, identity7), null, null, y3, outputs, maybeInsetX(options));\n}\nfunction binY(outputs = { x: \"count\" }, options = {}) {\n [outputs, options] = mergeOptions2(outputs, options);\n const { x: x3, y: y3 } = options;\n return binn(null, maybeBinValue(y3, options, identity7), x3, null, outputs, maybeInsetY(options));\n}\nfunction bin(outputs = { fill: \"count\" }, options = {}) {\n [outputs, options] = mergeOptions2(outputs, options);\n const { x: x3, y: y3 } = maybeBinValueTuple(options);\n return binn(x3, y3, null, null, outputs, maybeInsetX(maybeInsetY(options)));\n}\nfunction maybeDenseInterval(bin3, k2, options = {}) {\n if (options?.interval == null) return options;\n const { reduce = reduceFirst } = options;\n const outputs = { filter: null };\n if (options[k2] != null) outputs[k2] = reduce;\n if (options[`${k2}1`] != null) outputs[`${k2}1`] = reduce;\n if (options[`${k2}2`] != null) outputs[`${k2}2`] = reduce;\n return bin3(outputs, options);\n}\nfunction maybeDenseIntervalX(options = {}) {\n return maybeDenseInterval(binX, \"y\", withTip(options, \"x\"));\n}\nfunction maybeDenseIntervalY(options = {}) {\n return maybeDenseInterval(binY, \"x\", withTip(options, \"y\"));\n}\nfunction binn(bx, by, gx, gy, {\n data: reduceData = reduceIdentity,\n // TODO avoid materializing when unused?\n filter: filter3 = reduceCount,\n // return only non-empty bins by default\n sort: sort3,\n reverse: reverse3,\n ...outputs\n // output channel definitions\n} = {}, inputs = {}) {\n bx = maybeBin(bx);\n by = maybeBin(by);\n outputs = maybeBinOutputs(outputs, inputs);\n reduceData = maybeBinReduce(reduceData, identity7);\n sort3 = sort3 == null ? void 0 : maybeBinOutput(\"sort\", sort3, inputs);\n filter3 = filter3 == null ? void 0 : maybeBinEvaluator(\"filter\", filter3, inputs);\n if (gx != null && hasOutput(outputs, \"x\", \"x1\", \"x2\")) gx = null;\n if (gy != null && hasOutput(outputs, \"y\", \"y1\", \"y2\")) gy = null;\n const [BX1, setBX1] = maybeColumn(bx);\n const [BX2, setBX2] = maybeColumn(bx);\n const [BY1, setBY1] = maybeColumn(by);\n const [BY2, setBY2] = maybeColumn(by);\n const [k2, gk] = gx != null ? [gx, \"x\"] : gy != null ? [gy, \"y\"] : [];\n const [GK, setGK] = maybeColumn(k2);\n const {\n x: x3,\n y: y3,\n z,\n fill,\n stroke,\n x1: x12,\n x2: x22,\n // consumed if x is an output\n y1: y12,\n y2: y22,\n // consumed if y is an output\n domain,\n cumulative,\n thresholds,\n interval: interval3,\n ...options\n } = inputs;\n const [GZ, setGZ] = maybeColumn(z);\n const [vfill] = maybeColorChannel(fill);\n const [vstroke] = maybeColorChannel(stroke);\n const [GF, setGF] = maybeColumn(vfill);\n const [GS, setGS] = maybeColumn(vstroke);\n return {\n ...\"z\" in inputs && { z: GZ || z },\n ...\"fill\" in inputs && { fill: GF || fill },\n ...\"stroke\" in inputs && { stroke: GS || stroke },\n ...basic(options, (data, facets, plotOptions) => {\n const K2 = maybeApplyInterval(valueof(data, k2), plotOptions?.[gk]);\n const Z = valueof(data, z);\n const F = valueof(data, vfill);\n const S = valueof(data, vstroke);\n const G = maybeSubgroup(outputs, { z: Z, fill: F, stroke: S });\n const groupFacets = [];\n const groupData = [];\n const GK2 = K2 && setGK([]);\n const GZ2 = Z && setGZ([]);\n const GF2 = F && setGF([]);\n const GS2 = S && setGS([]);\n const BX12 = bx && setBX1([]);\n const BX22 = bx && setBX2([]);\n const BY12 = by && setBY1([]);\n const BY22 = by && setBY2([]);\n const bin3 = bing(bx, by, data);\n let i = 0;\n for (const o of outputs) o.initialize(data);\n if (sort3) sort3.initialize(data);\n if (filter3) filter3.initialize(data);\n for (const facet of facets) {\n const groupFacet = [];\n for (const o of outputs) o.scope(\"facet\", facet);\n if (sort3) sort3.scope(\"facet\", facet);\n if (filter3) filter3.scope(\"facet\", facet);\n for (const [f, I] of maybeGroup(facet, G)) {\n for (const [k3, g] of maybeGroup(I, K2)) {\n for (const [b, extent4] of bin3(g)) {\n if (G) extent4.z = f;\n if (filter3 && !filter3.reduce(b, extent4)) continue;\n groupFacet.push(i++);\n groupData.push(reduceData.reduceIndex(b, data, extent4));\n if (K2) GK2.push(k3);\n if (Z) GZ2.push(G === Z ? f : Z[(b.length > 0 ? b : g)[0]]);\n if (F) GF2.push(G === F ? f : F[(b.length > 0 ? b : g)[0]]);\n if (S) GS2.push(G === S ? f : S[(b.length > 0 ? b : g)[0]]);\n if (BX12) BX12.push(extent4.x1), BX22.push(extent4.x2);\n if (BY12) BY12.push(extent4.y1), BY22.push(extent4.y2);\n for (const o of outputs) o.reduce(b, extent4);\n if (sort3) sort3.reduce(b, extent4);\n }\n }\n }\n groupFacets.push(groupFacet);\n }\n maybeSort(groupFacets, sort3, reverse3);\n return { data: groupData, facets: groupFacets };\n }),\n ...!hasOutput(outputs, \"x\") && (BX1 ? { x1: BX1, x2: BX2, x: mid(BX1, BX2) } : { x: x3, x1: x12, x2: x22 }),\n ...!hasOutput(outputs, \"y\") && (BY1 ? { y1: BY1, y2: BY2, y: mid(BY1, BY2) } : { y: y3, y1: y12, y2: y22 }),\n ...GK && { [gk]: GK },\n ...Object.fromEntries(outputs.map(({ name: name2, output }) => [name2, output]))\n };\n}\nfunction mergeOptions2({ cumulative, domain, thresholds, interval: interval3, ...outputs }, options) {\n return [outputs, { cumulative, domain, thresholds, interval: interval3, ...options }];\n}\nfunction maybeBinValue(value, { cumulative, domain, thresholds, interval: interval3 }, defaultValue) {\n value = { ...maybeValue(value) };\n if (value.domain === void 0) value.domain = domain;\n if (value.cumulative === void 0) value.cumulative = cumulative;\n if (value.thresholds === void 0) value.thresholds = thresholds;\n if (value.interval === void 0) value.interval = interval3;\n if (value.value === void 0) value.value = defaultValue;\n value.thresholds = maybeThresholds(value.thresholds, value.interval);\n return value;\n}\nfunction maybeBinValueTuple(options) {\n let { x: x3, y: y3 } = options;\n x3 = maybeBinValue(x3, options);\n y3 = maybeBinValue(y3, options);\n [x3.value, y3.value] = maybeTuple(x3.value, y3.value);\n return { x: x3, y: y3 };\n}\nfunction maybeBin(options) {\n if (options == null) return;\n const { value, cumulative, domain = extent, thresholds } = options;\n const bin3 = (data) => {\n let V = valueof(data, value);\n let T;\n if (isTemporal(V) || isTimeThresholds(thresholds)) {\n V = map3(V, coerceDate, Float64Array);\n let [min5, max4] = typeof domain === \"function\" ? domain(V) : domain;\n let t = typeof thresholds === \"function\" && !isInterval(thresholds) ? thresholds(V, min5, max4) : thresholds;\n if (typeof t === \"number\") t = utcTickInterval(min5, max4, t);\n if (isInterval(t)) {\n if (domain === extent) {\n min5 = t.floor(min5);\n max4 = t.offset(t.floor(max4));\n }\n t = t.range(min5, t.offset(max4));\n }\n T = t;\n } else {\n V = coerceNumbers(V);\n let [min5, max4] = typeof domain === \"function\" ? domain(V) : domain;\n let t = typeof thresholds === \"function\" && !isInterval(thresholds) ? thresholds(V, min5, max4) : thresholds;\n if (typeof t === \"number\") {\n if (domain === extent) {\n let step = tickIncrement(min5, max4, t);\n if (isFinite(step)) {\n if (step > 0) {\n let r0 = Math.round(min5 / step);\n let r1 = Math.round(max4 / step);\n if (!(r0 * step <= min5)) --r0;\n if (!(r1 * step > max4)) ++r1;\n let n = r1 - r0 + 1;\n t = new Float64Array(n);\n for (let i = 0; i < n; ++i) t[i] = (r0 + i) * step;\n } else if (step < 0) {\n step = -step;\n let r0 = Math.round(min5 * step);\n let r1 = Math.round(max4 * step);\n if (!(r0 / step <= min5)) --r0;\n if (!(r1 / step > max4)) ++r1;\n let n = r1 - r0 + 1;\n t = new Float64Array(n);\n for (let i = 0; i < n; ++i) t[i] = (r0 + i) / step;\n } else {\n t = [min5];\n }\n } else {\n t = [min5];\n }\n } else {\n t = ticks(min5, max4, t);\n }\n } else if (isInterval(t)) {\n if (domain === extent) {\n min5 = t.floor(min5);\n max4 = t.offset(t.floor(max4));\n }\n t = t.range(min5, t.offset(max4));\n }\n T = t;\n }\n const E2 = [];\n if (T.length === 1) E2.push([T[0], T[0]]);\n else for (let i = 1; i < T.length; ++i) E2.push([T[i - 1], T[i]]);\n E2.bin = (cumulative < 0 ? bin1cn : cumulative > 0 ? bin1cp : bin1)(E2, T, V);\n return E2;\n };\n bin3.label = labelof(value);\n return bin3;\n}\nfunction maybeThresholds(thresholds, interval3, defaultThresholds = thresholdAuto) {\n if (thresholds === void 0) {\n return interval3 === void 0 ? defaultThresholds : maybeRangeInterval(interval3);\n }\n if (typeof thresholds === \"string\") {\n switch (thresholds.toLowerCase()) {\n case \"freedman-diaconis\":\n return thresholdFreedmanDiaconis;\n case \"scott\":\n return thresholdScott;\n case \"sturges\":\n return thresholdSturges;\n case \"auto\":\n return thresholdAuto;\n }\n return utcInterval(thresholds);\n }\n return thresholds;\n}\nfunction maybeBinOutputs(outputs, inputs) {\n return maybeOutputs(outputs, inputs, maybeBinOutput);\n}\nfunction maybeBinOutput(name2, reduce, inputs) {\n return maybeOutput(name2, reduce, inputs, maybeBinEvaluator);\n}\nfunction maybeBinEvaluator(name2, reduce, inputs) {\n return maybeEvaluator(name2, reduce, inputs, maybeBinReduce);\n}\nfunction maybeBinReduce(reduce, value) {\n return maybeReduce(reduce, value, maybeBinReduceFallback);\n}\nfunction maybeBinReduceFallback(reduce) {\n switch (`${reduce}`.toLowerCase()) {\n case \"x\":\n return reduceX2;\n case \"x1\":\n return reduceX1;\n case \"x2\":\n return reduceX22;\n case \"y\":\n return reduceY2;\n case \"y1\":\n return reduceY1;\n case \"y2\":\n return reduceY22;\n case \"z\":\n return reduceZ;\n }\n throw new Error(`invalid bin reduce: ${reduce}`);\n}\nfunction thresholdAuto(values2, min5, max4) {\n return Math.min(200, thresholdScott(values2, min5, max4));\n}\nfunction isTimeThresholds(t) {\n return isTimeInterval(t) || isIterable(t) && isTemporal(t);\n}\nfunction bing(bx, by, data) {\n const EX = bx?.(data);\n const EY = by?.(data);\n return EX && EY ? function* (I) {\n const X3 = EX.bin(I);\n for (const [ix, [x12, x22]] of EX.entries()) {\n const Y3 = EY.bin(X3[ix]);\n for (const [iy, [y12, y22]] of EY.entries()) {\n yield [Y3[iy], { data, x1: x12, y1: y12, x2: x22, y2: y22 }];\n }\n }\n } : EX ? function* (I) {\n const X3 = EX.bin(I);\n for (const [i, [x12, x22]] of EX.entries()) {\n yield [X3[i], { data, x1: x12, x2: x22 }];\n }\n } : function* (I) {\n const Y3 = EY.bin(I);\n for (const [i, [y12, y22]] of EY.entries()) {\n yield [Y3[i], { data, y1: y12, y2: y22 }];\n }\n };\n}\nfunction bin1(E2, T, V) {\n T = coerceNumbers(T);\n return (I) => {\n const B3 = E2.map(() => []);\n for (const i of I) B3[bisect_default(T, V[i]) - 1]?.push(i);\n return B3;\n };\n}\nfunction bin1cp(E2, T, V) {\n const bin3 = bin1(E2, T, V);\n return (I) => {\n const B3 = bin3(I);\n for (let i = 1, n = B3.length; i < n; ++i) {\n const C3 = B3[i - 1];\n const b = B3[i];\n for (const j of C3) b.push(j);\n }\n return B3;\n };\n}\nfunction bin1cn(E2, T, V) {\n const bin3 = bin1(E2, T, V);\n return (I) => {\n const B3 = bin3(I);\n for (let i = B3.length - 2; i >= 0; --i) {\n const C3 = B3[i + 1];\n const b = B3[i];\n for (const j of C3) b.push(j);\n }\n return B3;\n };\n}\nfunction mid1(x12, x22) {\n const m = (+x12 + +x22) / 2;\n return x12 instanceof Date ? new Date(m) : m;\n}\nvar reduceX2 = {\n reduceIndex(I, X3, { x1: x12, x2: x22 }) {\n return mid1(x12, x22);\n }\n};\nvar reduceY2 = {\n reduceIndex(I, X3, { y1: y12, y2: y22 }) {\n return mid1(y12, y22);\n }\n};\nvar reduceX1 = {\n reduceIndex(I, X3, { x1: x12 }) {\n return x12;\n }\n};\nvar reduceX22 = {\n reduceIndex(I, X3, { x2: x22 }) {\n return x22;\n }\n};\nvar reduceY1 = {\n reduceIndex(I, X3, { y1: y12 }) {\n return y12;\n }\n};\nvar reduceY22 = {\n reduceIndex(I, X3, { y2: y22 }) {\n return y22;\n }\n};\n\n// ../../node_modules/@observablehq/plot/src/marks/area.js\nvar defaults7 = {\n ariaLabel: \"area\",\n strokeWidth: 1,\n strokeLinecap: \"round\",\n strokeLinejoin: \"round\",\n strokeMiterlimit: 1\n};\nvar Area = class extends Mark {\n constructor(data, options = {}) {\n const { x1: x12, y1: y12, x2: x22, y2: y22, z, curve, tension } = options;\n super(\n data,\n {\n x1: { value: x12, scale: \"x\" },\n y1: { value: y12, scale: \"y\" },\n x2: { value: x22, scale: \"x\", optional: true },\n y2: { value: y22, scale: \"y\", optional: true },\n z: { value: maybeZ(options), optional: true }\n },\n options,\n defaults7\n );\n this.z = z;\n this.curve = maybeCurve(curve, tension);\n }\n filter(index2) {\n return index2;\n }\n render(index2, scales2, channels, dimensions, context) {\n const { x1: X13, y1: Y13, x2: X23 = X13, y2: Y23 = Y13 } = channels;\n return create4(\"svg:g\", context).call(applyIndirectStyles, this, dimensions, context).call(applyTransform, this, scales2, 0, 0).call(\n (g) => g.selectAll().data(groupIndex(index2, [X13, Y13, X23, Y23], this, channels)).enter().append(\"path\").call(applyDirectStyles, this).call(applyGroupedChannelStyles, this, channels).attr(\n \"d\",\n area_default3().curve(this.curve).defined((i) => i >= 0).x0((i) => X13[i]).y0((i) => Y13[i]).x1((i) => X23[i]).y1((i) => Y23[i])\n )\n ).node();\n }\n};\nfunction area(data, options) {\n if (options === void 0) return areaY(data, { x: first2, y: second2 });\n return new Area(data, options);\n}\nfunction areaX(data, options) {\n const { y: y3 = indexOf, ...rest } = maybeDenseIntervalY(options);\n return new Area(data, maybeStackX(maybeIdentityX({ ...rest, y1: y3, y2: void 0 })));\n}\nfunction areaY(data, options) {\n const { x: x3 = indexOf, ...rest } = maybeDenseIntervalX(options);\n return new Area(data, maybeStackY(maybeIdentityY({ ...rest, x1: x3, x2: void 0 })));\n}\n\n// ../../node_modules/@observablehq/plot/src/marks/link.js\nvar defaults8 = {\n ariaLabel: \"link\",\n fill: \"none\",\n stroke: \"currentColor\",\n strokeMiterlimit: 1\n};\nvar Link = class extends Mark {\n constructor(data, options = {}) {\n const { x1: x12, y1: y12, x2: x22, y2: y22, curve, tension } = options;\n super(\n data,\n {\n x1: { value: x12, scale: \"x\" },\n y1: { value: y12, scale: \"y\" },\n x2: { value: x22, scale: \"x\", optional: true },\n y2: { value: y22, scale: \"y\", optional: true }\n },\n options,\n defaults8\n );\n this.curve = maybeCurveAuto(curve, tension);\n markers(this, options);\n }\n project(channels, values2, context) {\n if (this.curve !== curveAuto) {\n super.project(channels, values2, context);\n }\n }\n render(index2, scales2, channels, dimensions, context) {\n const { x1: X13, y1: Y13, x2: X23 = X13, y2: Y23 = Y13 } = channels;\n const { curve } = this;\n return create4(\"svg:g\", context).call(applyIndirectStyles, this, dimensions, context).call(applyTransform, this, scales2).call(\n (g) => g.selectAll().data(index2).enter().append(\"path\").call(applyDirectStyles, this).attr(\n \"d\",\n curve === curveAuto && context.projection ? sphereLink(context.projection, X13, Y13, X23, Y23) : (i) => {\n const p = pathRound();\n const c4 = curve(p);\n c4.lineStart();\n c4.point(X13[i], Y13[i]);\n c4.point(X23[i], Y23[i]);\n c4.lineEnd();\n return p;\n }\n ).call(applyChannelStyles, this, channels).call(applyMarkers, this, channels, context)\n ).node();\n }\n};\nfunction sphereLink(projection3, X13, Y13, X23, Y23) {\n const path2 = path_default(projection3);\n X13 = coerceNumbers(X13);\n Y13 = coerceNumbers(Y13);\n X23 = coerceNumbers(X23);\n Y23 = coerceNumbers(Y23);\n return (i) => path2({\n type: \"LineString\",\n coordinates: [\n [X13[i], Y13[i]],\n [X23[i], Y23[i]]\n ]\n });\n}\nfunction link2(data, { x: x3, x1: x12, x2: x22, y: y3, y1: y12, y2: y22, ...options } = {}) {\n [x12, x22] = maybeSameValue(x3, x12, x22);\n [y12, y22] = maybeSameValue(y3, y12, y22);\n return new Link(data, { ...options, x1: x12, x2: x22, y1: y12, y2: y22 });\n}\nfunction maybeSameValue(x3, x12, x22) {\n if (x3 === void 0) {\n if (x12 === void 0) {\n if (x22 !== void 0) return [x22];\n } else {\n if (x22 === void 0) return [x12];\n }\n } else if (x12 === void 0) {\n return x22 === void 0 ? [x3] : [x3, x22];\n } else if (x22 === void 0) {\n return [x3, x12];\n }\n return [x12, x22];\n}\n\n// ../../node_modules/@observablehq/plot/src/marks/arrow.js\nvar defaults9 = {\n ariaLabel: \"arrow\",\n fill: \"none\",\n stroke: \"currentColor\",\n strokeLinecap: \"round\",\n strokeMiterlimit: 1,\n strokeWidth: 1.5\n};\nvar Arrow = class extends Mark {\n constructor(data, options = {}) {\n const {\n x1: x12,\n y1: y12,\n x2: x22,\n y2: y22,\n bend = 0,\n headAngle = 60,\n headLength = 8,\n // Disable the arrow with headLength = 0; or, use Plot.link.\n inset: inset2 = 0,\n insetStart = inset2,\n insetEnd = inset2,\n sweep\n } = options;\n super(\n data,\n {\n x1: { value: x12, scale: \"x\" },\n y1: { value: y12, scale: \"y\" },\n x2: { value: x22, scale: \"x\", optional: true },\n y2: { value: y22, scale: \"y\", optional: true }\n },\n options,\n defaults9\n );\n this.bend = bend === true ? 22.5 : Math.max(-90, Math.min(90, bend));\n this.headAngle = +headAngle;\n this.headLength = +headLength;\n this.insetStart = +insetStart;\n this.insetEnd = +insetEnd;\n this.sweep = maybeSweep(sweep);\n }\n render(index2, scales2, channels, dimensions, context) {\n const { x1: X13, y1: Y13, x2: X23 = X13, y2: Y23 = Y13, SW } = channels;\n const { strokeWidth, bend, headAngle, headLength, insetStart, insetEnd } = this;\n const sw = SW ? (i) => SW[i] : constant(strokeWidth === void 0 ? 1 : strokeWidth);\n const wingAngle = headAngle * radians3 / 2;\n const wingScale = headLength / 1.5;\n return create4(\"svg:g\", context).call(applyIndirectStyles, this, dimensions, context).call(applyTransform, this, scales2).call(\n (g) => g.selectAll().data(index2).enter().append(\"path\").call(applyDirectStyles, this).attr(\"d\", (i) => {\n let x12 = X13[i], y12 = Y13[i], x22 = X23[i], y22 = Y23[i];\n const lineLength = Math.hypot(x22 - x12, y22 - y12);\n if (lineLength <= insetStart + insetEnd) return null;\n let lineAngle = Math.atan2(y22 - y12, x22 - x12);\n const headLength2 = Math.min(wingScale * sw(i), lineLength / 3);\n const bendAngle = this.sweep(x12, y12, x22, y22) * bend * radians3;\n const r = Math.hypot(lineLength / Math.tan(bendAngle), lineLength) / 2;\n if (insetStart || insetEnd) {\n if (r < 1e5) {\n const sign3 = Math.sign(bendAngle);\n const [cx, cy] = pointPointCenter([x12, y12], [x22, y22], r, sign3);\n if (insetStart) {\n [x12, y12] = circleCircleIntersect([cx, cy, r], [x12, y12, insetStart], -sign3 * Math.sign(insetStart));\n }\n if (insetEnd) {\n const [x5, y5] = circleCircleIntersect([cx, cy, r], [x22, y22, insetEnd], sign3 * Math.sign(insetEnd));\n lineAngle += Math.atan2(y5 - cy, x5 - cx) - Math.atan2(y22 - cy, x22 - cx);\n x22 = x5, y22 = y5;\n }\n } else {\n const dx = x22 - x12, dy = y22 - y12, d = Math.hypot(dx, dy);\n if (insetStart) x12 += dx / d * insetStart, y12 += dy / d * insetStart;\n if (insetEnd) x22 -= dx / d * insetEnd, y22 -= dy / d * insetEnd;\n }\n }\n const endAngle = lineAngle + bendAngle;\n const leftAngle = endAngle + wingAngle;\n const rightAngle = endAngle - wingAngle;\n const x3 = x22 - headLength2 * Math.cos(leftAngle);\n const y3 = y22 - headLength2 * Math.sin(leftAngle);\n const x4 = x22 - headLength2 * Math.cos(rightAngle);\n const y4 = y22 - headLength2 * Math.sin(rightAngle);\n const a2 = r < 1e5 ? `A${r},${r} 0,0,${bendAngle > 0 ? 1 : 0} ` : `L`;\n const h = headLength2 ? `M${x3},${y3}L${x22},${y22}L${x4},${y4}` : \"\";\n return `M${x12},${y12}${a2}${x22},${y22}${h}`;\n }).call(applyChannelStyles, this, channels)\n ).node();\n }\n};\nfunction maybeSweep(sweep = 1) {\n if (typeof sweep === \"number\") return constant(Math.sign(sweep));\n if (typeof sweep === \"function\") return (x12, y12, x22, y22) => Math.sign(sweep(x12, y12, x22, y22));\n switch (keyword(sweep, \"sweep\", [\"+x\", \"-x\", \"+y\", \"-y\"])) {\n case \"+x\":\n return (x12, y12, x22) => ascending(x12, x22);\n case \"-x\":\n return (x12, y12, x22) => descending(x12, x22);\n case \"+y\":\n return (x12, y12, x22, y22) => ascending(y12, y22);\n case \"-y\":\n return (x12, y12, x22, y22) => descending(y12, y22);\n }\n}\nfunction pointPointCenter([ax, ay], [bx, by], r, sign3) {\n const dx = bx - ax, dy = by - ay, d = Math.hypot(dx, dy);\n const k2 = sign3 * Math.sqrt(r * r - d * d / 4) / d;\n return [(ax + bx) / 2 - dy * k2, (ay + by) / 2 + dx * k2];\n}\nfunction circleCircleIntersect([ax, ay, ar], [bx, by, br], sign3) {\n const dx = bx - ax, dy = by - ay, d = Math.hypot(dx, dy);\n const x3 = (dx * dx + dy * dy - br * br + ar * ar) / (2 * d);\n const y3 = sign3 * Math.sqrt(ar * ar - x3 * x3);\n return [ax + (dx * x3 + dy * y3) / d, ay + (dy * x3 - dx * y3) / d];\n}\nfunction arrow(data, { x: x3, x1: x12, x2: x22, y: y3, y1: y12, y2: y22, ...options } = {}) {\n [x12, x22] = maybeSameValue(x3, x12, x22);\n [y12, y22] = maybeSameValue(y3, y12, y22);\n return new Arrow(data, { ...options, x1: x12, x2: x22, y1: y12, y2: y22 });\n}\n\n// ../../node_modules/@observablehq/plot/src/marks/bar.js\nvar barDefaults = {\n ariaLabel: \"bar\"\n};\nvar AbstractBar = class extends Mark {\n constructor(data, channels, options = {}, defaults22 = barDefaults) {\n super(data, channels, options, defaults22);\n rectInsets(this, options);\n rectRadii(this, options);\n }\n render(index2, scales2, channels, dimensions, context) {\n const { rx, ry, rx1y1, rx1y2, rx2y1, rx2y2 } = this;\n const x3 = this._x(scales2, channels, dimensions);\n const y3 = this._y(scales2, channels, dimensions);\n const w = this._width(scales2, channels, dimensions);\n const h = this._height(scales2, channels, dimensions);\n return create4(\"svg:g\", context).call(applyIndirectStyles, this, dimensions, context).call(this._transform, this, scales2).call(\n (g) => g.selectAll().data(index2).enter().call(\n rx1y1 || rx1y2 || rx2y1 || rx2y2 ? (g2) => g2.append(\"path\").call(applyDirectStyles, this).call(applyRoundedRect, x3, y3, add(x3, w), add(y3, h), this).call(applyChannelStyles, this, channels) : (g2) => g2.append(\"rect\").call(applyDirectStyles, this).attr(\"x\", x3).attr(\"width\", w).attr(\"y\", y3).attr(\"height\", h).call(applyAttr, \"rx\", rx).call(applyAttr, \"ry\", ry).call(applyChannelStyles, this, channels)\n )\n ).node();\n }\n _x(scales2, { x: X3 }, { marginLeft: marginLeft2 }) {\n const { insetLeft } = this;\n return X3 ? (i) => X3[i] + insetLeft : marginLeft2 + insetLeft;\n }\n _y(scales2, { y: Y3 }, { marginTop: marginTop2 }) {\n const { insetTop } = this;\n return Y3 ? (i) => Y3[i] + insetTop : marginTop2 + insetTop;\n }\n _width({ x: x3 }, { x: X3 }, { marginRight: marginRight2, marginLeft: marginLeft2, width: width2 }) {\n const { insetLeft, insetRight } = this;\n const bandwidth = X3 && x3 ? x3.bandwidth() : width2 - marginRight2 - marginLeft2;\n return Math.max(0, bandwidth - insetLeft - insetRight);\n }\n _height({ y: y3 }, { y: Y3 }, { marginTop: marginTop2, marginBottom: marginBottom2, height: height2 }) {\n const { insetTop, insetBottom } = this;\n const bandwidth = Y3 && y3 ? y3.bandwidth() : height2 - marginTop2 - marginBottom2;\n return Math.max(0, bandwidth - insetTop - insetBottom);\n }\n};\nfunction add(a2, b) {\n return typeof a2 === \"function\" && typeof b === \"function\" ? (i) => a2(i) + b(i) : typeof a2 === \"function\" ? (i) => a2(i) + b : typeof b === \"function\" ? (i) => a2 + b(i) : a2 + b;\n}\nvar BarX = class extends AbstractBar {\n constructor(data, options = {}, defaults22) {\n const { x1: x12, x2: x22, y: y3 } = options;\n super(\n data,\n {\n x1: { value: x12, scale: \"x\" },\n x2: { value: x22, scale: \"x\" },\n y: { value: y3, scale: \"y\", type: \"band\", optional: true }\n },\n options,\n defaults22\n );\n }\n _transform(selection2, mark2, { x: x3 }) {\n selection2.call(applyTransform, mark2, { x: x3 }, 0, 0);\n }\n _x({ x: x3 }, { x1: X13, x2: X23 }, { marginLeft: marginLeft2 }) {\n const { insetLeft } = this;\n return isCollapsed(x3) ? marginLeft2 + insetLeft : (i) => Math.min(X13[i], X23[i]) + insetLeft;\n }\n _width({ x: x3 }, { x1: X13, x2: X23 }, { marginRight: marginRight2, marginLeft: marginLeft2, width: width2 }) {\n const { insetLeft, insetRight } = this;\n return isCollapsed(x3) ? width2 - marginRight2 - marginLeft2 - insetLeft - insetRight : (i) => Math.max(0, Math.abs(X23[i] - X13[i]) - insetLeft - insetRight);\n }\n};\nvar BarY = class extends AbstractBar {\n constructor(data, options = {}, defaults22) {\n const { x: x3, y1: y12, y2: y22 } = options;\n super(\n data,\n {\n y1: { value: y12, scale: \"y\" },\n y2: { value: y22, scale: \"y\" },\n x: { value: x3, scale: \"x\", type: \"band\", optional: true }\n },\n options,\n defaults22\n );\n }\n _transform(selection2, mark2, { y: y3 }) {\n selection2.call(applyTransform, mark2, { y: y3 }, 0, 0);\n }\n _y({ y: y3 }, { y1: Y13, y2: Y23 }, { marginTop: marginTop2 }) {\n const { insetTop } = this;\n return isCollapsed(y3) ? marginTop2 + insetTop : (i) => Math.min(Y13[i], Y23[i]) + insetTop;\n }\n _height({ y: y3 }, { y1: Y13, y2: Y23 }, { marginTop: marginTop2, marginBottom: marginBottom2, height: height2 }) {\n const { insetTop, insetBottom } = this;\n return isCollapsed(y3) ? height2 - marginTop2 - marginBottom2 - insetTop - insetBottom : (i) => Math.max(0, Math.abs(Y23[i] - Y13[i]) - insetTop - insetBottom);\n }\n};\nfunction barX(data, options = {}) {\n if (!hasXY(options)) options = { ...options, y: indexOf, x2: identity7 };\n return new BarX(data, maybeStackX(maybeIntervalX(maybeIdentityX(options))));\n}\nfunction barY(data, options = {}) {\n if (!hasXY(options)) options = { ...options, x: indexOf, y2: identity7 };\n return new BarY(data, maybeStackY(maybeIntervalY(maybeIdentityY(options))));\n}\n\n// ../../node_modules/@observablehq/plot/src/marks/cell.js\nvar defaults10 = {\n ariaLabel: \"cell\"\n};\nvar Cell = class extends AbstractBar {\n constructor(data, { x: x3, y: y3, ...options } = {}) {\n super(\n data,\n {\n x: { value: x3, scale: \"x\", type: \"band\", optional: true },\n y: { value: y3, scale: \"y\", type: \"band\", optional: true }\n },\n options,\n defaults10\n );\n }\n _transform(selection2, mark2) {\n selection2.call(applyTransform, mark2, {}, 0, 0);\n }\n};\nfunction cell(data, { x: x3, y: y3, ...options } = {}) {\n [x3, y3] = maybeTuple(x3, y3);\n return new Cell(data, { ...options, x: x3, y: y3 });\n}\nfunction cellX(data, { x: x3 = indexOf, fill, stroke, ...options } = {}) {\n if (fill === void 0 && maybeColorChannel(stroke)[0] === void 0) fill = identity7;\n return new Cell(data, { ...options, x: x3, fill, stroke });\n}\nfunction cellY(data, { y: y3 = indexOf, fill, stroke, ...options } = {}) {\n if (fill === void 0 && maybeColorChannel(stroke)[0] === void 0) fill = identity7;\n return new Cell(data, { ...options, y: y3, fill, stroke });\n}\n\n// ../../node_modules/@observablehq/plot/src/marks/dot.js\nvar defaults11 = {\n ariaLabel: \"dot\",\n fill: \"none\",\n stroke: \"currentColor\",\n strokeWidth: 1.5\n};\nfunction withDefaultSort(options) {\n return options.sort === void 0 && options.reverse === void 0 ? sort2({ channel: \"-r\" }, options) : options;\n}\nvar Dot = class extends Mark {\n constructor(data, options = {}) {\n const { x: x3, y: y3, r, rotate, symbol: symbol2 = circle_default2, frameAnchor } = options;\n const [vrotate, crotate] = maybeNumberChannel(rotate, 0);\n const [vsymbol, csymbol] = maybeSymbolChannel(symbol2);\n const [vr, cr] = maybeNumberChannel(r, vsymbol == null ? 3 : 4.5);\n super(\n data,\n {\n x: { value: x3, scale: \"x\", optional: true },\n y: { value: y3, scale: \"y\", optional: true },\n r: { value: vr, scale: \"r\", filter: positive, optional: true },\n rotate: { value: vrotate, optional: true },\n symbol: { value: vsymbol, scale: \"auto\", optional: true }\n },\n withDefaultSort(options),\n defaults11\n );\n this.r = cr;\n this.rotate = crotate;\n this.symbol = csymbol;\n this.frameAnchor = maybeFrameAnchor(frameAnchor);\n const { channels } = this;\n const { symbol: symbolChannel } = channels;\n if (symbolChannel) {\n const { fill: fillChannel, stroke: strokeChannel } = channels;\n symbolChannel.hint = {\n fill: fillChannel ? fillChannel.value === symbolChannel.value ? \"color\" : \"currentColor\" : this.fill ?? \"currentColor\",\n stroke: strokeChannel ? strokeChannel.value === symbolChannel.value ? \"color\" : \"currentColor\" : this.stroke ?? \"none\"\n };\n }\n }\n render(index2, scales2, channels, dimensions, context) {\n const { x: x3, y: y3 } = scales2;\n const { x: X3, y: Y3, r: R, rotate: A5, symbol: S } = channels;\n const { r, rotate, symbol: symbol2 } = this;\n const [cx, cy] = applyFrameAnchor(this, dimensions);\n const circle3 = symbol2 === circle_default2;\n const size = R ? void 0 : r * r * Math.PI;\n if (negative(r)) index2 = [];\n return create4(\"svg:g\", context).call(applyIndirectStyles, this, dimensions, context).call(applyTransform, this, { x: X3 && x3, y: Y3 && y3 }).call(\n (g) => g.selectAll().data(index2).enter().append(circle3 ? \"circle\" : \"path\").call(applyDirectStyles, this).call(\n circle3 ? (selection2) => {\n selection2.attr(\"cx\", X3 ? (i) => X3[i] : cx).attr(\"cy\", Y3 ? (i) => Y3[i] : cy).attr(\"r\", R ? (i) => R[i] : r);\n } : (selection2) => {\n selection2.attr(\n \"transform\",\n template`translate(${X3 ? (i) => X3[i] : cx},${Y3 ? (i) => Y3[i] : cy})${A5 ? (i) => ` rotate(${A5[i]})` : rotate ? ` rotate(${rotate})` : ``}`\n ).attr(\n \"d\",\n R && S ? (i) => {\n const p = pathRound();\n S[i].draw(p, R[i] * R[i] * Math.PI);\n return p;\n } : R ? (i) => {\n const p = pathRound();\n symbol2.draw(p, R[i] * R[i] * Math.PI);\n return p;\n } : S ? (i) => {\n const p = pathRound();\n S[i].draw(p, size);\n return p;\n } : (() => {\n const p = pathRound();\n symbol2.draw(p, size);\n return p;\n })()\n );\n }\n ).call(applyChannelStyles, this, channels)\n ).node();\n }\n};\nfunction dot(data, { x: x3, y: y3, ...options } = {}) {\n if (options.frameAnchor === void 0) [x3, y3] = maybeTuple(x3, y3);\n return new Dot(data, { ...options, x: x3, y: y3 });\n}\nfunction dotX(data, { x: x3 = identity7, ...options } = {}) {\n return new Dot(data, maybeIntervalMidY({ ...options, x: x3 }));\n}\nfunction dotY(data, { y: y3 = identity7, ...options } = {}) {\n return new Dot(data, maybeIntervalMidX({ ...options, y: y3 }));\n}\nfunction circle(data, options) {\n return dot(data, { ...options, symbol: \"circle\" });\n}\nfunction hexagon(data, options) {\n return dot(data, { ...options, symbol: \"hexagon\" });\n}\n\n// ../../node_modules/@observablehq/plot/src/marks/line.js\nvar defaults12 = {\n ariaLabel: \"line\",\n fill: \"none\",\n stroke: \"currentColor\",\n strokeWidth: 1.5,\n strokeLinecap: \"round\",\n strokeLinejoin: \"round\",\n strokeMiterlimit: 1\n};\nvar Line = class extends Mark {\n constructor(data, options = {}) {\n const { x: x3, y: y3, z, curve, tension } = options;\n super(\n data,\n {\n x: { value: x3, scale: \"x\" },\n y: { value: y3, scale: \"y\" },\n z: { value: maybeZ(options), optional: true }\n },\n options,\n defaults12\n );\n this.z = z;\n this.curve = maybeCurveAuto(curve, tension);\n markers(this, options);\n }\n filter(index2) {\n return index2;\n }\n project(channels, values2, context) {\n if (this.curve !== curveAuto) {\n super.project(channels, values2, context);\n }\n }\n render(index2, scales2, channels, dimensions, context) {\n const { x: X3, y: Y3 } = channels;\n const { curve } = this;\n return create4(\"svg:g\", context).call(applyIndirectStyles, this, dimensions, context).call(applyTransform, this, scales2).call(\n (g) => g.selectAll().data(groupIndex(index2, [X3, Y3], this, channels)).enter().append(\"path\").call(applyDirectStyles, this).call(applyGroupedChannelStyles, this, channels).call(applyGroupedMarkers, this, channels, context).attr(\n \"d\",\n curve === curveAuto && context.projection ? sphereLine(context.projection, X3, Y3) : line_default2().curve(curve).defined((i) => i >= 0).x((i) => X3[i]).y((i) => Y3[i])\n )\n ).node();\n }\n};\nfunction sphereLine(projection3, X3, Y3) {\n const path2 = path_default(projection3);\n X3 = coerceNumbers(X3);\n Y3 = coerceNumbers(Y3);\n return (I) => {\n let line3 = [];\n const lines = [line3];\n for (const i of I) {\n if (i === -1) {\n line3 = [];\n lines.push(line3);\n } else {\n line3.push([X3[i], Y3[i]]);\n }\n }\n return path2({ type: \"MultiLineString\", coordinates: lines });\n };\n}\nfunction line(data, { x: x3, y: y3, ...options } = {}) {\n [x3, y3] = maybeTuple(x3, y3);\n return new Line(data, { ...options, x: x3, y: y3 });\n}\nfunction lineX(data, { x: x3 = identity7, y: y3 = indexOf, ...options } = {}) {\n return new Line(data, maybeDenseIntervalY({ ...options, x: x3, y: y3 }));\n}\nfunction lineY(data, { x: x3 = indexOf, y: y3 = identity7, ...options } = {}) {\n return new Line(data, maybeDenseIntervalX({ ...options, x: x3, y: y3 }));\n}\n\n// ../../node_modules/@observablehq/plot/src/marks/auto.js\nfunction autoSpec(data, options) {\n options = normalizeOptions(options);\n const { x: x3, y: y3, color: color3, size } = options;\n const X3 = materializeValue(data, x3);\n const Y3 = materializeValue(data, y3);\n const C3 = materializeValue(data, color3);\n const S = materializeValue(data, size);\n let {\n fx,\n fy,\n x: { value: xValue, reduce: xReduce, zero: xZero2, ...xOptions },\n y: { value: yValue, reduce: yReduce, zero: yZero2, ...yOptions },\n color: { value: colorValue, color: colorColor, reduce: colorReduce },\n size: { value: sizeValue, reduce: sizeReduce },\n // TODO constant radius?\n mark: mark2\n } = options;\n if (xReduce === void 0)\n xReduce = yReduce == null && xValue == null && sizeValue == null && yValue != null ? \"count\" : null;\n if (yReduce === void 0)\n yReduce = xReduce == null && yValue == null && sizeValue == null && xValue != null ? \"count\" : null;\n if (sizeReduce === void 0 && sizeValue == null && colorReduce == null && xReduce == null && yReduce == null && (xValue == null || isOrdinal(X3)) && (yValue == null || isOrdinal(Y3))) {\n sizeReduce = \"count\";\n }\n if (xZero2 === void 0) xZero2 = isZeroReducer(xReduce) ? true : void 0;\n if (yZero2 === void 0) yZero2 = isZeroReducer(yReduce) ? true : void 0;\n if (xValue == null && yValue == null) throw new Error(\"must specify x or y\");\n if (xReduce != null && yValue == null) throw new Error(\"reducing x requires y\");\n if (yReduce != null && xValue == null) throw new Error(\"reducing y requires x\");\n if (mark2 === void 0) {\n mark2 = sizeValue != null || sizeReduce != null ? \"dot\" : isZeroReducer(xReduce) || isZeroReducer(yReduce) || colorReduce != null ? \"bar\" : xValue != null && yValue != null ? isOrdinal(X3) || isOrdinal(Y3) || xReduce == null && yReduce == null && !isMonotonic(X3) && !isMonotonic(Y3) ? \"dot\" : \"line\" : xValue != null || yValue != null ? \"rule\" : null;\n }\n let Z;\n let colorMode;\n let markImpl;\n switch (mark2) {\n case \"dot\":\n markImpl = dot;\n colorMode = \"stroke\";\n break;\n case \"line\":\n markImpl = X3 && Y3 || xReduce != null || yReduce != null ? yZero2 || yReduce != null || X3 && isMonotonic(X3) ? lineY : xZero2 || xReduce != null || Y3 && isMonotonic(Y3) ? lineX : line : X3 ? lineX : lineY;\n colorMode = \"stroke\";\n if (isHighCardinality(C3)) Z = null;\n break;\n case \"area\":\n markImpl = !(yZero2 || yReduce != null) && (xZero2 || xReduce != null || Y3 && isMonotonic(Y3)) ? areaX : areaY;\n colorMode = \"fill\";\n if (isHighCardinality(C3)) Z = null;\n break;\n case \"rule\":\n markImpl = X3 ? ruleX : ruleY;\n colorMode = \"stroke\";\n break;\n case \"bar\":\n markImpl = xReduce != null ? isOrdinal(Y3) ? isSelectReducer(xReduce) && X3 && isOrdinal(X3) ? cell : barX : rectX : yReduce != null ? isOrdinal(X3) ? isSelectReducer(yReduce) && Y3 && isOrdinal(Y3) ? cell : barY : rectY : colorReduce != null || sizeReduce != null ? X3 && isOrdinal(X3) && Y3 && isOrdinal(Y3) ? cell : X3 && isOrdinal(X3) ? barY : Y3 && isOrdinal(Y3) ? barX : rect : X3 && isNumeric(X3) && !(Y3 && isNumeric(Y3)) ? barX : Y3 && isNumeric(Y3) && !(X3 && isNumeric(X3)) ? barY : cell;\n colorMode = \"fill\";\n break;\n default:\n throw new Error(`invalid mark: ${mark2}`);\n }\n let markOptions2 = {\n fx,\n fy,\n x: X3 ?? void 0,\n // treat null x as undefined for implicit stack\n y: Y3 ?? void 0,\n // treat null y as undefined for implicit stack\n [colorMode]: C3 ?? colorColor,\n z: Z,\n r: S ?? void 0,\n // treat null size as undefined for default constant radius\n tip: true\n };\n let transformImpl;\n let transformOptions = { [colorMode]: colorReduce ?? void 0, r: sizeReduce ?? void 0 };\n if (xReduce != null && yReduce != null) {\n throw new Error(`cannot reduce both x and y`);\n } else if (yReduce != null) {\n transformOptions.y = yReduce;\n transformImpl = isOrdinal(X3) ? groupX : binX;\n } else if (xReduce != null) {\n transformOptions.x = xReduce;\n transformImpl = isOrdinal(Y3) ? groupY : binY;\n } else if (colorReduce != null || sizeReduce != null) {\n if (X3 && Y3) {\n transformImpl = isOrdinal(X3) && isOrdinal(Y3) ? group2 : isOrdinal(X3) ? binY : isOrdinal(Y3) ? binX : bin;\n } else if (X3) {\n transformImpl = isOrdinal(X3) ? groupX : binX;\n } else if (Y3) {\n transformImpl = isOrdinal(Y3) ? groupY : binY;\n }\n }\n if (transformImpl === bin || transformImpl === binX) markOptions2.x = { value: X3, ...xOptions };\n if (transformImpl === bin || transformImpl === binY) markOptions2.y = { value: Y3, ...yOptions };\n if (xZero2 === void 0)\n xZero2 = X3 && !(transformImpl === bin || transformImpl === binX) && (markImpl === barX || markImpl === areaX || markImpl === rectX || markImpl === ruleY);\n if (yZero2 === void 0)\n yZero2 = Y3 && !(transformImpl === bin || transformImpl === binY) && (markImpl === barY || markImpl === areaY || markImpl === rectY || markImpl === ruleX);\n return {\n fx: fx ?? null,\n fy: fy ?? null,\n x: {\n value: xValue ?? null,\n reduce: xReduce ?? null,\n zero: !!xZero2,\n ...xOptions\n },\n y: {\n value: yValue ?? null,\n reduce: yReduce ?? null,\n zero: !!yZero2,\n ...yOptions\n },\n color: {\n value: colorValue ?? null,\n reduce: colorReduce ?? null,\n ...colorColor !== void 0 && { color: colorColor }\n },\n size: {\n value: sizeValue ?? null,\n reduce: sizeReduce ?? null\n },\n mark: mark2,\n markImpl: implNames[markImpl],\n markOptions: markOptions2,\n transformImpl: implNames[transformImpl],\n transformOptions,\n colorMode\n };\n}\nfunction auto(data, options) {\n const spec = autoSpec(data, options);\n const {\n fx,\n fy,\n x: { zero: xZero2 },\n y: { zero: yZero2 },\n markOptions: markOptions2,\n transformOptions,\n colorMode\n } = spec;\n const markImpl = impls[spec.markImpl];\n const transformImpl = impls[spec.transformImpl];\n const frames = fx != null || fy != null ? frame2({ strokeOpacity: 0.1 }) : null;\n const rules = [xZero2 ? ruleX([0]) : null, yZero2 ? ruleY([0]) : null];\n const mark2 = markImpl(data, transformImpl ? transformImpl(transformOptions, markOptions2) : markOptions2);\n return colorMode === \"stroke\" ? marks(frames, rules, mark2) : marks(frames, mark2, rules);\n}\nfunction isMonotonic(values2) {\n let previous;\n let previousOrder;\n for (const value of values2) {\n if (value == null) continue;\n if (previous === void 0) {\n previous = value;\n continue;\n }\n const order = Math.sign(ascending(previous, value));\n if (!order) continue;\n if (previousOrder !== void 0 && order !== previousOrder) return false;\n previous = value;\n previousOrder = order;\n }\n return true;\n}\nfunction normalizeOptions({ x: x3, y: y3, color: color3, size, fx, fy, mark: mark2 } = {}) {\n if (!isOptions(x3)) x3 = makeOptions(x3);\n if (!isOptions(y3)) y3 = makeOptions(y3);\n if (!isOptions(color3)) color3 = isColor(color3) ? { color: color3 } : makeOptions(color3);\n if (!isOptions(size)) size = makeOptions(size);\n if (isOptions(fx)) ({ value: fx } = makeOptions(fx));\n if (isOptions(fy)) ({ value: fy } = makeOptions(fy));\n if (mark2 != null) mark2 = `${mark2}`.toLowerCase();\n return { x: x3, y: y3, color: color3, size, fx, fy, mark: mark2 };\n}\nfunction materializeValue(data, options) {\n const V = valueof(data, options.value);\n if (V) V.label = labelof(options.value);\n return V;\n}\nfunction makeOptions(value) {\n return isReducer(value) ? { reduce: value } : { value };\n}\nfunction isZeroReducer(reduce) {\n return /^(?:distinct|count|sum|proportion)$/i.test(reduce);\n}\nfunction isSelectReducer(reduce) {\n return /^(?:first|last|mode)$/i.test(reduce);\n}\nfunction isReducer(reduce) {\n if (reduce == null) return false;\n if (typeof reduce.reduceIndex === \"function\") return true;\n if (typeof reduce.reduce === \"function\" && isObject(reduce)) return true;\n if (/^p\\d{2}$/i.test(reduce)) return true;\n switch (`${reduce}`.toLowerCase()) {\n case \"first\":\n case \"last\":\n case \"count\":\n case \"distinct\":\n case \"sum\":\n case \"proportion\":\n case \"proportion-facet\":\n // TODO remove me?\n case \"deviation\":\n case \"min\":\n case \"min-index\":\n // TODO remove me?\n case \"max\":\n case \"max-index\":\n // TODO remove me?\n case \"mean\":\n case \"median\":\n case \"variance\":\n case \"mode\":\n return true;\n }\n return false;\n}\nfunction isHighCardinality(value) {\n return value ? new InternSet(value).size > value.length >> 1 : false;\n}\nvar impls = {\n dot,\n line,\n lineX,\n lineY,\n areaX,\n areaY,\n ruleX,\n ruleY,\n barX,\n barY,\n rect,\n rectX,\n rectY,\n cell,\n bin,\n binX,\n binY,\n group: group2,\n groupX,\n groupY\n};\nvar implNames = Object.fromEntries(Object.entries(impls).map(([name2, impl]) => [impl, name2]));\n\n// ../../node_modules/@observablehq/plot/src/transforms/map.js\nfunction mapX(mapper, options = {}) {\n let { x: x3, x1: x12, x2: x22 } = options;\n if (x3 === void 0 && x12 === void 0 && x22 === void 0) options = { ...options, x: x3 = identity7 };\n const outputs = {};\n if (x3 != null) outputs.x = mapper;\n if (x12 != null) outputs.x1 = mapper;\n if (x22 != null) outputs.x2 = mapper;\n return map4(outputs, options);\n}\nfunction mapY(mapper, options = {}) {\n let { y: y3, y1: y12, y2: y22 } = options;\n if (y3 === void 0 && y12 === void 0 && y22 === void 0) options = { ...options, y: y3 = identity7 };\n const outputs = {};\n if (y3 != null) outputs.y = mapper;\n if (y12 != null) outputs.y1 = mapper;\n if (y22 != null) outputs.y2 = mapper;\n return map4(outputs, options);\n}\nfunction map4(outputs = {}, options = {}) {\n const z = maybeZ(options);\n const channels = Object.entries(outputs).map(([key, map5]) => {\n const input3 = maybeInput(key, options);\n if (input3 == null) throw new Error(`missing channel: ${key}`);\n const [output, setOutput] = column2(input3);\n return { key, input: input3, output, setOutput, map: maybeMap(map5) };\n });\n return {\n ...basic(options, (data, facets) => {\n const Z = valueof(data, z);\n const X3 = channels.map(({ input: input3 }) => valueof(data, input3));\n const MX = channels.map(({ setOutput }) => setOutput(new Array(data.length)));\n for (const facet of facets) {\n for (const I of Z ? group(facet, (i) => Z[i]).values() : [facet]) {\n channels.forEach(({ map: map5 }, i) => map5.mapIndex(I, X3[i], MX[i]));\n }\n }\n return { data, facets };\n }),\n ...Object.fromEntries(channels.map(({ key, output }) => [key, output]))\n };\n}\nfunction maybeMap(map5) {\n if (map5 == null) throw new Error(\"missing map\");\n if (typeof map5.mapIndex === \"function\") return map5;\n if (typeof map5.map === \"function\" && isObject(map5)) return mapMap(map5);\n if (typeof map5 === \"function\") return mapFunction(taker(map5));\n switch (`${map5}`.toLowerCase()) {\n case \"cumsum\":\n return mapCumsum;\n case \"rank\":\n return mapFunction((I, V) => rank2(I, (i) => V[i]));\n case \"quantile\":\n return mapFunction((I, V) => rankQuantile(I, (i) => V[i]));\n }\n throw new Error(`invalid map: ${map5}`);\n}\nfunction mapMap(map5) {\n console.warn(\"deprecated map interface; implement mapIndex instead.\");\n return { mapIndex: map5.map.bind(map5) };\n}\nfunction rankQuantile(I, f) {\n const n = count2(I, f) - 1;\n return rank2(I, f).map((r) => r / n);\n}\nfunction mapFunction(f) {\n return {\n mapIndex(I, S, T) {\n const M2 = f(I, S);\n if (M2.length !== I.length) throw new Error(\"map function returned a mismatched length\");\n for (let i = 0, n = I.length; i < n; ++i) T[I[i]] = M2[i];\n }\n };\n}\nvar mapCumsum = {\n mapIndex(I, S, T) {\n let sum4 = 0;\n for (const i of I) T[i] = sum4 += S[i];\n }\n};\n\n// ../../node_modules/@observablehq/plot/src/transforms/window.js\nfunction windowX(windowOptions = {}, options) {\n if (arguments.length === 1) options = windowOptions;\n return mapX(window2(windowOptions), options);\n}\nfunction windowY(windowOptions = {}, options) {\n if (arguments.length === 1) options = windowOptions;\n return mapY(window2(windowOptions), options);\n}\nfunction window2(options = {}) {\n if (typeof options === \"number\") options = { k: options };\n let { k: k2, reduce, shift, anchor, strict } = options;\n if (anchor === void 0 && shift !== void 0) {\n anchor = maybeShift(shift);\n warn(`Warning: the shift option is deprecated; please use anchor \"${anchor}\" instead.`);\n }\n if (!((k2 = Math.floor(k2)) > 0)) throw new Error(`invalid k: ${k2}`);\n return maybeReduce2(reduce)(k2, maybeAnchor3(anchor, k2), strict);\n}\nfunction maybeAnchor3(anchor = \"middle\", k2) {\n switch (`${anchor}`.toLowerCase()) {\n case \"middle\":\n return k2 - 1 >> 1;\n case \"start\":\n return 0;\n case \"end\":\n return k2 - 1;\n }\n throw new Error(`invalid anchor: ${anchor}`);\n}\nfunction maybeShift(shift) {\n switch (`${shift}`.toLowerCase()) {\n case \"centered\":\n return \"middle\";\n case \"leading\":\n return \"start\";\n case \"trailing\":\n return \"end\";\n }\n throw new Error(`invalid shift: ${shift}`);\n}\nfunction maybeReduce2(reduce = \"mean\") {\n if (typeof reduce === \"string\") {\n if (/^p\\d{2}$/i.test(reduce)) return reduceAccessor2(percentile(reduce));\n switch (reduce.toLowerCase()) {\n case \"deviation\":\n return reduceAccessor2(deviation);\n case \"max\":\n return reduceArray((I, V) => max2(I, (i) => V[i]));\n case \"mean\":\n return reduceMean;\n case \"median\":\n return reduceAccessor2(median2);\n case \"min\":\n return reduceArray((I, V) => min2(I, (i) => V[i]));\n case \"mode\":\n return reduceArray((I, V) => mode2(I, (i) => V[i]));\n case \"sum\":\n return reduceSum2;\n case \"variance\":\n return reduceAccessor2(variance2);\n case \"difference\":\n return reduceDifference;\n case \"ratio\":\n return reduceRatio;\n case \"first\":\n return reduceFirst2;\n case \"last\":\n return reduceLast2;\n }\n }\n if (typeof reduce !== \"function\") throw new Error(`invalid reduce: ${reduce}`);\n return reduceArray(taker(reduce));\n}\nfunction reduceAccessor2(f) {\n return (k2, s2, strict) => strict ? {\n mapIndex(I, S, T) {\n const v2 = (i) => S[i] == null ? NaN : +S[i];\n let nans = 0;\n for (let i = 0; i < k2 - 1; ++i) if (isNaN(v2(i))) ++nans;\n for (let i = 0, n = I.length - k2 + 1; i < n; ++i) {\n if (isNaN(v2(i + k2 - 1))) ++nans;\n T[I[i + s2]] = nans === 0 ? f(subarray(I, i, i + k2), v2) : NaN;\n if (isNaN(v2(i))) --nans;\n }\n }\n } : {\n mapIndex(I, S, T) {\n const v2 = (i) => S[i] == null ? NaN : +S[i];\n for (let i = -s2; i < 0; ++i) {\n T[I[i + s2]] = f(subarray(I, 0, i + k2), v2);\n }\n for (let i = 0, n = I.length - s2; i < n; ++i) {\n T[I[i + s2]] = f(subarray(I, i, i + k2), v2);\n }\n }\n };\n}\nfunction reduceArray(f) {\n return (k2, s2, strict) => strict ? {\n mapIndex(I, S, T) {\n let count4 = 0;\n for (let i = 0; i < k2 - 1; ++i) count4 += defined(S[I[i]]);\n for (let i = 0, n = I.length - k2 + 1; i < n; ++i) {\n count4 += defined(S[I[i + k2 - 1]]);\n if (count4 === k2) T[I[i + s2]] = f(subarray(I, i, i + k2), S);\n count4 -= defined(S[I[i]]);\n }\n }\n } : {\n mapIndex(I, S, T) {\n for (let i = -s2; i < 0; ++i) {\n T[I[i + s2]] = f(subarray(I, 0, i + k2), S);\n }\n for (let i = 0, n = I.length - s2; i < n; ++i) {\n T[I[i + s2]] = f(subarray(I, i, i + k2), S);\n }\n }\n };\n}\nfunction reduceSum2(k2, s2, strict) {\n return strict ? {\n mapIndex(I, S, T) {\n let nans = 0;\n let sum4 = 0;\n for (let i = 0; i < k2 - 1; ++i) {\n const v2 = S[I[i]];\n if (v2 === null || isNaN(v2)) ++nans;\n else sum4 += +v2;\n }\n for (let i = 0, n = I.length - k2 + 1; i < n; ++i) {\n const a2 = S[I[i]];\n const b = S[I[i + k2 - 1]];\n if (b === null || isNaN(b)) ++nans;\n else sum4 += +b;\n T[I[i + s2]] = nans === 0 ? sum4 : NaN;\n if (a2 === null || isNaN(a2)) --nans;\n else sum4 -= +a2;\n }\n }\n } : {\n mapIndex(I, S, T) {\n let sum4 = 0;\n const n = I.length;\n for (let i = 0, j = Math.min(n, k2 - s2 - 1); i < j; ++i) {\n sum4 += +S[I[i]] || 0;\n }\n for (let i = -s2, j = n - s2; i < j; ++i) {\n sum4 += +S[I[i + k2 - 1]] || 0;\n T[I[i + s2]] = sum4;\n sum4 -= +S[I[i]] || 0;\n }\n }\n };\n}\nfunction reduceMean(k2, s2, strict) {\n if (strict) {\n const sum4 = reduceSum2(k2, s2, strict);\n return {\n mapIndex(I, S, T) {\n sum4.mapIndex(I, S, T);\n for (let i = 0, n = I.length - k2 + 1; i < n; ++i) {\n T[I[i + s2]] /= k2;\n }\n }\n };\n } else {\n return {\n mapIndex(I, S, T) {\n let sum4 = 0;\n let count4 = 0;\n const n = I.length;\n for (let i = 0, j = Math.min(n, k2 - s2 - 1); i < j; ++i) {\n let v2 = S[I[i]];\n if (v2 !== null && !isNaN(v2 = +v2)) sum4 += v2, ++count4;\n }\n for (let i = -s2, j = n - s2; i < j; ++i) {\n let a2 = S[I[i + k2 - 1]];\n let b = S[I[i]];\n if (a2 !== null && !isNaN(a2 = +a2)) sum4 += a2, ++count4;\n T[I[i + s2]] = sum4 / count4;\n if (b !== null && !isNaN(b = +b)) sum4 -= b, --count4;\n }\n }\n };\n }\n}\nfunction firstDefined(S, I, i, k2) {\n for (let j = i + k2; i < j; ++i) {\n const v2 = S[I[i]];\n if (defined(v2)) return v2;\n }\n}\nfunction lastDefined(S, I, i, k2) {\n for (let j = i + k2 - 1; j >= i; --j) {\n const v2 = S[I[j]];\n if (defined(v2)) return v2;\n }\n}\nfunction firstNumber(S, I, i, k2) {\n for (let j = i + k2; i < j; ++i) {\n let v2 = S[I[i]];\n if (v2 !== null && !isNaN(v2 = +v2)) return v2;\n }\n}\nfunction lastNumber(S, I, i, k2) {\n for (let j = i + k2 - 1; j >= i; --j) {\n let v2 = S[I[j]];\n if (v2 !== null && !isNaN(v2 = +v2)) return v2;\n }\n}\nfunction reduceDifference(k2, s2, strict) {\n return strict ? {\n mapIndex(I, S, T) {\n for (let i = 0, n = I.length - k2; i < n; ++i) {\n const a2 = S[I[i]];\n const b = S[I[i + k2 - 1]];\n T[I[i + s2]] = a2 === null || b === null ? NaN : b - a2;\n }\n }\n } : {\n mapIndex(I, S, T) {\n for (let i = -s2, n = I.length - k2 + s2 + 1; i < n; ++i) {\n T[I[i + s2]] = lastNumber(S, I, i, k2) - firstNumber(S, I, i, k2);\n }\n }\n };\n}\nfunction reduceRatio(k2, s2, strict) {\n return strict ? {\n mapIndex(I, S, T) {\n for (let i = 0, n = I.length - k2; i < n; ++i) {\n const a2 = S[I[i]];\n const b = S[I[i + k2 - 1]];\n T[I[i + s2]] = a2 === null || b === null ? NaN : b / a2;\n }\n }\n } : {\n mapIndex(I, S, T) {\n for (let i = -s2, n = I.length - k2 + s2 + 1; i < n; ++i) {\n T[I[i + s2]] = lastNumber(S, I, i, k2) / firstNumber(S, I, i, k2);\n }\n }\n };\n}\nfunction reduceFirst2(k2, s2, strict) {\n return strict ? {\n mapIndex(I, S, T) {\n for (let i = 0, n = I.length - k2; i < n; ++i) {\n T[I[i + s2]] = S[I[i]];\n }\n }\n } : {\n mapIndex(I, S, T) {\n for (let i = -s2, n = I.length - k2 + s2 + 1; i < n; ++i) {\n T[I[i + s2]] = firstDefined(S, I, i, k2);\n }\n }\n };\n}\nfunction reduceLast2(k2, s2, strict) {\n return strict ? {\n mapIndex(I, S, T) {\n for (let i = 0, n = I.length - k2; i < n; ++i) {\n T[I[i + s2]] = S[I[i + k2 - 1]];\n }\n }\n } : {\n mapIndex(I, S, T) {\n for (let i = -s2, n = I.length - k2 + s2 + 1; i < n; ++i) {\n T[I[i + s2]] = lastDefined(S, I, i, k2);\n }\n }\n };\n}\n\n// ../../node_modules/@observablehq/plot/src/marks/bollinger.js\nvar defaults13 = {\n n: 20,\n k: 2,\n color: \"currentColor\",\n opacity: 0.2,\n strict: true,\n anchor: \"end\"\n};\nfunction bollingerX(data, {\n x: x3 = identity7,\n y: y3,\n k: k2 = defaults13.k,\n color: color3 = defaults13.color,\n opacity: opacity2 = defaults13.opacity,\n fill = color3,\n fillOpacity = opacity2,\n stroke = color3,\n strokeOpacity,\n strokeWidth,\n ...options\n} = {}) {\n return marks(\n isNoneish(fill) ? null : areaX(\n data,\n map4(\n { x1: bollinger({ k: -k2, ...options }), x2: bollinger({ k: k2, ...options }) },\n { x1: x3, x2: x3, y: y3, fill, fillOpacity, ...options }\n )\n ),\n isNoneish(stroke) ? null : lineX(data, map4({ x: bollinger(options) }, { x: x3, y: y3, stroke, strokeOpacity, strokeWidth, ...options }))\n );\n}\nfunction bollingerY(data, {\n x: x3,\n y: y3 = identity7,\n k: k2 = defaults13.k,\n color: color3 = defaults13.color,\n opacity: opacity2 = defaults13.opacity,\n fill = color3,\n fillOpacity = opacity2,\n stroke = color3,\n strokeOpacity,\n strokeWidth,\n ...options\n} = {}) {\n return marks(\n isNoneish(fill) ? null : areaY(\n data,\n map4(\n { y1: bollinger({ k: -k2, ...options }), y2: bollinger({ k: k2, ...options }) },\n { x: x3, y1: y3, y2: y3, fill, fillOpacity, ...options }\n )\n ),\n isNoneish(stroke) ? null : lineY(data, map4({ y: bollinger(options) }, { x: x3, y: y3, stroke, strokeOpacity, strokeWidth, ...options }))\n );\n}\nfunction bollinger({ n = defaults13.n, k: k2 = 0, strict = defaults13.strict, anchor = defaults13.anchor } = {}) {\n return window2({ k: n, reduce: (Y3) => mean2(Y3) + k2 * (deviation(Y3) || 0), strict, anchor });\n}\n\n// ../../node_modules/@observablehq/plot/src/marks/tick.js\nvar defaults14 = {\n ariaLabel: \"tick\",\n fill: null,\n stroke: \"currentColor\"\n};\nvar AbstractTick = class extends Mark {\n constructor(data, channels, options) {\n super(data, channels, options, defaults14);\n markers(this, options);\n }\n render(index2, scales2, channels, dimensions, context) {\n return create4(\"svg:g\", context).call(applyIndirectStyles, this, dimensions, context).call(this._transform, this, scales2).call(\n (g) => g.selectAll().data(index2).enter().append(\"line\").call(applyDirectStyles, this).attr(\"x1\", this._x1(scales2, channels, dimensions)).attr(\"x2\", this._x2(scales2, channels, dimensions)).attr(\"y1\", this._y1(scales2, channels, dimensions)).attr(\"y2\", this._y2(scales2, channels, dimensions)).call(applyChannelStyles, this, channels).call(applyMarkers, this, channels, context)\n ).node();\n }\n};\nvar TickX = class extends AbstractTick {\n constructor(data, options = {}) {\n const { x: x3, y: y3, inset: inset2 = 0, insetTop = inset2, insetBottom = inset2 } = options;\n super(\n data,\n {\n x: { value: x3, scale: \"x\" },\n y: { value: y3, scale: \"y\", type: \"band\", optional: true }\n },\n options\n );\n this.insetTop = number5(insetTop);\n this.insetBottom = number5(insetBottom);\n }\n _transform(selection2, mark2, { x: x3 }) {\n selection2.call(applyTransform, mark2, { x: x3 }, offset, 0);\n }\n _x1(scales2, { x: X3 }) {\n return (i) => X3[i];\n }\n _x2(scales2, { x: X3 }) {\n return (i) => X3[i];\n }\n _y1({ y: y3 }, { y: Y3 }, { marginTop: marginTop2 }) {\n const { insetTop } = this;\n return Y3 && y3 ? (i) => Y3[i] + insetTop : marginTop2 + insetTop;\n }\n _y2({ y: y3 }, { y: Y3 }, { height: height2, marginBottom: marginBottom2 }) {\n const { insetBottom } = this;\n return Y3 && y3 ? (i) => Y3[i] + y3.bandwidth() - insetBottom : height2 - marginBottom2 - insetBottom;\n }\n};\nvar TickY = class extends AbstractTick {\n constructor(data, options = {}) {\n const { x: x3, y: y3, inset: inset2 = 0, insetRight = inset2, insetLeft = inset2 } = options;\n super(\n data,\n {\n y: { value: y3, scale: \"y\" },\n x: { value: x3, scale: \"x\", type: \"band\", optional: true }\n },\n options\n );\n this.insetRight = number5(insetRight);\n this.insetLeft = number5(insetLeft);\n }\n _transform(selection2, mark2, { y: y3 }) {\n selection2.call(applyTransform, mark2, { y: y3 }, 0, offset);\n }\n _x1({ x: x3 }, { x: X3 }, { marginLeft: marginLeft2 }) {\n const { insetLeft } = this;\n return X3 && x3 ? (i) => X3[i] + insetLeft : marginLeft2 + insetLeft;\n }\n _x2({ x: x3 }, { x: X3 }, { width: width2, marginRight: marginRight2 }) {\n const { insetRight } = this;\n return X3 && x3 ? (i) => X3[i] + x3.bandwidth() - insetRight : width2 - marginRight2 - insetRight;\n }\n _y1(scales2, { y: Y3 }) {\n return (i) => Y3[i];\n }\n _y2(scales2, { y: Y3 }) {\n return (i) => Y3[i];\n }\n};\nfunction tickX(data, { x: x3 = identity7, ...options } = {}) {\n return new TickX(data, { ...options, x: x3 });\n}\nfunction tickY(data, { y: y3 = identity7, ...options } = {}) {\n return new TickY(data, { ...options, y: y3 });\n}\n\n// ../../node_modules/@observablehq/plot/src/marks/box.js\nfunction boxX(data, {\n x: x3 = identity7,\n y: y3 = null,\n r,\n fill = \"#ccc\",\n fillOpacity,\n stroke = \"currentColor\",\n strokeOpacity,\n strokeWidth = 2,\n sort: sort3,\n ...options\n} = {}) {\n const group3 = y3 != null ? groupY : groupZ;\n return marks(\n ruleY(data, group3({ x1: loqr1, x2: hiqr2 }, { x: x3, y: y3, stroke, strokeOpacity, ...options })),\n barX(data, group3({ x1: \"p25\", x2: \"p75\" }, { x: x3, y: y3, fill, fillOpacity, ...options })),\n tickX(data, group3({ x: \"p50\" }, { x: x3, y: y3, stroke, strokeOpacity, strokeWidth, sort: sort3, ...options })),\n dot(data, map4({ x: oqr }, { x: x3, y: y3, z: y3, r, stroke, strokeOpacity, ...options }))\n );\n}\nfunction boxY(data, {\n y: y3 = identity7,\n x: x3 = null,\n r,\n fill = \"#ccc\",\n fillOpacity,\n stroke = \"currentColor\",\n strokeOpacity,\n strokeWidth = 2,\n sort: sort3,\n ...options\n} = {}) {\n const group3 = x3 != null ? groupX : groupZ;\n return marks(\n ruleX(data, group3({ y1: loqr1, y2: hiqr2 }, { x: x3, y: y3, stroke, strokeOpacity, ...options })),\n barY(data, group3({ y1: \"p25\", y2: \"p75\" }, { x: x3, y: y3, fill, fillOpacity, ...options })),\n tickY(data, group3({ y: \"p50\" }, { x: x3, y: y3, stroke, strokeOpacity, strokeWidth, sort: sort3, ...options })),\n dot(data, map4({ y: oqr }, { x: x3, y: y3, z: x3, r, stroke, strokeOpacity, ...options }))\n );\n}\nfunction oqr(values2) {\n const r1 = loqr1(values2);\n const r2 = hiqr2(values2);\n return values2.map((v2) => v2 < r1 || v2 > r2 ? v2 : NaN);\n}\nfunction loqr1(values2) {\n const lo = quartile1(values2) * 2.5 - quartile3(values2) * 1.5;\n return min2(values2, (d) => d >= lo ? d : NaN);\n}\nfunction hiqr2(values2) {\n const hi = quartile3(values2) * 2.5 - quartile1(values2) * 1.5;\n return max2(values2, (d) => d <= hi ? d : NaN);\n}\nfunction quartile1(values2) {\n return quantile2(values2, 0.25);\n}\nfunction quartile3(values2) {\n return quantile2(values2, 0.75);\n}\n\n// ../../node_modules/@observablehq/plot/src/marks/raster.js\nvar defaults15 = {\n ariaLabel: \"raster\",\n stroke: null,\n pixelSize: 1\n};\nfunction number6(input3, name2) {\n const x3 = +input3;\n if (isNaN(x3)) throw new Error(`invalid ${name2}: ${input3}`);\n return x3;\n}\nfunction integer(input3, name2) {\n const x3 = Math.floor(input3);\n if (isNaN(x3)) throw new Error(`invalid ${name2}: ${input3}`);\n return x3;\n}\nvar AbstractRaster = class extends Mark {\n constructor(data, channels, options = {}, defaults22) {\n let {\n width: width2,\n height: height2,\n x: x3,\n y: y3,\n x1: x12 = x3 == null ? 0 : void 0,\n y1: y12 = y3 == null ? 0 : void 0,\n x2: x22 = x3 == null ? width2 : void 0,\n y2: y22 = y3 == null ? height2 : void 0,\n pixelSize = defaults22.pixelSize,\n blur: blur3 = 0,\n interpolate\n } = options;\n if (width2 != null) width2 = integer(width2, \"width\");\n if (height2 != null) height2 = integer(height2, \"height\");\n if (x12 != null) x12 = number6(x12, \"x1\");\n if (y12 != null) y12 = number6(y12, \"y1\");\n if (x22 != null) x22 = number6(x22, \"x2\");\n if (y22 != null) y22 = number6(y22, \"y2\");\n if (x3 == null && (x12 == null || x22 == null)) throw new Error(\"missing x\");\n if (y3 == null && (y12 == null || y22 == null)) throw new Error(\"missing y\");\n if (data != null && width2 != null && height2 != null) {\n if (x3 === void 0 && x12 != null && x22 != null) x3 = denseX(x12, x22, width2, height2);\n if (y3 === void 0 && y12 != null && y22 != null) y3 = denseY(y12, y22, width2, height2);\n }\n super(\n data,\n {\n x: { value: x3, scale: \"x\", optional: true },\n y: { value: y3, scale: \"y\", optional: true },\n x1: { value: x12 == null ? null : [x12], scale: \"x\", optional: true, filter: null },\n y1: { value: y12 == null ? null : [y12], scale: \"y\", optional: true, filter: null },\n x2: { value: x22 == null ? null : [x22], scale: \"x\", optional: true, filter: null },\n y2: { value: y22 == null ? null : [y22], scale: \"y\", optional: true, filter: null },\n ...channels\n },\n options,\n defaults22\n );\n this.width = width2;\n this.height = height2;\n this.pixelSize = number6(pixelSize, \"pixelSize\");\n this.blur = number6(blur3, \"blur\");\n this.interpolate = x3 == null || y3 == null ? null : maybeInterpolate(interpolate);\n }\n};\nvar Raster = class extends AbstractRaster {\n constructor(data, options = {}) {\n const { imageRendering } = options;\n if (data == null) {\n const { fill, fillOpacity } = options;\n if (maybeNumberChannel(fillOpacity)[0] !== void 0) options = sampler(\"fillOpacity\", options);\n if (maybeColorChannel(fill)[0] !== void 0) options = sampler(\"fill\", options);\n }\n super(data, void 0, options, defaults15);\n this.imageRendering = impliedString(imageRendering, \"auto\");\n }\n // Ignore the color scale, so the fill channel is returned unscaled.\n scale(channels, { color: color3, ...scales2 }, context) {\n return super.scale(channels, scales2, context);\n }\n render(index2, scales2, values2, dimensions, context) {\n const color3 = scales2[values2.channels.fill?.scale] ?? ((x3) => x3);\n const { x: X3, y: Y3 } = values2;\n const { document: document2 } = context;\n const [x12, y12, x22, y22] = renderBounds(values2, dimensions, context);\n const dx = x22 - x12;\n const dy = y22 - y12;\n const { pixelSize: k2, width: w = Math.round(Math.abs(dx) / k2), height: h = Math.round(Math.abs(dy) / k2) } = this;\n const n = w * h;\n let { fill: F, fillOpacity: FO } = values2;\n let offset2 = 0;\n if (this.interpolate) {\n const kx2 = w / dx;\n const ky2 = h / dy;\n const IX = map3(X3, (x3) => (x3 - x12) * kx2, Float64Array);\n const IY = map3(Y3, (y3) => (y3 - y12) * ky2, Float64Array);\n if (F) F = this.interpolate(index2, w, h, IX, IY, F);\n if (FO) FO = this.interpolate(index2, w, h, IX, IY, FO);\n } else if (this.data == null && index2) offset2 = index2.fi * n;\n const canvas = document2.createElement(\"canvas\");\n canvas.width = w;\n canvas.height = h;\n const context2d = canvas.getContext(\"2d\");\n const image3 = context2d.createImageData(w, h);\n const imageData3 = image3.data;\n let { r, g, b } = rgb(this.fill) ?? { r: 0, g: 0, b: 0 };\n let a2 = (this.fillOpacity ?? 1) * 255;\n for (let i = 0; i < n; ++i) {\n const j = i << 2;\n if (F) {\n const fi = color3(F[i + offset2]);\n if (fi == null) {\n imageData3[j + 3] = 0;\n continue;\n }\n ({ r, g, b } = rgb(fi));\n }\n if (FO) a2 = FO[i + offset2] * 255;\n imageData3[j + 0] = r;\n imageData3[j + 1] = g;\n imageData3[j + 2] = b;\n imageData3[j + 3] = a2;\n }\n if (this.blur > 0) blurImage(image3, this.blur);\n context2d.putImageData(image3, 0, 0);\n return create4(\"svg:g\", context).call(applyIndirectStyles, this, dimensions, context).call(applyTransform, this, scales2).call(\n (g2) => g2.append(\"image\").attr(\"transform\", `translate(${x12},${y12}) scale(${Math.sign(x22 - x12)},${Math.sign(y22 - y12)})`).attr(\"width\", Math.abs(dx)).attr(\"height\", Math.abs(dy)).attr(\"preserveAspectRatio\", \"none\").call(applyAttr, \"image-rendering\", this.imageRendering).call(applyDirectStyles, this).attr(\"xlink:href\", canvas.toDataURL())\n ).node();\n }\n};\nfunction maybeTuples(k2, data, options) {\n if (arguments.length < 3) options = data, data = null;\n let { x: x3, y: y3, [k2]: z, ...rest } = options;\n if (x3 === void 0 && y3 === void 0 && isTuples(data)) {\n x3 = first2, y3 = second2;\n if (z === void 0) z = third;\n }\n return [data, { ...rest, x: x3, y: y3, [k2]: z }];\n}\nfunction raster() {\n const [data, options] = maybeTuples(\"fill\", ...arguments);\n return new Raster(\n data,\n data == null || options.fill !== void 0 || options.fillOpacity !== void 0 ? options : { ...options, fill: identity7 }\n );\n}\nfunction renderBounds({ x1: x12, y1: y12, x2: x22, y2: y22 }, dimensions, { projection: projection3 }) {\n const { width: width2, height: height2, marginTop: marginTop2, marginRight: marginRight2, marginBottom: marginBottom2, marginLeft: marginLeft2 } = dimensions;\n return [\n x12 && projection3 == null ? x12[0] : marginLeft2,\n y12 && projection3 == null ? y12[0] : marginTop2,\n x22 && projection3 == null ? x22[0] : width2 - marginRight2,\n y22 && projection3 == null ? y22[0] : height2 - marginBottom2\n ];\n}\nfunction rasterBounds({ x1: x12, y1: y12, x2: x22, y2: y22 }, scales2, dimensions, context) {\n const channels = {};\n if (x12) channels.x1 = x12;\n if (y12) channels.y1 = y12;\n if (x22) channels.x2 = x22;\n if (y22) channels.y2 = y22;\n return renderBounds(valueObject(channels, scales2), dimensions, context);\n}\nfunction sampler(name2, options = {}) {\n const { [name2]: value } = options;\n if (typeof value !== \"function\") throw new Error(`invalid ${name2}: not a function`);\n return initializer({ ...options, [name2]: void 0 }, function(data, facets, channels, scales2, dimensions, context) {\n const { x: x3, y: y3 } = scales2;\n if (!x3) throw new Error(\"missing scale: x\");\n if (!y3) throw new Error(\"missing scale: y\");\n const [x12, y12, x22, y22] = rasterBounds(channels, scales2, dimensions, context);\n const dx = x22 - x12;\n const dy = y22 - y12;\n const { pixelSize: k2 } = this;\n const { width: w = Math.round(Math.abs(dx) / k2), height: h = Math.round(Math.abs(dy) / k2) } = options;\n const V = new Array(w * h * (facets ? facets.length : 1));\n const kx2 = dx / w;\n const ky2 = dy / h;\n let i = 0;\n for (const facet of facets ?? [void 0]) {\n for (let yi = 0.5; yi < h; ++yi) {\n for (let xi = 0.5; xi < w; ++xi, ++i) {\n V[i] = value(x3.invert(x12 + xi * kx2), y3.invert(y12 + yi * ky2), facet);\n }\n }\n }\n return { data: V, facets, channels: { [name2]: { value: V, scale: \"auto\" } } };\n });\n}\nfunction maybeInterpolate(interpolate) {\n if (typeof interpolate === \"function\") return interpolate;\n if (interpolate == null) return interpolateNone;\n switch (`${interpolate}`.toLowerCase()) {\n case \"none\":\n return interpolateNone;\n case \"nearest\":\n return interpolateNearest;\n case \"barycentric\":\n return interpolatorBarycentric();\n case \"random-walk\":\n return interpolatorRandomWalk();\n }\n throw new Error(`invalid interpolate: ${interpolate}`);\n}\nfunction interpolateNone(index2, width2, height2, X3, Y3, V) {\n const W = new Array(width2 * height2);\n for (const i of index2) {\n if (X3[i] < 0 || X3[i] >= width2 || Y3[i] < 0 || Y3[i] >= height2) continue;\n W[Math.floor(Y3[i]) * width2 + Math.floor(X3[i])] = V[i];\n }\n return W;\n}\nfunction interpolatorBarycentric({ random = lcg(42) } = {}) {\n return (index2, width2, height2, X3, Y3, V) => {\n const { points: points2, triangles, hull: hull3 } = Delaunay.from(\n index2,\n (i) => X3[i],\n (i) => Y3[i]\n );\n const W = new V.constructor(width2 * height2).fill(NaN);\n const S = new Uint8Array(width2 * height2);\n const mix = mixer(V, random);\n for (let i = 0; i < triangles.length; i += 3) {\n const ta = triangles[i];\n const tb = triangles[i + 1];\n const tc = triangles[i + 2];\n const Ax = points2[2 * ta];\n const Bx = points2[2 * tb];\n const Cx = points2[2 * tc];\n const Ay = points2[2 * ta + 1];\n const By = points2[2 * tb + 1];\n const Cy = points2[2 * tc + 1];\n const x12 = Math.min(Ax, Bx, Cx);\n const x22 = Math.max(Ax, Bx, Cx);\n const y12 = Math.min(Ay, By, Cy);\n const y22 = Math.max(Ay, By, Cy);\n const z = (By - Cy) * (Ax - Cx) + (Ay - Cy) * (Cx - Bx);\n if (!z) continue;\n const va = V[index2[ta]];\n const vb = V[index2[tb]];\n const vc = V[index2[tc]];\n for (let x3 = Math.floor(x12); x3 < x22; ++x3) {\n for (let y3 = Math.floor(y12); y3 < y22; ++y3) {\n if (x3 < 0 || x3 >= width2 || y3 < 0 || y3 >= height2) continue;\n const xp = x3 + 0.5;\n const yp = y3 + 0.5;\n const s2 = Math.sign(z);\n const ga = (By - Cy) * (xp - Cx) + (yp - Cy) * (Cx - Bx);\n if (ga * s2 < 0) continue;\n const gb = (Cy - Ay) * (xp - Cx) + (yp - Cy) * (Ax - Cx);\n if (gb * s2 < 0) continue;\n const gc = z - (ga + gb);\n if (gc * s2 < 0) continue;\n const i2 = x3 + width2 * y3;\n W[i2] = mix(va, ga / z, vb, gb / z, vc, gc / z, x3, y3);\n S[i2] = 1;\n }\n }\n }\n extrapolateBarycentric(W, S, X3, Y3, V, width2, height2, hull3, index2, mix);\n return W;\n };\n}\nfunction extrapolateBarycentric(W, S, X3, Y3, V, width2, height2, hull3, index2, mix) {\n X3 = Float64Array.from(hull3, (i) => X3[index2[i]]);\n Y3 = Float64Array.from(hull3, (i) => Y3[index2[i]]);\n V = Array.from(hull3, (i) => V[index2[i]]);\n const n = X3.length;\n const rays = Array.from({ length: n }, (_, j) => ray(j, X3, Y3));\n let k2 = 0;\n for (let y3 = 0; y3 < height2; ++y3) {\n const yp = y3 + 0.5;\n for (let x3 = 0; x3 < width2; ++x3) {\n const i = x3 + width2 * y3;\n if (!S[i]) {\n const xp = x3 + 0.5;\n for (let l = 0; l < n; ++l) {\n const j = (n + k2 + (l % 2 ? (l + 1) / 2 : -l / 2)) % n;\n if (rays[j](xp, yp)) {\n const t = segmentProject(X3.at(j - 1), Y3.at(j - 1), X3[j], Y3[j], xp, yp);\n W[i] = mix(V.at(j - 1), t, V[j], 1 - t, V[j], 0, x3, y3);\n k2 = j;\n break;\n }\n }\n }\n }\n }\n}\nfunction segmentProject(x12, y12, x22, y22, x3, y3) {\n const dx = x22 - x12;\n const dy = y22 - y12;\n const a2 = dx * (x22 - x3) + dy * (y22 - y3);\n const b = dx * (x3 - x12) + dy * (y3 - y12);\n return a2 > 0 && b > 0 ? a2 / (a2 + b) : +(a2 > b);\n}\nfunction cross2(xa, ya, xb, yb) {\n return xa * yb - xb * ya;\n}\nfunction ray(j, X3, Y3) {\n const n = X3.length;\n const xc = X3.at(j - 2);\n const yc = Y3.at(j - 2);\n const xa = X3.at(j - 1);\n const ya = Y3.at(j - 1);\n const xb = X3[j];\n const yb = Y3[j];\n const xd = X3.at(j + 1 - n);\n const yd = Y3.at(j + 1 - n);\n const dxab = xa - xb;\n const dyab = ya - yb;\n const dxca = xc - xa;\n const dyca = yc - ya;\n const dxbd = xb - xd;\n const dybd = yb - yd;\n const hab = Math.hypot(dxab, dyab);\n const hca = Math.hypot(dxca, dyca);\n const hbd = Math.hypot(dxbd, dybd);\n return (x3, y3) => {\n const dxa = x3 - xa;\n const dya = y3 - ya;\n const dxb = x3 - xb;\n const dyb = y3 - yb;\n return cross2(dxa, dya, dxb, dyb) > -1e-6 && cross2(dxa, dya, dxab, dyab) * hca - cross2(dxa, dya, dxca, dyca) * hab > -1e-6 && cross2(dxb, dyb, dxbd, dybd) * hab - cross2(dxb, dyb, dxab, dyab) * hbd <= 0;\n };\n}\nfunction interpolateNearest(index2, width2, height2, X3, Y3, V) {\n const W = new V.constructor(width2 * height2);\n const delaunay = Delaunay.from(\n index2,\n (i) => X3[i],\n (i) => Y3[i]\n );\n let iy, ix;\n for (let y3 = 0.5, k2 = 0; y3 < height2; ++y3) {\n ix = iy;\n for (let x3 = 0.5; x3 < width2; ++x3, ++k2) {\n ix = delaunay.find(x3, y3, ix);\n if (x3 === 0.5) iy = ix;\n W[k2] = V[index2[ix]];\n }\n }\n return W;\n}\nfunction interpolatorRandomWalk({ random = lcg(42), minDistance = 0.5, maxSteps = 2 } = {}) {\n return (index2, width2, height2, X3, Y3, V) => {\n const W = new V.constructor(width2 * height2);\n const delaunay = Delaunay.from(\n index2,\n (i) => X3[i],\n (i) => Y3[i]\n );\n let iy, ix, iw;\n for (let y3 = 0.5, k2 = 0; y3 < height2; ++y3) {\n ix = iy;\n for (let x3 = 0.5; x3 < width2; ++x3, ++k2) {\n let cx = x3;\n let cy = y3;\n iw = ix = delaunay.find(cx, cy, ix);\n if (x3 === 0.5) iy = ix;\n let distance;\n let step = 0;\n while ((distance = Math.hypot(X3[index2[iw]] - cx, Y3[index2[iw]] - cy)) > minDistance && step < maxSteps) {\n const angle = random(x3, y3, step) * 2 * Math.PI;\n cx += Math.cos(angle) * distance;\n cy += Math.sin(angle) * distance;\n iw = delaunay.find(cx, cy, iw);\n ++step;\n }\n W[k2] = V[index2[iw]];\n }\n }\n return W;\n };\n}\nfunction blend(a2, ca3, b, cb, c4, cc2) {\n return ca3 * a2 + cb * b + cc2 * c4;\n}\nfunction pick(random) {\n return (a2, ca3, b, cb, c4, cc2, x3, y3) => {\n const u4 = random(x3, y3);\n return u4 < ca3 ? a2 : u4 < ca3 + cb ? b : c4;\n };\n}\nfunction mixer(F, random) {\n return isNumeric(F) || isTemporal(F) ? blend : pick(random);\n}\nfunction denseX(x12, x22, width2) {\n return {\n transform(data) {\n const n = data.length;\n const X3 = new Float64Array(n);\n const kx2 = (x22 - x12) / width2;\n const x06 = x12 + kx2 / 2;\n for (let i = 0; i < n; ++i) X3[i] = i % width2 * kx2 + x06;\n return X3;\n }\n };\n}\nfunction denseY(y12, y22, width2, height2) {\n return {\n transform(data) {\n const n = data.length;\n const Y3 = new Float64Array(n);\n const ky2 = (y22 - y12) / height2;\n const y06 = y12 + ky2 / 2;\n for (let i = 0; i < n; ++i) Y3[i] = Math.floor(i / width2) % height2 * ky2 + y06;\n return Y3;\n }\n };\n}\n\n// ../../node_modules/@observablehq/plot/src/marks/contour.js\nvar defaults16 = {\n ariaLabel: \"contour\",\n fill: \"none\",\n stroke: \"currentColor\",\n strokeMiterlimit: 1,\n pixelSize: 2\n};\nvar Contour = class extends AbstractRaster {\n constructor(data, { smooth = true, value, ...options } = {}) {\n const channels = styles({}, options, defaults16);\n if (value === void 0) {\n for (const key in channels) {\n if (channels[key].value != null) {\n if (value !== void 0) throw new Error(\"ambiguous contour value\");\n value = options[key];\n options[key] = \"value\";\n }\n }\n }\n if (value != null) {\n const v2 = { transform: (D3) => D3.map((d) => d.value), label: labelof(value) };\n for (const key in channels) {\n if (options[key] === \"value\") {\n options[key] = v2;\n }\n }\n }\n if (data == null) {\n if (value == null) throw new Error(\"missing contour value\");\n options = sampler(\"value\", { value, ...options });\n value = null;\n } else {\n let { interpolate } = options;\n if (value === void 0) value = identity7;\n if (interpolate === void 0) options.interpolate = \"nearest\";\n }\n super(data, { value: { value, optional: true } }, contourGeometry(options), defaults16);\n const contourChannels = { geometry: { value: identity7 } };\n for (const key in this.channels) {\n const channel = this.channels[key];\n const { scale: scale3 } = channel;\n if (scale3 === \"x\" || scale3 === \"y\" || key === \"value\") continue;\n contourChannels[key] = channel;\n delete this.channels[key];\n }\n this.contourChannels = contourChannels;\n this.smooth = !!smooth;\n }\n filter(index2, { x: x3, y: y3, value, ...channels }, values2) {\n return super.filter(index2, channels, values2);\n }\n render(index2, scales2, channels, dimensions, context) {\n const { geometry: G } = channels;\n const path2 = path_default();\n return create4(\"svg:g\", context).call(applyIndirectStyles, this, dimensions, context).call(applyTransform, this, scales2).call((g) => {\n g.selectAll().data(index2).enter().append(\"path\").call(applyDirectStyles, this).attr(\"d\", (i) => path2(G[i])).call(applyChannelStyles, this, channels);\n }).node();\n }\n};\nfunction contourGeometry({ thresholds, interval: interval3, ...options }) {\n thresholds = maybeThresholds(thresholds, interval3, thresholdSturges);\n return initializer(options, function(data, facets, channels, scales2, dimensions, context) {\n const [x12, y12, x22, y22] = rasterBounds(channels, scales2, dimensions, context);\n const dx = x22 - x12;\n const dy = y22 - y12;\n const { pixelSize: k2, width: w = Math.round(Math.abs(dx) / k2), height: h = Math.round(Math.abs(dy) / k2) } = this;\n const kx2 = w / dx;\n const ky2 = h / dy;\n const V = channels.value.value;\n const VV = [];\n if (this.interpolate) {\n const { x: X3, y: Y3 } = applyPosition(channels, scales2, context);\n const IX = map3(X3, (x3) => (x3 - x12) * kx2, Float64Array);\n const IY = map3(Y3, (y3) => (y3 - y12) * ky2, Float64Array);\n const ichannels = [channels.x, channels.y, channels.value];\n const ivalues = [IX, IY, V];\n for (const facet of facets) {\n const index2 = this.filter(facet, ichannels, ivalues);\n VV.push(this.interpolate(index2, w, h, IX, IY, V));\n }\n } else if (facets) {\n const n = w * h;\n const m = facets.length;\n for (let i = 0; i < m; ++i) VV.push(V.slice(i * n, i * n + n));\n } else {\n VV.push(V);\n }\n if (this.blur > 0) for (const V2 of VV) blur2({ data: V2, width: w, height: h }, this.blur);\n const T = maybeTicks(thresholds, V, ...finiteExtent(VV));\n if (T === null) throw new Error(`unsupported thresholds: ${thresholds}`);\n const { contour: contour3 } = contours_default().size([w, h]).smooth(this.smooth);\n const contourData = [];\n const contourFacets = [];\n for (const V2 of VV) {\n contourFacets.push(range(contourData.length, contourData.push(...map3(T, (t) => contour3(V2, t)))));\n }\n for (const { coordinates } of contourData) {\n for (const rings of coordinates) {\n for (const ring of rings) {\n for (const point6 of ring) {\n point6[0] = point6[0] / kx2 + x12;\n point6[1] = point6[1] / ky2 + y12;\n }\n }\n }\n }\n return {\n data: contourData,\n facets: contourFacets,\n channels: createChannels(this.contourChannels, contourData)\n };\n });\n}\nfunction maybeTicks(thresholds, V, min5, max4) {\n if (typeof thresholds?.range === \"function\") return thresholds.range(thresholds.floor(min5), max4);\n if (typeof thresholds === \"function\") thresholds = thresholds(V, min5, max4);\n if (typeof thresholds !== \"number\") return arrayify2(thresholds);\n const tz = ticks(...nice(min5, max4, thresholds), thresholds);\n while (tz[tz.length - 1] >= max4) tz.pop();\n while (tz[1] < min5) tz.shift();\n return tz;\n}\nfunction contour() {\n return new Contour(...maybeTuples(\"value\", ...arguments));\n}\nfunction finiteExtent(VV) {\n return [min2(VV, (V) => min2(V, finite3)), max2(VV, (V) => max2(V, finite3))];\n}\nfunction finite3(x3) {\n return isFinite(x3) ? x3 : NaN;\n}\n\n// ../../node_modules/@observablehq/plot/src/marks/crosshair.js\nfunction crosshair(data, options) {\n return crosshairK(pointer, data, options);\n}\nfunction crosshairX(data, options = {}) {\n return crosshairK(pointerX, data, options);\n}\nfunction crosshairY(data, options = {}) {\n return crosshairK(pointerY, data, options);\n}\nfunction crosshairK(pointer2, data, options = {}) {\n const { x: x3, y: y3, maxRadius } = options;\n const p = pointer2({ px: x3, py: y3, maxRadius });\n const M2 = [];\n if (x3 != null) M2.push(ruleX(data, ruleOptions(\"x\", { ...p, inset: -6 }, options)));\n if (y3 != null) M2.push(ruleY(data, ruleOptions(\"y\", { ...p, inset: -6 }, options)));\n if (x3 != null) M2.push(text(data, textOptions(\"x\", { ...p, dy: 9, frameAnchor: \"bottom\", lineAnchor: \"top\" }, options)));\n if (y3 != null) M2.push(text(data, textOptions(\"y\", { ...p, dx: -9, frameAnchor: \"left\", textAnchor: \"end\" }, options)));\n for (const m of M2) m.ariaLabel = `crosshair ${m.ariaLabel}`;\n return marks(...M2);\n}\nfunction markOptions(k2, { channels: pointerChannels, ...pointerOptions }, { facet, facetAnchor, fx, fy, [k2]: p, channels, transform: transform3, initializer: initializer2 }) {\n return {\n ...pointerOptions,\n facet,\n facetAnchor,\n fx,\n fy,\n [k2]: p,\n channels: { ...pointerChannels, ...channels },\n transform: transform3,\n initializer: pxpy(k2, initializer2)\n };\n}\nfunction pxpy(k2, i) {\n if (i == null) return i;\n return function(data, facets, { x: x12, y: y12, px, py, ...c1 }, ...args) {\n const { channels: { x: x3, y: y3, ...c4 } = {}, ...rest } = i.call(this, data, facets, { ...c1, x: px, y: py }, ...args);\n return {\n channels: {\n ...c4,\n ...x3 && { px: x3, ...k2 === \"x\" && { x: x3 } },\n ...y3 && { py: y3, ...k2 === \"y\" && { y: y3 } }\n },\n ...rest\n };\n };\n}\nfunction ruleOptions(k2, pointerOptions, options) {\n const {\n color: color3 = \"currentColor\",\n opacity: opacity2 = 0.2,\n ruleStroke: stroke = color3,\n ruleStrokeOpacity: strokeOpacity = opacity2,\n ruleStrokeWidth: strokeWidth\n } = options;\n return {\n ...markOptions(k2, pointerOptions, options),\n stroke,\n strokeOpacity,\n strokeWidth\n };\n}\nfunction textOptions(k2, pointerOptions, options) {\n const {\n color: color3 = \"currentColor\",\n textFill: fill = color3,\n textFillOpacity: fillOpacity,\n textStroke: stroke = \"var(--plot-background)\",\n textStrokeOpacity: strokeOpacity,\n textStrokeWidth: strokeWidth = 5\n } = options;\n return {\n ...markOptions(k2, pointerOptions, textChannel(k2, options)),\n fill,\n fillOpacity,\n stroke,\n strokeOpacity,\n strokeWidth\n };\n}\nfunction textChannel(source, options) {\n return initializer(options, (data, facets, channels) => {\n return { channels: { text: { value: getSource(channels, source)?.value } } };\n });\n}\n\n// ../../node_modules/@observablehq/plot/src/marks/delaunay.js\nvar delaunayLinkDefaults = {\n ariaLabel: \"delaunay link\",\n fill: \"none\",\n stroke: \"currentColor\",\n strokeMiterlimit: 1\n};\nvar delaunayMeshDefaults = {\n ariaLabel: \"delaunay mesh\",\n fill: null,\n stroke: \"currentColor\",\n strokeOpacity: 0.2\n};\nvar hullDefaults = {\n ariaLabel: \"hull\",\n fill: \"none\",\n stroke: \"currentColor\",\n strokeWidth: 1.5,\n strokeMiterlimit: 1\n};\nvar voronoiDefaults = {\n ariaLabel: \"voronoi\",\n fill: \"none\",\n stroke: \"currentColor\",\n strokeMiterlimit: 1\n};\nvar voronoiMeshDefaults = {\n ariaLabel: \"voronoi mesh\",\n fill: null,\n stroke: \"currentColor\",\n strokeOpacity: 0.2\n};\nvar DelaunayLink = class extends Mark {\n constructor(data, options = {}) {\n const { x: x3, y: y3, z, curve, tension } = options;\n super(\n data,\n {\n x: { value: x3, scale: \"x\", optional: true },\n y: { value: y3, scale: \"y\", optional: true },\n z: { value: z, optional: true }\n },\n options,\n delaunayLinkDefaults\n );\n this.curve = maybeCurve(curve, tension);\n markers(this, options);\n }\n render(index2, scales2, channels, dimensions, context) {\n const { x: x3, y: y3 } = scales2;\n const { x: X3, y: Y3, z: Z } = channels;\n const { curve } = this;\n const [cx, cy] = applyFrameAnchor(this, dimensions);\n const xi = X3 ? (i) => X3[i] : constant(cx);\n const yi = Y3 ? (i) => Y3[i] : constant(cy);\n const mark2 = this;\n function links(index3) {\n let i = -1;\n const newIndex = [];\n const newChannels = {};\n for (const k2 in channels) newChannels[k2] = [];\n const X13 = [];\n const X23 = [];\n const Y13 = [];\n const Y23 = [];\n function link4(ti, tj) {\n ti = index3[ti];\n tj = index3[tj];\n newIndex.push(++i);\n X13[i] = xi(ti);\n Y13[i] = yi(ti);\n X23[i] = xi(tj);\n Y23[i] = yi(tj);\n for (const k2 in channels) newChannels[k2].push(channels[k2][tj]);\n }\n const { halfedges, hull: hull3, triangles } = Delaunay.from(index3, xi, yi);\n for (let i2 = 0; i2 < halfedges.length; ++i2) {\n const j = halfedges[i2];\n if (j > i2) link4(triangles[i2], triangles[j]);\n }\n for (let i2 = 0; i2 < hull3.length; ++i2) {\n link4(hull3[i2], hull3[(i2 + 1) % hull3.length]);\n }\n select_default2(this).selectAll().data(newIndex).enter().append(\"path\").call(applyDirectStyles, mark2).attr(\"d\", (i2) => {\n const p = pathRound();\n const c4 = curve(p);\n c4.lineStart();\n c4.point(X13[i2], Y13[i2]);\n c4.point(X23[i2], Y23[i2]);\n c4.lineEnd();\n return p;\n }).call(applyChannelStyles, mark2, newChannels).call(applyMarkers, mark2, newChannels, context);\n }\n return create4(\"svg:g\", context).call(applyIndirectStyles, this, dimensions, context).call(applyTransform, this, { x: X3 && x3, y: Y3 && y3 }).call(\n Z ? (g) => g.selectAll().data(group(index2, (i) => Z[i]).values()).enter().append(\"g\").each(links) : (g) => g.datum(index2).each(links)\n ).node();\n }\n};\nvar AbstractDelaunayMark = class extends Mark {\n constructor(data, options = {}, defaults22, zof = ({ z }) => z) {\n const { x: x3, y: y3 } = options;\n super(\n data,\n {\n x: { value: x3, scale: \"x\", optional: true },\n y: { value: y3, scale: \"y\", optional: true },\n z: { value: zof(options), optional: true }\n },\n options,\n defaults22\n );\n }\n render(index2, scales2, channels, dimensions, context) {\n const { x: x3, y: y3 } = scales2;\n const { x: X3, y: Y3, z: Z } = channels;\n const [cx, cy] = applyFrameAnchor(this, dimensions);\n const xi = X3 ? (i) => X3[i] : constant(cx);\n const yi = Y3 ? (i) => Y3[i] : constant(cy);\n const mark2 = this;\n function mesh(index3) {\n const delaunay = Delaunay.from(index3, xi, yi);\n select_default2(this).append(\"path\").datum(index3[0]).call(applyDirectStyles, mark2).attr(\"d\", mark2._render(delaunay, dimensions)).call(applyChannelStyles, mark2, channels);\n }\n return create4(\"svg:g\", context).call(applyIndirectStyles, this, dimensions, context).call(applyTransform, this, { x: X3 && x3, y: Y3 && y3 }).call(\n Z ? (g) => g.selectAll().data(group(index2, (i) => Z[i]).values()).enter().append(\"g\").each(mesh) : (g) => g.datum(index2).each(mesh)\n ).node();\n }\n};\nvar DelaunayMesh = class extends AbstractDelaunayMark {\n constructor(data, options = {}) {\n super(data, options, delaunayMeshDefaults);\n this.fill = \"none\";\n }\n _render(delaunay) {\n return delaunay.render();\n }\n};\nvar Hull = class extends AbstractDelaunayMark {\n constructor(data, options = {}) {\n super(data, options, hullDefaults, maybeZ);\n }\n _render(delaunay) {\n return delaunay.renderHull();\n }\n};\nvar Voronoi2 = class extends Mark {\n constructor(data, options = {}) {\n const { x: x3, y: y3, z } = options;\n super(\n data,\n {\n x: { value: x3, scale: \"x\", optional: true },\n y: { value: y3, scale: \"y\", optional: true },\n z: { value: z, optional: true }\n },\n initializer(options, function(data2, facets, channels, scales2, dimensions, context) {\n let { x: X3, y: Y3, z: Z } = channels;\n ({ x: X3, y: Y3 } = applyPosition(channels, scales2, context));\n Z = Z?.value;\n const C3 = new Array((X3 ?? Y3).length).fill(null);\n const [cx, cy] = applyFrameAnchor(this, dimensions);\n const xi = X3 ? (i) => X3[i] : constant(cx);\n const yi = Y3 ? (i) => Y3[i] : constant(cy);\n for (let I of facets) {\n if (X3) I = I.filter((i) => defined(xi(i)));\n if (Y3) I = I.filter((i) => defined(yi(i)));\n for (const [, J] of maybeGroup(I, Z)) {\n const delaunay = Delaunay.from(J, xi, yi);\n const voronoi3 = voronoiof(delaunay, dimensions);\n for (let i = 0, n = J.length; i < n; ++i) {\n C3[J[i]] = voronoi3.renderCell(i);\n }\n }\n }\n return { data: data2, facets, channels: { cells: { value: C3 } } };\n }),\n voronoiDefaults\n );\n }\n render(index2, scales2, channels, dimensions, context) {\n const { x: x3, y: y3 } = scales2;\n const { x: X3, y: Y3, cells: C3 } = channels;\n return create4(\"svg:g\", context).call(applyIndirectStyles, this, dimensions, context).call(applyTransform, this, { x: X3 && x3, y: Y3 && y3 }).call((g) => {\n g.selectAll().data(index2).enter().append(\"path\").call(applyDirectStyles, this).attr(\"d\", (i) => C3[i]).call(applyChannelStyles, this, channels);\n }).node();\n }\n};\nvar VoronoiMesh = class extends AbstractDelaunayMark {\n constructor(data, options) {\n super(data, options, voronoiMeshDefaults);\n this.fill = \"none\";\n }\n _render(delaunay, dimensions) {\n return voronoiof(delaunay, dimensions).render();\n }\n};\nfunction voronoiof(delaunay, dimensions) {\n const { width: width2, height: height2, marginTop: marginTop2, marginRight: marginRight2, marginBottom: marginBottom2, marginLeft: marginLeft2 } = dimensions;\n return delaunay.voronoi([marginLeft2, marginTop2, width2 - marginRight2, height2 - marginBottom2]);\n}\nfunction delaunayMark(DelaunayMark, data, { x: x3, y: y3, ...options } = {}) {\n [x3, y3] = maybeTuple(x3, y3);\n return new DelaunayMark(data, { ...options, x: x3, y: y3 });\n}\nfunction delaunayLink(data, options) {\n return delaunayMark(DelaunayLink, data, options);\n}\nfunction delaunayMesh(data, options) {\n return delaunayMark(DelaunayMesh, data, options);\n}\nfunction hull(data, options) {\n return delaunayMark(Hull, data, options);\n}\nfunction voronoi(data, { x: x3, y: y3, initializer: initializer2, ...options } = {}) {\n return delaunayMark(Voronoi2, data, { ...basic({ ...options, x: x3, y: y3 }, exclusiveFacets), initializer: initializer2 });\n}\nfunction voronoiMesh(data, options) {\n return delaunayMark(VoronoiMesh, data, options);\n}\n\n// ../../node_modules/@observablehq/plot/src/marks/density.js\nvar defaults17 = {\n ariaLabel: \"density\",\n fill: \"none\",\n stroke: \"currentColor\",\n strokeMiterlimit: 1\n};\nvar Density = class extends Mark {\n constructor(data, { x: x3, y: y3, z, weight, fill, stroke, ...options } = {}) {\n const fillDensity = isDensity(fill) && (fill = \"currentColor\", true);\n const strokeDensity = isDensity(stroke) && (stroke = \"currentColor\", true);\n super(\n data,\n {\n x: { value: x3, scale: \"x\", optional: true },\n y: { value: y3, scale: \"y\", optional: true },\n z: { value: maybeZ({ z, fill, stroke }), optional: true },\n weight: { value: weight, optional: true }\n },\n densityInitializer({ ...options, fill, stroke }, fillDensity, strokeDensity),\n defaults17\n );\n if (fillDensity) this.fill = void 0;\n if (strokeDensity) this.stroke = void 0;\n this.z = z;\n }\n filter(index2) {\n return index2;\n }\n render(index2, scales2, channels, dimensions, context) {\n const { contours } = channels;\n const path2 = path_default();\n return create4(\"svg:g\", context).call(applyIndirectStyles, this, dimensions, context).call(applyTransform, this, {}).call(\n (g) => g.selectAll().data(index2).enter().append(\"path\").call(applyDirectStyles, this).call(applyChannelStyles, this, channels).attr(\"d\", (i) => path2(contours[i]))\n ).node();\n }\n};\nfunction density(data, { x: x3, y: y3, ...options } = {}) {\n [x3, y3] = maybeTuple(x3, y3);\n return new Density(data, { ...options, x: x3, y: y3 });\n}\nvar dropChannels = /* @__PURE__ */ new Set([\"x\", \"y\", \"z\", \"weight\"]);\nfunction densityInitializer(options, fillDensity, strokeDensity) {\n const k2 = 100;\n let { bandwidth, thresholds } = options;\n bandwidth = bandwidth === void 0 ? 20 : +bandwidth;\n thresholds = thresholds === void 0 ? 20 : typeof thresholds?.[Symbol.iterator] === \"function\" ? coerceNumbers(thresholds) : +thresholds;\n return initializer(options, function(data, facets, channels, scales2, dimensions, context) {\n const W = channels.weight ? coerceNumbers(channels.weight.value) : null;\n const Z = channels.z?.value;\n const { z } = this;\n const [cx, cy] = applyFrameAnchor(this, dimensions);\n const { width: width2, height: height2 } = dimensions;\n const { x: X3, y: Y3 } = applyPosition(channels, scales2, context);\n const newChannels = Object.fromEntries(\n Object.entries(channels).filter(([key]) => !dropChannels.has(key)).map(([key, channel]) => [key, { ...channel, value: [] }])\n );\n const FD = fillDensity && [];\n const SD = strokeDensity && [];\n const density3 = density_default().x(X3 ? (i) => X3[i] : cx).y(Y3 ? (i) => Y3[i] : cy).weight(W ? (i) => W[i] : 1).size([width2, height2]).bandwidth(bandwidth);\n const facetsContours = [];\n for (const facet of facets) {\n const facetContours = [];\n facetsContours.push(facetContours);\n for (const index2 of Z ? groupZ2(facet, Z, z) : [facet]) {\n const contour3 = density3.contours(index2);\n facetContours.push([index2, contour3]);\n }\n }\n let T = thresholds;\n if (!(T instanceof TypedArray2)) {\n let maxValue = 0;\n for (const facetContours of facetsContours) {\n for (const [, contour3] of facetContours) {\n const max4 = contour3.max;\n if (max4 > maxValue) maxValue = max4;\n }\n }\n T = Float64Array.from({ length: thresholds - 1 }, (_, i) => maxValue * k2 * (i + 1) / thresholds);\n }\n const newFacets = [];\n const contours = [];\n for (const facetContours of facetsContours) {\n const newFacet = [];\n newFacets.push(newFacet);\n for (const [index2, contour3] of facetContours) {\n for (const t of T) {\n newFacet.push(contours.length);\n contours.push(contour3(t / k2));\n if (FD) FD.push(t);\n if (SD) SD.push(t);\n for (const key in newChannels) {\n newChannels[key].value.push(channels[key].value[index2[0]]);\n }\n }\n }\n }\n if (FD) FD.push(0);\n if (SD) SD.push(0);\n return {\n data,\n facets: newFacets,\n channels: {\n ...newChannels,\n ...FD && { fill: { value: FD, scale: \"color\" } },\n ...SD && { stroke: { value: SD, scale: \"color\" } },\n contours: { value: contours }\n }\n };\n });\n}\nfunction isDensity(value) {\n return /^density$/i.test(value);\n}\n\n// ../../node_modules/@observablehq/plot/src/marks/difference.js\nfunction differenceX(data, options) {\n return differenceK(\"x\", data, options);\n}\nfunction differenceY(data, options) {\n return differenceK(\"y\", data, options);\n}\nfunction differenceK(k2, data, {\n x1: x12,\n x2: x22,\n y1: y12,\n y2: y22,\n x: x3 = x12 === void 0 && x22 === void 0 ? k2 === \"y\" ? indexOf : identity7 : void 0,\n y: y3 = y12 === void 0 && y22 === void 0 ? k2 === \"x\" ? indexOf : identity7 : void 0,\n fill,\n // ignored\n positiveFill = \"#3ca951\",\n negativeFill = \"#4269d0\",\n fillOpacity = 1,\n positiveFillOpacity = fillOpacity,\n negativeFillOpacity = fillOpacity,\n stroke,\n strokeOpacity,\n z = maybeColorChannel(stroke)[0],\n clip,\n // optional additional clip for area\n tip: tip2,\n render,\n ...options\n} = {}) {\n [x12, x22] = memoTuple(x3, x12, x22);\n [y12, y22] = memoTuple(y3, y12, y22);\n if (x12 === x22 && y12 === y22) {\n if (k2 === \"y\") y12 = memo(0);\n else x12 = memo(0);\n }\n ({ tip: tip2 } = withTip({ tip: tip2 }, k2 === \"y\" ? \"x\" : \"y\"));\n return marks(\n !isNoneish(positiveFill) ? Object.assign(\n area(data, {\n x1: x12,\n x2: x22,\n y1: y12,\n y2: y22,\n z,\n fill: positiveFill,\n fillOpacity: positiveFillOpacity,\n render: composeRender(render, clipDifference(k2, true)),\n clip,\n ...options\n }),\n { ariaLabel: \"positive difference\" }\n ) : null,\n !isNoneish(negativeFill) ? Object.assign(\n area(data, {\n x1: x12,\n x2: x22,\n y1: y12,\n y2: y22,\n z,\n fill: negativeFill,\n fillOpacity: negativeFillOpacity,\n render: composeRender(render, clipDifference(k2, false)),\n clip,\n ...options\n }),\n { ariaLabel: \"negative difference\" }\n ) : null,\n line(data, {\n x: x22,\n y: y22,\n z,\n stroke,\n strokeOpacity,\n tip: tip2,\n clip: true,\n ...options\n })\n );\n}\nfunction memoTuple(x3, x12, x22) {\n if (x12 === void 0 && x22 === void 0) {\n x12 = x22 = memo(x3);\n } else if (x12 === void 0) {\n x22 = memo(x22);\n x12 = x3 === void 0 ? x22 : memo(x3);\n } else if (x22 === void 0) {\n x12 = memo(x12);\n x22 = x3 === void 0 ? x12 : memo(x3);\n } else {\n x12 = memo(x12);\n x22 = memo(x22);\n }\n return [x12, x22];\n}\nfunction memo(v2) {\n let V;\n const { value, label: label2 = labelof(value) } = maybeValue(v2);\n return { transform: (data) => V || (V = valueof(data, value)), label: label2 };\n}\nfunction clipDifference(k2, positive2) {\n const f = k2 === \"x\" ? \"y\" : \"x\";\n const f1 = `${f}1`;\n const f2 = `${f}2`;\n const k1 = `${k2}1`;\n const k22 = `${k2}2`;\n return (index2, scales2, channels, dimensions, context, next) => {\n const { [f1]: F1, [f2]: F2 } = channels;\n const K1 = new Float32Array(F1.length);\n const K2 = new Float32Array(F2.length);\n const m = dimensions[k2 === \"y\" ? \"height\" : \"width\"];\n (positive2 === inferScaleOrder(scales2[k2]) < 0 ? K1 : K2).fill(m);\n const oc = next(index2, scales2, { ...channels, [f2]: F1, [k22]: K2 }, dimensions, context);\n const og = next(index2, scales2, { ...channels, [f1]: F2, [k1]: K1 }, dimensions, context);\n const c4 = oc.querySelector(\"g\") ?? oc;\n const g = og.querySelector(\"g\") ?? og;\n for (let i = 0; c4.firstChild; i += 2) {\n const id2 = getClipId();\n const clipPath = create4(\"svg:clipPath\", context).attr(\"id\", id2).node();\n clipPath.appendChild(c4.firstChild);\n g.childNodes[i].setAttribute(\"clip-path\", `url(#${id2})`);\n g.insertBefore(clipPath, g.childNodes[i]);\n }\n return og;\n };\n}\n\n// ../../node_modules/@observablehq/plot/src/transforms/centroid.js\nfunction centroid2({ geometry = identity7, ...options } = {}) {\n const getG = memoize1((data) => valueof(data, geometry));\n return initializer(\n // Suppress defaults for x and y since they will be computed by the initializer.\n // Propagate the (memoized) geometry channel in case it’s still needed.\n { ...options, x: null, y: null, geometry: { transform: getG } },\n (data, facets, channels, scales2, dimensions, { projection: projection3 }) => {\n const G = getG(data);\n const n = G.length;\n const X3 = new Float64Array(n);\n const Y3 = new Float64Array(n);\n const path2 = path_default(projection3);\n for (let i = 0; i < n; ++i) [X3[i], Y3[i]] = path2.centroid(G[i]);\n return {\n data,\n facets,\n channels: {\n x: { value: X3, scale: projection3 == null ? \"x\" : null, source: null },\n y: { value: Y3, scale: projection3 == null ? \"y\" : null, source: null }\n }\n };\n }\n );\n}\nfunction geoCentroid({ geometry = identity7, ...options } = {}) {\n const getG = memoize1((data) => valueof(data, geometry));\n const getC = memoize1((data) => valueof(getG(data), centroid_default));\n return {\n ...options,\n x: { transform: (data) => Float64Array.from(getC(data), ([x3]) => x3) },\n y: { transform: (data) => Float64Array.from(getC(data), ([, y3]) => y3) },\n geometry: { transform: getG }\n };\n}\n\n// ../../node_modules/@observablehq/plot/src/marks/geo.js\nvar defaults18 = {\n ariaLabel: \"geo\",\n fill: \"none\",\n stroke: \"currentColor\",\n strokeWidth: 1,\n strokeLinecap: \"round\",\n strokeLinejoin: \"round\",\n strokeMiterlimit: 1\n};\nvar Geo = class extends Mark {\n constructor(data, options = {}) {\n const [vr, cr] = maybeNumberChannel(options.r, 3);\n super(\n data,\n {\n x: { value: options.tip ? options.x : null, scale: \"x\", optional: true },\n y: { value: options.tip ? options.y : null, scale: \"y\", optional: true },\n r: { value: vr, scale: \"r\", filter: positive, optional: true },\n geometry: { value: options.geometry, scale: \"projection\" }\n },\n withDefaultSort(options),\n defaults18\n );\n this.r = cr;\n }\n render(index2, scales2, channels, dimensions, context) {\n const { geometry: G, r: R } = channels;\n const path2 = path_default(context.projection ?? scaleProjection2(scales2));\n const { r } = this;\n if (negative(r)) index2 = [];\n else if (r !== void 0) path2.pointRadius(r);\n return create4(\"svg:g\", context).call(applyIndirectStyles, this, dimensions, context).call(applyTransform, this, scales2).call((g) => {\n g.selectAll().data(index2).enter().append(\"path\").call(applyDirectStyles, this).attr(\"d\", R ? (i) => path2.pointRadius(R[i])(G[i]) : (i) => path2(G[i])).call(applyChannelStyles, this, channels);\n }).node();\n }\n};\nfunction scaleProjection2({ x: X3, y: Y3 }) {\n if (X3 || Y3) {\n X3 ??= (x3) => x3;\n Y3 ??= (y3) => y3;\n return transform_default({\n point(x3, y3) {\n this.stream.point(X3(x3), Y3(y3));\n }\n });\n }\n}\nfunction geo(data, options = {}) {\n if (options.tip && options.x === void 0 && options.y === void 0) options = centroid2(options);\n else if (options.geometry === void 0) options = { ...options, geometry: identity7 };\n return new Geo(data, options);\n}\nfunction sphere({ strokeWidth = 1.5, ...options } = {}) {\n return geo({ type: \"Sphere\" }, { strokeWidth, ...options });\n}\nfunction graticule2({ strokeOpacity = 0.1, ...options } = {}) {\n return geo(graticule10(), { strokeOpacity, ...options });\n}\n\n// ../../node_modules/@observablehq/plot/src/transforms/hexbin.js\nvar ox = 0.5;\nvar oy = 0;\nfunction hexbin(outputs = { fill: \"count\" }, { binWidth, ...options } = {}) {\n const { z } = options;\n binWidth = binWidth === void 0 ? 20 : number5(binWidth);\n outputs = maybeGroupOutputs(outputs, options);\n if (hasOutput(outputs, \"fill\")) options.channels = { ...options.channels, fill: { value: [] } };\n if (options.symbol === void 0) options.symbol = \"hexagon\";\n if (options.r === void 0 && !hasOutput(outputs, \"r\")) options.r = binWidth / 2;\n return initializer(options, (data, facets, channels, scales2, _, context) => {\n let { x: X3, y: Y3, z: Z, fill: F, stroke: S, symbol: Q } = channels;\n if (X3 === void 0) throw new Error(\"missing channel: x\");\n if (Y3 === void 0) throw new Error(\"missing channel: y\");\n ({ x: X3, y: Y3 } = applyPosition(channels, scales2, context));\n Z = Z ? Z.value : valueof(data, z);\n F = F?.value;\n S = S?.value;\n Q = Q?.value;\n const G = maybeSubgroup(outputs, { z: Z, fill: F, stroke: S, symbol: Q });\n const GZ = Z && [];\n const GF = F && [];\n const GS = S && [];\n const GQ = Q && [];\n const binFacets = [];\n const BX = [];\n const BY = [];\n let i = -1;\n for (const o of outputs) o.initialize(data);\n for (const facet of facets) {\n const binFacet = [];\n for (const o of outputs) o.scope(\"facet\", facet);\n for (const [f, I] of maybeGroup(facet, G)) {\n for (const { index: b, extent: extent4 } of hbin(data, I, X3, Y3, binWidth)) {\n binFacet.push(++i);\n BX.push(extent4.x);\n BY.push(extent4.y);\n if (Z) GZ.push(G === Z ? f : Z[b[0]]);\n if (F) GF.push(G === F ? f : F[b[0]]);\n if (S) GS.push(G === S ? f : S[b[0]]);\n if (Q) GQ.push(G === Q ? f : Q[b[0]]);\n for (const o of outputs) o.reduce(b, extent4);\n }\n }\n binFacets.push(binFacet);\n }\n const sx = channels.x.scale;\n const sy = channels.y.scale;\n const binChannels = {\n x: { value: BX, source: scales2[sx] ? { value: map3(BX, scales2[sx].invert), scale: sx } : null },\n y: { value: BY, source: scales2[sy] ? { value: map3(BY, scales2[sy].invert), scale: sy } : null },\n ...Z && { z: { value: GZ } },\n ...F && { fill: { value: GF, scale: \"auto\" } },\n ...S && { stroke: { value: GS, scale: \"auto\" } },\n ...Q && { symbol: { value: GQ, scale: \"auto\" } },\n ...Object.fromEntries(\n outputs.map(({ name: name2, output }) => [\n name2,\n {\n scale: \"auto\",\n label: output.label,\n radius: name2 === \"r\" ? binWidth / 2 : void 0,\n value: output.transform()\n }\n ])\n )\n };\n return { data, facets: binFacets, channels: binChannels };\n });\n}\nfunction hbin(data, I, X3, Y3, dx) {\n const dy = dx * (1.5 / sqrt35);\n const bins2 = /* @__PURE__ */ new Map();\n for (const i of I) {\n let px = X3[i], py = Y3[i];\n if (isNaN(px) || isNaN(py)) continue;\n let pj = Math.round(py = (py - oy) / dy), pi5 = Math.round(px = (px - ox) / dx - (pj & 1) / 2), py1 = py - pj;\n if (Math.abs(py1) * 3 > 1) {\n let px1 = px - pi5, pi22 = pi5 + (px < pi5 ? -1 : 1) / 2, pj2 = pj + (py < pj ? -1 : 1), px2 = px - pi22, py2 = py - pj2;\n if (px1 * px1 + py1 * py1 > px2 * px2 + py2 * py2) pi5 = pi22 + (pj & 1 ? 1 : -1) / 2, pj = pj2;\n }\n const key = `${pi5},${pj}`;\n let bin3 = bins2.get(key);\n if (bin3 === void 0) {\n bin3 = { index: [], extent: { data, x: (pi5 + (pj & 1) / 2) * dx + ox, y: pj * dy + oy } };\n bins2.set(key, bin3);\n }\n bin3.index.push(i);\n }\n return bins2.values();\n}\n\n// ../../node_modules/@observablehq/plot/src/marks/hexgrid.js\nvar defaults19 = {\n ariaLabel: \"hexgrid\",\n fill: \"none\",\n stroke: \"currentColor\",\n strokeOpacity: 0.1\n};\nfunction hexgrid(options) {\n return new Hexgrid(options);\n}\nvar Hexgrid = class extends Mark {\n constructor({ binWidth = 20, clip = true, ...options } = {}) {\n super(singleton, void 0, { clip, ...options }, defaults19);\n this.binWidth = number5(binWidth);\n }\n render(index2, scales2, channels, dimensions, context) {\n const { binWidth } = this;\n const { marginTop: marginTop2, marginRight: marginRight2, marginBottom: marginBottom2, marginLeft: marginLeft2, width: width2, height: height2 } = dimensions;\n const x06 = marginLeft2 - ox, x12 = width2 - marginRight2 - ox, y06 = marginTop2 - oy, y12 = height2 - marginBottom2 - oy, rx = binWidth / 2, ry = rx * sqrt4_3, hy = ry / 2, wx = rx * 2, wy = ry * 1.5, i0 = Math.floor(x06 / wx), i1 = Math.ceil(x12 / wx), j0 = Math.floor((y06 + hy) / wy), j1 = Math.ceil((y12 - hy) / wy) + 1, path2 = `m0,${round(-ry)}l${round(rx)},${round(hy)}v${round(ry)}l${round(-rx)},${round(hy)}`;\n let d = path2;\n for (let j = j0; j < j1; ++j) {\n for (let i = i0; i < i1; ++i) {\n d += `M${round(i * wx + (j & 1) * rx)},${round(j * wy)}${path2}`;\n }\n }\n return create4(\"svg:g\", context).datum(0).call(applyIndirectStyles, this, dimensions, context).call(applyTransform, this, {}, offset + ox, offset + oy).call((g) => g.append(\"path\").call(applyDirectStyles, this).call(applyChannelStyles, this, channels).attr(\"d\", d)).node();\n }\n};\nfunction round(x3) {\n return Math.round(x3 * 1e3) / 1e3;\n}\n\n// ../../node_modules/@observablehq/plot/src/marks/image.js\nvar defaults20 = {\n ariaLabel: \"image\",\n fill: null,\n stroke: null\n};\nfunction isPath(string2) {\n return /^\\.*\\//.test(string2);\n}\nfunction isUrl(string2) {\n return /^(blob|data|file|http|https):/i.test(string2);\n}\nfunction maybePathChannel(value) {\n return typeof value === \"string\" && (isPath(value) || isUrl(value)) ? [void 0, value] : [value, void 0];\n}\nvar Image = class extends Mark {\n constructor(data, options = {}) {\n let { x: x3, y: y3, r, width: width2, height: height2, rotate, src, preserveAspectRatio, crossOrigin, frameAnchor, imageRendering } = options;\n if (r == null) r = void 0;\n if (r === void 0 && width2 === void 0 && height2 === void 0) width2 = height2 = 16;\n else if (width2 === void 0 && height2 !== void 0) width2 = height2;\n else if (height2 === void 0 && width2 !== void 0) height2 = width2;\n const [vs, cs] = maybePathChannel(src);\n const [vr, cr] = maybeNumberChannel(r);\n const [vw, cw] = maybeNumberChannel(width2, cr !== void 0 ? cr * 2 : void 0);\n const [vh, ch] = maybeNumberChannel(height2, cr !== void 0 ? cr * 2 : void 0);\n const [va, ca3] = maybeNumberChannel(rotate, 0);\n super(\n data,\n {\n x: { value: x3, scale: \"x\", optional: true },\n y: { value: y3, scale: \"y\", optional: true },\n r: { value: vr, scale: \"r\", filter: positive, optional: true },\n width: { value: vw, filter: positive, optional: true },\n height: { value: vh, filter: positive, optional: true },\n rotate: { value: va, optional: true },\n src: { value: vs, optional: true }\n },\n withDefaultSort(options),\n defaults20\n );\n this.src = cs;\n this.width = cw;\n this.rotate = ca3;\n this.height = ch;\n this.r = cr;\n this.preserveAspectRatio = impliedString(preserveAspectRatio, \"xMidYMid\");\n this.crossOrigin = string(crossOrigin);\n this.frameAnchor = maybeFrameAnchor(frameAnchor);\n this.imageRendering = impliedString(imageRendering, \"auto\");\n }\n render(index2, scales2, channels, dimensions, context) {\n const { x: x3, y: y3 } = scales2;\n const { x: X3, y: Y3, width: W, height: H, r: R, rotate: A5, src: S } = channels;\n const { r, width: width2, height: height2, rotate } = this;\n const [cx, cy] = applyFrameAnchor(this, dimensions);\n return create4(\"svg:g\", context).call(applyIndirectStyles, this, dimensions, context).call(applyTransform, this, { x: X3 && x3, y: Y3 && y3 }).call(\n (g) => g.selectAll().data(index2).enter().append(\"image\").call(applyDirectStyles, this).attr(\"x\", position2(X3, W, R, cx, width2, r)).attr(\"y\", position2(Y3, H, R, cy, height2, r)).attr(\"width\", W ? (i) => W[i] : width2 !== void 0 ? width2 : R ? (i) => R[i] * 2 : r * 2).attr(\"height\", H ? (i) => H[i] : height2 !== void 0 ? height2 : R ? (i) => R[i] * 2 : r * 2).attr(\"transform\", A5 ? (i) => `rotate(${A5[i]})` : rotate ? `rotate(${rotate})` : null).attr(\"transform-origin\", A5 || rotate ? template`${X3 ? (i) => X3[i] : cx}px ${Y3 ? (i) => Y3[i] : cy}px` : null).call(applyAttr, \"href\", S ? (i) => S[i] : this.src).call(applyAttr, \"preserveAspectRatio\", this.preserveAspectRatio).call(applyAttr, \"crossorigin\", this.crossOrigin).call(applyAttr, \"image-rendering\", this.imageRendering).call(applyAttr, \"clip-path\", R ? (i) => `circle(${R[i]}px)` : r !== void 0 ? `circle(${r}px)` : null).call(applyChannelStyles, this, channels)\n ).node();\n }\n};\nfunction position2(X3, W, R, x3, w, r) {\n return W && X3 ? (i) => X3[i] - W[i] / 2 : W ? (i) => x3 - W[i] / 2 : X3 && w !== void 0 ? (i) => X3[i] - w / 2 : w !== void 0 ? x3 - w / 2 : R && X3 ? (i) => X3[i] - R[i] : R ? (i) => x3 - R[i] : X3 ? (i) => X3[i] - r : x3 - r;\n}\nfunction image(data, { x: x3, y: y3, ...options } = {}) {\n if (options.frameAnchor === void 0) [x3, y3] = maybeTuple(x3, y3);\n return new Image(data, { ...options, x: x3, y: y3 });\n}\n\n// ../../node_modules/@observablehq/plot/src/stats.js\nfunction ibetainv(p, a2, b) {\n var EPS2 = 1e-8;\n var a1 = a2 - 1;\n var b1 = b - 1;\n var j = 0;\n var lna, lnb, pp, t, u4, err, x3, al, h, w, afac;\n if (p <= 0) return 0;\n if (p >= 1) return 1;\n if (a2 >= 1 && b >= 1) {\n pp = p < 0.5 ? p : 1 - p;\n t = Math.sqrt(-2 * Math.log(pp));\n x3 = (2.30753 + t * 0.27061) / (1 + t * (0.99229 + t * 0.04481)) - t;\n if (p < 0.5) x3 = -x3;\n al = (x3 * x3 - 3) / 6;\n h = 2 / (1 / (2 * a2 - 1) + 1 / (2 * b - 1));\n w = x3 * Math.sqrt(al + h) / h - (1 / (2 * b - 1) - 1 / (2 * a2 - 1)) * (al + 5 / 6 - 2 / (3 * h));\n x3 = a2 / (a2 + b * Math.exp(2 * w));\n } else {\n lna = Math.log(a2 / (a2 + b));\n lnb = Math.log(b / (a2 + b));\n t = Math.exp(a2 * lna) / a2;\n u4 = Math.exp(b * lnb) / b;\n w = t + u4;\n if (p < t / w) x3 = Math.pow(a2 * w * p, 1 / a2);\n else x3 = 1 - Math.pow(b * w * (1 - p), 1 / b);\n }\n afac = -gammaln(a2) - gammaln(b) + gammaln(a2 + b);\n for (; j < 10; j++) {\n if (x3 === 0 || x3 === 1) return x3;\n err = ibeta(x3, a2, b) - p;\n t = Math.exp(a1 * Math.log(x3) + b1 * Math.log(1 - x3) + afac);\n u4 = err / t;\n x3 -= t = u4 / (1 - 0.5 * Math.min(1, u4 * (a1 / x3 - b1 / (1 - x3))));\n if (x3 <= 0) x3 = 0.5 * (x3 + t);\n if (x3 >= 1) x3 = 0.5 * (x3 + t + 1);\n if (Math.abs(t) < EPS2 * x3 && j > 0) break;\n }\n return x3;\n}\nfunction ibeta(x3, a2, b) {\n var bt = x3 === 0 || x3 === 1 ? 0 : Math.exp(gammaln(a2 + b) - gammaln(a2) - gammaln(b) + a2 * Math.log(x3) + b * Math.log(1 - x3));\n if (x3 < 0 || x3 > 1) return false;\n if (x3 < (a2 + 1) / (a2 + b + 2))\n return bt * betacf(x3, a2, b) / a2;\n return 1 - bt * betacf(1 - x3, b, a2) / b;\n}\nfunction betacf(x3, a2, b) {\n var fpmin = 1e-30;\n var m = 1;\n var qab = a2 + b;\n var qap = a2 + 1;\n var qam = a2 - 1;\n var c4 = 1;\n var d = 1 - qab * x3 / qap;\n var m2, aa2, del, h;\n if (Math.abs(d) < fpmin) d = fpmin;\n d = 1 / d;\n h = d;\n for (; m <= 100; m++) {\n m2 = 2 * m;\n aa2 = m * (b - m) * x3 / ((qam + m2) * (a2 + m2));\n d = 1 + aa2 * d;\n if (Math.abs(d) < fpmin) d = fpmin;\n c4 = 1 + aa2 / c4;\n if (Math.abs(c4) < fpmin) c4 = fpmin;\n d = 1 / d;\n h *= d * c4;\n aa2 = -(a2 + m) * (qab + m) * x3 / ((a2 + m2) * (qap + m2));\n d = 1 + aa2 * d;\n if (Math.abs(d) < fpmin) d = fpmin;\n c4 = 1 + aa2 / c4;\n if (Math.abs(c4) < fpmin) c4 = fpmin;\n d = 1 / d;\n del = d * c4;\n h *= del;\n if (Math.abs(del - 1) < 3e-7) break;\n }\n return h;\n}\nfunction gammaln(x3) {\n var j = 0;\n var cof = [\n 76.18009172947146,\n -86.5053203294167,\n 24.01409824083091,\n -1.231739572450155,\n 0.001208650973866179,\n -5395239384953e-18\n ];\n var ser = 1.000000000190015;\n var xx, y3, tmp;\n tmp = (y3 = xx = x3) + 5.5;\n tmp -= (xx + 0.5) * Math.log(tmp);\n for (; j < 6; j++) ser += cof[j] / ++y3;\n return Math.log(2.506628274631 * ser / xx) - tmp;\n}\nfunction qt(p, dof) {\n var x3 = ibetainv(2 * Math.min(p, 1 - p), 0.5 * dof, 0.5);\n x3 = Math.sqrt(dof * (1 - x3) / x3);\n return p > 0.5 ? x3 : -x3;\n}\n\n// ../../node_modules/@observablehq/plot/src/marks/linearRegression.js\nvar defaults21 = {\n ariaLabel: \"linear-regression\",\n fill: \"currentColor\",\n fillOpacity: 0.1,\n stroke: \"currentColor\",\n strokeWidth: 1.5,\n strokeLinecap: \"round\",\n strokeLinejoin: \"round\",\n strokeMiterlimit: 1\n};\nvar LinearRegression = class extends Mark {\n constructor(data, options = {}) {\n const { x: x3, y: y3, z, ci = 0.95, precision = 4 } = options;\n super(\n data,\n {\n x: { value: x3, scale: \"x\" },\n y: { value: y3, scale: \"y\" },\n z: { value: maybeZ(options), optional: true }\n },\n options,\n defaults21\n );\n this.z = z;\n this.ci = +ci;\n this.precision = +precision;\n if (!(0 <= this.ci && this.ci < 1)) throw new Error(`invalid ci; not in [0, 1): ${ci}`);\n if (!(this.precision > 0)) throw new Error(`invalid precision: ${precision}`);\n }\n render(index2, scales2, channels, dimensions, context) {\n const { x: X3, y: Y3, z: Z } = channels;\n const { ci } = this;\n return create4(\"svg:g\", context).call(applyIndirectStyles, this, dimensions, context).call(applyTransform, this, scales2).call(\n (g) => g.selectAll().data(Z ? groupZ2(index2, Z, this.z) : [index2]).enter().call(\n (enter) => enter.append(\"path\").attr(\"fill\", \"none\").call(applyDirectStyles, this).call(applyGroupedChannelStyles, this, { ...channels, fill: null, fillOpacity: null }).attr(\"d\", (I) => this._renderLine(I, X3, Y3)).call(\n ci && !isNone(this.fill) ? (path2) => path2.select(pathBefore).attr(\"stroke\", \"none\").call(applyDirectStyles, this).call(applyGroupedChannelStyles, this, {\n ...channels,\n stroke: null,\n strokeOpacity: null,\n strokeWidth: null\n }).attr(\"d\", (I) => this._renderBand(I, X3, Y3)) : () => {\n }\n )\n )\n ).node();\n }\n};\nfunction pathBefore() {\n return this.parentNode.insertBefore(this.ownerDocument.createElementNS(namespaces_default.svg, \"path\"), this);\n}\nvar LinearRegressionX = class extends LinearRegression {\n constructor(data, options) {\n super(data, options);\n }\n _renderBand(I, X3, Y3) {\n const { ci, precision } = this;\n const [y12, y22] = extent(I, (i) => Y3[i]);\n const f = linearRegressionF(I, Y3, X3);\n const g = confidenceIntervalF(I, Y3, X3, (1 - ci) / 2, f);\n return area_default3().y((y3) => y3).x0((y3) => g(y3, -1)).x1((y3) => g(y3, 1))(range(y12, y22 - precision / 2, precision).concat(y22));\n }\n _renderLine(I, X3, Y3) {\n const [y12, y22] = extent(I, (i) => Y3[i]);\n const f = linearRegressionF(I, Y3, X3);\n return `M${f(y12)},${y12}L${f(y22)},${y22}`;\n }\n};\nvar LinearRegressionY = class extends LinearRegression {\n constructor(data, options) {\n super(data, options);\n }\n _renderBand(I, X3, Y3) {\n const { ci, precision } = this;\n const [x12, x22] = extent(I, (i) => X3[i]);\n const f = linearRegressionF(I, X3, Y3);\n const g = confidenceIntervalF(I, X3, Y3, (1 - ci) / 2, f);\n return area_default3().x((x3) => x3).y0((x3) => g(x3, -1)).y1((x3) => g(x3, 1))(range(x12, x22 - precision / 2, precision).concat(x22));\n }\n _renderLine(I, X3, Y3) {\n const [x12, x22] = extent(I, (i) => X3[i]);\n const f = linearRegressionF(I, X3, Y3);\n return `M${x12},${f(x12)}L${x22},${f(x22)}`;\n }\n};\nfunction linearRegressionX(data, { y: y3 = indexOf, x: x3 = identity7, stroke, fill = isNoneish(stroke) ? \"currentColor\" : stroke, ...options } = {}) {\n return new LinearRegressionX(data, maybeDenseIntervalY({ ...options, x: x3, y: y3, fill, stroke }));\n}\nfunction linearRegressionY(data, { x: x3 = indexOf, y: y3 = identity7, stroke, fill = isNoneish(stroke) ? \"currentColor\" : stroke, ...options } = {}) {\n return new LinearRegressionY(data, maybeDenseIntervalX({ ...options, x: x3, y: y3, fill, stroke }));\n}\nfunction linearRegressionF(I, X3, Y3) {\n let sumX = 0, sumY = 0, sumXY = 0, sumX2 = 0;\n for (const i of I) {\n const xi = X3[i];\n const yi = Y3[i];\n sumX += xi;\n sumY += yi;\n sumXY += xi * yi;\n sumX2 += xi * xi;\n }\n const n = I.length;\n const slope = (n * sumXY - sumX * sumY) / (n * sumX2 - sumX * sumX);\n const intercept = (sumY - slope * sumX) / n;\n return (x3) => slope * x3 + intercept;\n}\nfunction confidenceIntervalF(I, X3, Y3, p, f) {\n const mean3 = sum2(I, (i) => X3[i]) / I.length;\n let a2 = 0, b = 0;\n for (const i of I) {\n a2 += (X3[i] - mean3) ** 2;\n b += (Y3[i] - f(X3[i])) ** 2;\n }\n const sy = Math.sqrt(b / (I.length - 2));\n const t = qt(p, I.length - 2);\n return (x3, k2) => {\n const Y4 = f(x3);\n const se = sy * Math.sqrt(1 / I.length + (x3 - mean3) ** 2 / a2);\n return Y4 + k2 * t * se;\n };\n}\n\n// ../../node_modules/@observablehq/plot/src/transforms/tree.js\nfunction treeNode({\n path: path2 = identity7,\n // the delimited path\n delimiter,\n // how the path is separated\n frameAnchor,\n treeLayout = tree_default,\n treeSort,\n treeSeparation,\n treeAnchor,\n treeFilter,\n ...options\n} = {}) {\n treeAnchor = maybeTreeAnchor(treeAnchor);\n treeSort = maybeTreeSort(treeSort);\n if (treeFilter != null) treeFilter = maybeNodeValue(treeFilter);\n if (frameAnchor === void 0) frameAnchor = treeAnchor.frameAnchor;\n const normalize4 = normalizer(delimiter);\n const outputs = treeOutputs(options, maybeNodeValue);\n const [X3, setX] = column2();\n const [Y3, setY] = column2();\n return {\n x: X3,\n y: Y3,\n frameAnchor,\n ...basic(options, (data, facets) => {\n const P = normalize4(valueof(data, path2));\n const X4 = setX([]);\n const Y4 = setY([]);\n let treeIndex = -1;\n const treeData = [];\n const treeFacets = [];\n const rootof = stratify_default().path((i) => P[i]);\n const setData = isArray2(data) ? (node) => node.data = data[node.data] : (node) => node.data = data.get(node.data);\n const layout = treeLayout();\n if (layout.nodeSize) layout.nodeSize([1, 1]);\n if (layout.separation && treeSeparation !== void 0) layout.separation(treeSeparation ?? one2);\n for (const o of outputs) o[output_values] = o[output_setValues]([]);\n for (const facet of facets) {\n const treeFacet = [];\n const root2 = rootof(facet.filter((i) => P[i] != null)).each(setData);\n if (treeSort != null) root2.sort(treeSort);\n layout(root2);\n for (const node of root2.descendants()) {\n if (treeFilter != null && !treeFilter(node)) continue;\n treeFacet.push(++treeIndex);\n treeData[treeIndex] = node.data;\n treeAnchor.position(node, treeIndex, X4, Y4);\n for (const o of outputs) o[output_values][treeIndex] = o[output_evaluate](node);\n }\n treeFacets.push(treeFacet);\n }\n return { data: treeData, facets: treeFacets };\n }),\n ...Object.fromEntries(outputs)\n };\n}\nfunction treeLink({\n path: path2 = identity7,\n // the delimited path\n delimiter,\n // how the path is separated\n curve = \"bump-x\",\n stroke = \"#555\",\n strokeWidth = 1.5,\n strokeOpacity = 0.5,\n treeLayout = tree_default,\n treeSort,\n treeSeparation,\n treeAnchor,\n treeFilter,\n ...options\n} = {}) {\n treeAnchor = maybeTreeAnchor(treeAnchor);\n treeSort = maybeTreeSort(treeSort);\n if (treeFilter != null) treeFilter = maybeLinkValue(treeFilter);\n options = { curve, stroke, strokeWidth, strokeOpacity, ...options };\n const normalize4 = normalizer(delimiter);\n const outputs = treeOutputs(options, maybeLinkValue);\n const [X13, setX1] = column2();\n const [X23, setX2] = column2();\n const [Y13, setY1] = column2();\n const [Y23, setY2] = column2();\n return {\n x1: X13,\n x2: X23,\n y1: Y13,\n y2: Y23,\n ...basic(options, (data, facets) => {\n const P = normalize4(valueof(data, path2));\n const X14 = setX1([]);\n const X24 = setX2([]);\n const Y14 = setY1([]);\n const Y24 = setY2([]);\n let treeIndex = -1;\n const treeData = [];\n const treeFacets = [];\n const rootof = stratify_default().path((i) => P[i]);\n const layout = treeLayout();\n if (layout.nodeSize) layout.nodeSize([1, 1]);\n if (layout.separation && treeSeparation !== void 0) layout.separation(treeSeparation ?? one2);\n for (const o of outputs) o[output_values] = o[output_setValues]([]);\n for (const facet of facets) {\n const treeFacet = [];\n const root2 = rootof(facet.filter((i) => P[i] != null)).each((node) => node.data = data[node.data]);\n if (treeSort != null) root2.sort(treeSort);\n layout(root2);\n for (const { source, target } of root2.links()) {\n if (treeFilter != null && !treeFilter(target, source)) continue;\n treeFacet.push(++treeIndex);\n treeData[treeIndex] = target.data;\n treeAnchor.position(source, treeIndex, X14, Y14);\n treeAnchor.position(target, treeIndex, X24, Y24);\n for (const o of outputs) o[output_values][treeIndex] = o[output_evaluate](target, source);\n }\n treeFacets.push(treeFacet);\n }\n return { data: treeData, facets: treeFacets };\n }),\n ...Object.fromEntries(outputs)\n };\n}\nfunction maybeTreeAnchor(anchor = \"left\") {\n switch (`${anchor}`.trim().toLowerCase()) {\n case \"left\":\n return treeAnchorLeft;\n case \"right\":\n return treeAnchorRight;\n }\n throw new Error(`invalid tree anchor: ${anchor}`);\n}\nvar treeAnchorLeft = {\n frameAnchor: \"left\",\n dx: 6,\n position({ x: x3, y: y3 }, i, X3, Y3) {\n X3[i] = y3;\n Y3[i] = -x3;\n }\n};\nvar treeAnchorRight = {\n frameAnchor: \"right\",\n dx: -6,\n position({ x: x3, y: y3 }, i, X3, Y3) {\n X3[i] = -y3;\n Y3[i] = -x3;\n }\n};\nfunction maybeTreeSort(sort3) {\n return sort3 == null || typeof sort3 === \"function\" ? sort3 : `${sort3}`.trim().toLowerCase().startsWith(\"node:\") ? nodeSort(maybeNodeValue(sort3)) : nodeSort(nodeData(sort3));\n}\nfunction nodeSort(value) {\n return (a2, b) => ascendingDefined2(value(a2), value(b));\n}\nfunction nodeData(field3) {\n return (node) => node.data?.[field3];\n}\nfunction normalizer(delimiter = \"/\") {\n delimiter = `${delimiter}`;\n if (delimiter === \"/\") return (P) => P;\n if (delimiter.length !== 1) throw new Error(\"delimiter must be exactly one character\");\n const delimiterCode = delimiter.charCodeAt(0);\n return (P) => P.map((p) => slashDelimiter(p, delimiterCode));\n}\nvar CODE_BACKSLASH = 92;\nvar CODE_SLASH = 47;\nfunction slashDelimiter(input3, delimiterCode) {\n if (delimiterCode === CODE_BACKSLASH) throw new Error(\"delimiter cannot be backslash\");\n let afterBackslash = false;\n for (let i = 0, n = input3.length; i < n; ++i) {\n switch (input3.charCodeAt(i)) {\n case CODE_BACKSLASH:\n if (!afterBackslash) {\n afterBackslash = true;\n continue;\n }\n break;\n case delimiterCode:\n if (afterBackslash) {\n input3 = input3.slice(0, i - 1) + input3.slice(i), --i, --n;\n } else {\n input3 = input3.slice(0, i) + \"/\" + input3.slice(i + 1);\n }\n break;\n case CODE_SLASH:\n if (afterBackslash) {\n input3 = input3.slice(0, i) + \"\\\\\\\\\" + input3.slice(i), i += 2, n += 2;\n } else {\n input3 = input3.slice(0, i) + \"\\\\\" + input3.slice(i), ++i, ++n;\n }\n break;\n }\n afterBackslash = false;\n }\n return input3;\n}\nfunction slashUnescape(input3) {\n let afterBackslash = false;\n for (let i = 0, n = input3.length; i < n; ++i) {\n switch (input3.charCodeAt(i)) {\n case CODE_BACKSLASH:\n if (!afterBackslash) {\n afterBackslash = true;\n continue;\n }\n // eslint-disable-next-line no-fallthrough\n case CODE_SLASH:\n if (afterBackslash) {\n input3 = input3.slice(0, i - 1) + input3.slice(i), --i, --n;\n }\n break;\n }\n afterBackslash = false;\n }\n return input3;\n}\nfunction isNodeValue(option) {\n return isObject(option) && typeof option.node === \"function\";\n}\nfunction isLinkValue(option) {\n return isObject(option) && typeof option.link === \"function\";\n}\nfunction maybeNodeValue(value) {\n if (isNodeValue(value)) return value.node;\n value = `${value}`.trim().toLowerCase();\n if (!value.startsWith(\"node:\")) return;\n switch (value) {\n case \"node:name\":\n return nodeName;\n case \"node:path\":\n return nodePath;\n case \"node:internal\":\n return nodeInternal;\n case \"node:external\":\n return nodeExternal;\n case \"node:depth\":\n return nodeDepth;\n case \"node:height\":\n return nodeHeight;\n }\n throw new Error(`invalid node value: ${value}`);\n}\nfunction maybeLinkValue(value) {\n if (isNodeValue(value)) return value.node;\n if (isLinkValue(value)) return value.link;\n value = `${value}`.trim().toLowerCase();\n if (!value.startsWith(\"node:\") && !value.startsWith(\"parent:\")) return;\n switch (value) {\n case \"parent:name\":\n return parentValue(nodeName);\n case \"parent:path\":\n return parentValue(nodePath);\n case \"parent:depth\":\n return parentValue(nodeDepth);\n case \"parent:height\":\n return parentValue(nodeHeight);\n case \"node:name\":\n return nodeName;\n case \"node:path\":\n return nodePath;\n case \"node:internal\":\n return nodeInternal;\n case \"node:external\":\n return nodeExternal;\n case \"node:depth\":\n return nodeDepth;\n case \"node:height\":\n return nodeHeight;\n }\n throw new Error(`invalid link value: ${value}`);\n}\nfunction nodePath(node) {\n return node.id;\n}\nfunction nodeName(node) {\n return nameof(node.id);\n}\nfunction nodeDepth(node) {\n return node.depth;\n}\nfunction nodeHeight(node) {\n return node.height;\n}\nfunction nodeInternal(node) {\n return !!node.children;\n}\nfunction nodeExternal(node) {\n return !node.children;\n}\nfunction parentValue(evaluate) {\n return (child, parent) => parent == null ? void 0 : evaluate(parent);\n}\nfunction nameof(path2) {\n let i = path2.length;\n while (--i > 0) if (slash2(path2, i)) break;\n return slashUnescape(path2.slice(i + 1));\n}\nfunction slash2(path2, i) {\n if (path2[i] === \"/\") {\n let k2 = 0;\n while (i > 0 && path2[--i] === \"\\\\\") ++k2;\n if ((k2 & 1) === 0) return true;\n }\n return false;\n}\nvar output_setValues = 2;\nvar output_evaluate = 3;\nvar output_values = 4;\nfunction treeOutputs(options, maybeTreeValue) {\n const outputs = [];\n for (const name2 in options) {\n const value = options[name2];\n const treeValue = maybeTreeValue(value);\n if (treeValue !== void 0) {\n outputs.push([name2, ...column2(value), treeValue]);\n }\n }\n return outputs;\n}\n\n// ../../node_modules/@observablehq/plot/src/marks/tree.js\nfunction tree(data, {\n fill,\n stroke,\n strokeWidth,\n strokeOpacity,\n strokeLinejoin,\n strokeLinecap,\n strokeMiterlimit,\n strokeDasharray,\n strokeDashoffset,\n marker,\n markerStart = marker,\n markerEnd = marker,\n dot: dotDot = isNoneish(markerStart) && isNoneish(markerEnd),\n text: textText = \"node:name\",\n textStroke = \"var(--plot-background)\",\n title = \"node:path\",\n dx,\n dy,\n textAnchor,\n treeLayout = tree_default,\n textLayout = treeLayout === tree_default || treeLayout === cluster_default ? \"mirrored\" : \"normal\",\n tip: tip2,\n ...options\n} = {}) {\n if (dx === void 0) dx = maybeTreeAnchor(options.treeAnchor).dx;\n if (textAnchor !== void 0) throw new Error(\"textAnchor is not a configurable tree option\");\n textLayout = keyword(textLayout, \"textLayout\", [\"mirrored\", \"normal\"]);\n function treeText(textOptions2) {\n return text(\n data,\n treeNode({\n treeLayout,\n text: textText,\n fill: fill === void 0 ? \"currentColor\" : fill,\n stroke: textStroke,\n dx,\n dy,\n title,\n ...textOptions2,\n ...options\n })\n );\n }\n return marks(\n link2(\n data,\n treeLink({\n treeLayout,\n markerStart,\n markerEnd,\n stroke: stroke !== void 0 ? stroke : fill === void 0 ? \"node:internal\" : fill,\n strokeWidth,\n strokeOpacity,\n strokeLinejoin,\n strokeLinecap,\n strokeMiterlimit,\n strokeDasharray,\n strokeDashoffset,\n ...options\n })\n ),\n dotDot ? dot(data, treeNode({ treeLayout, fill: fill === void 0 ? \"node:internal\" : fill, title, tip: tip2, ...options })) : null,\n textText != null ? textLayout === \"mirrored\" ? [\n treeText({ textAnchor: \"start\", treeFilter: \"node:external\" }),\n treeText({ textAnchor: \"end\", treeFilter: \"node:internal\", dx: -dx })\n ] : treeText() : null\n );\n}\nfunction cluster(data, options) {\n return tree(data, { ...options, treeLayout: cluster_default });\n}\n\n// ../../node_modules/@observablehq/plot/src/marks/waffle.js\nvar waffleDefaults = {\n ariaLabel: \"waffle\"\n};\nvar WaffleX = class extends BarX {\n constructor(data, { unit: unit3 = 1, gap = 1, round: round2, render, multiple, ...options } = {}) {\n super(data, { ...options, render: composeRender(render, waffleRender(\"x\")) }, waffleDefaults);\n this.unit = Math.max(0, unit3);\n this.gap = +gap;\n this.round = maybeRound2(round2);\n this.multiple = maybeMultiple(multiple);\n }\n};\nvar WaffleY = class extends BarY {\n constructor(data, { unit: unit3 = 1, gap = 1, round: round2, render, multiple, ...options } = {}) {\n super(data, { ...options, render: composeRender(render, waffleRender(\"y\")) }, waffleDefaults);\n this.unit = Math.max(0, unit3);\n this.gap = +gap;\n this.round = maybeRound2(round2);\n this.multiple = maybeMultiple(multiple);\n }\n};\nfunction waffleRender(y3) {\n return function(index2, scales2, values2, dimensions, context) {\n const { unit: unit3, gap, rx, ry, round: round2 } = this;\n const { document: document2 } = context;\n const Y13 = values2.channels[`${y3}1`].value;\n const Y23 = values2.channels[`${y3}2`].value;\n const barwidth = this[y3 === \"y\" ? \"_width\" : \"_height\"](scales2, values2, dimensions);\n const barx = this[y3 === \"y\" ? \"_x\" : \"_y\"](scales2, values2, dimensions);\n const scale3 = unit3 * scaleof(scales2.scales[y3]);\n const { multiple = Math.max(1, Math.floor(Math.sqrt(barwidth / scale3))) } = this;\n const cx = Math.min(barwidth / multiple, scale3 * multiple);\n const cy = scale3 * multiple;\n const transform3 = y3 === \"y\" ? ([x3, y4]) => [x3 * cx, -y4 * cy] : ([x3, y4]) => [y4 * cy, x3 * cx];\n const tx = (barwidth - multiple * cx) / 2;\n const x06 = typeof barx === \"function\" ? (i) => barx(i) + tx : barx + tx;\n const y06 = scales2[y3](0);\n const patternId = getPatternId();\n const basePattern = document2.createElementNS(namespaces_default.svg, \"pattern\");\n basePattern.setAttribute(\"width\", y3 === \"y\" ? cx : cy);\n basePattern.setAttribute(\"height\", y3 === \"y\" ? cy : cx);\n basePattern.setAttribute(\"patternUnits\", \"userSpaceOnUse\");\n const basePatternRect = basePattern.appendChild(document2.createElementNS(namespaces_default.svg, \"rect\"));\n basePatternRect.setAttribute(\"x\", gap / 2);\n basePatternRect.setAttribute(\"y\", gap / 2);\n basePatternRect.setAttribute(\"width\", (y3 === \"y\" ? cx : cy) - gap);\n basePatternRect.setAttribute(\"height\", (y3 === \"y\" ? cy : cx) - gap);\n if (rx != null) basePatternRect.setAttribute(\"rx\", rx);\n if (ry != null) basePatternRect.setAttribute(\"ry\", ry);\n return create4(\"svg:g\", context).call(applyIndirectStyles, this, dimensions, context).call(this._transform, this, scales2).call(\n (g) => g.selectAll().data(index2).enter().append(() => basePattern.cloneNode(true)).attr(\"id\", (i) => `${patternId}-${i}`).select(\"rect\").call(applyDirectStyles, this).call(applyChannelStyles, this, values2)\n ).call(\n (g) => g.selectAll().data(index2).enter().append(\"path\").attr(\"transform\", y3 === \"y\" ? template`translate(${x06},${y06})` : template`translate(${y06},${x06})`).attr(\n \"d\",\n (i) => `M${wafflePoints(round2(Y13[i] / unit3), round2(Y23[i] / unit3), multiple).map(transform3).join(\"L\")}Z`\n ).attr(\"fill\", (i) => `url(#${patternId}-${i})`).attr(\"stroke\", this.stroke == null ? null : (i) => `url(#${patternId}-${i})`)\n ).node();\n };\n}\nfunction wafflePoints(i1, i2, columns) {\n if (i1 < 0 || i2 < 0) {\n const k2 = Math.ceil(-Math.min(i1, i2) / columns);\n return wafflePoints(i1 + k2 * columns, i2 + k2 * columns, columns).map(([x3, y3]) => [x3, y3 - k2]);\n }\n if (i2 < i1) {\n return wafflePoints(i2, i1, columns);\n }\n return [\n [0, Math.ceil(i1 / columns)],\n [Math.floor(i1 % columns), Math.ceil(i1 / columns)],\n [Math.floor(i1 % columns), Math.floor(i1 / columns) + i1 % 1],\n [Math.ceil(i1 % columns), Math.floor(i1 / columns) + i1 % 1],\n ...i1 % columns > columns - 1 ? [] : [\n [Math.ceil(i1 % columns), Math.floor(i1 / columns)],\n [columns, Math.floor(i1 / columns)]\n ],\n [columns, Math.floor(i2 / columns)],\n [Math.ceil(i2 % columns), Math.floor(i2 / columns)],\n [Math.ceil(i2 % columns), Math.floor(i2 / columns) + i2 % 1],\n [Math.floor(i2 % columns), Math.floor(i2 / columns) + i2 % 1],\n ...i2 % columns < 1 ? [] : [\n [Math.floor(i2 % columns), Math.ceil(i2 / columns)],\n [0, Math.ceil(i2 / columns)]\n ]\n ];\n}\nfunction maybeRound2(round2) {\n if (round2 === void 0 || round2 === false) return Number;\n if (round2 === true) return Math.round;\n if (typeof round2 !== \"function\") throw new Error(`invalid round: ${round2}`);\n return round2;\n}\nfunction maybeMultiple(multiple) {\n return multiple === void 0 ? void 0 : Math.max(1, Math.floor(multiple));\n}\nfunction scaleof({ domain, range: range3 }) {\n return spread(range3) / spread(domain);\n}\nfunction spread(domain) {\n const [min5, max4] = extent(domain);\n return max4 - min5;\n}\nfunction waffleX(data, options = {}) {\n if (!hasXY(options)) options = { ...options, y: indexOf, x2: identity7 };\n return new WaffleX(data, maybeStackX(maybeIntervalX(maybeIdentityX(options))));\n}\nfunction waffleY(data, options = {}) {\n if (!hasXY(options)) options = { ...options, x: indexOf, y2: identity7 };\n return new WaffleY(data, maybeStackY(maybeIntervalY(maybeIdentityY(options))));\n}\n\n// ../../node_modules/@observablehq/plot/src/transforms/dodge.js\nvar import_interval_tree_1d = __toESM(require_interval_tree(), 1);\nvar anchorXLeft = ({ marginLeft: marginLeft2 }) => [1, marginLeft2];\nvar anchorXRight = ({ width: width2, marginRight: marginRight2 }) => [-1, width2 - marginRight2];\nvar anchorXMiddle = ({ width: width2, marginLeft: marginLeft2, marginRight: marginRight2 }) => [0, (marginLeft2 + width2 - marginRight2) / 2];\nvar anchorYTop = ({ marginTop: marginTop2 }) => [1, marginTop2];\nvar anchorYBottom = ({ height: height2, marginBottom: marginBottom2 }) => [-1, height2 - marginBottom2];\nvar anchorYMiddle = ({ height: height2, marginTop: marginTop2, marginBottom: marginBottom2 }) => [0, (marginTop2 + height2 - marginBottom2) / 2];\nfunction maybeAnchor4(anchor) {\n return typeof anchor === \"string\" ? { anchor } : anchor;\n}\nfunction dodgeX(dodgeOptions = {}, options = {}) {\n if (arguments.length === 1) [dodgeOptions, options] = mergeOptions3(dodgeOptions);\n let { anchor = \"left\", padding: padding2 = 1, r = options.r } = maybeAnchor4(dodgeOptions);\n switch (`${anchor}`.toLowerCase()) {\n case \"left\":\n anchor = anchorXLeft;\n break;\n case \"right\":\n anchor = anchorXRight;\n break;\n case \"middle\":\n anchor = anchorXMiddle;\n break;\n default:\n throw new Error(`unknown dodge anchor: ${anchor}`);\n }\n return dodge(\"x\", \"y\", anchor, number5(padding2), r, options);\n}\nfunction dodgeY(dodgeOptions = {}, options = {}) {\n if (arguments.length === 1) [dodgeOptions, options] = mergeOptions3(dodgeOptions);\n let { anchor = \"bottom\", padding: padding2 = 1, r = options.r } = maybeAnchor4(dodgeOptions);\n switch (`${anchor}`.toLowerCase()) {\n case \"top\":\n anchor = anchorYTop;\n break;\n case \"bottom\":\n anchor = anchorYBottom;\n break;\n case \"middle\":\n anchor = anchorYMiddle;\n break;\n default:\n throw new Error(`unknown dodge anchor: ${anchor}`);\n }\n return dodge(\"y\", \"x\", anchor, number5(padding2), r, options);\n}\nfunction mergeOptions3(options) {\n const { anchor, padding: padding2, ...rest } = options;\n const { r } = rest;\n return [{ anchor, padding: padding2, r }, rest];\n}\nfunction dodge(y3, x3, anchor, padding2, r, options) {\n if (r != null && typeof r !== \"number\") {\n let { channels, sort: sort3, reverse: reverse3 } = options;\n channels = maybeNamed(channels);\n if (channels?.r === void 0) options = { ...options, channels: { ...channels, r: { value: r, scale: \"r\" } } };\n if (sort3 === void 0 && reverse3 === void 0) options.sort = { channel: \"-r\" };\n }\n return initializer(options, function(data, facets, channels, scales2, dimensions, context) {\n let { [x3]: X3, r: R } = channels;\n if (!channels[x3]) throw new Error(`missing channel: ${x3}`);\n ({ [x3]: X3 } = applyPosition(channels, scales2, context));\n const cr = R ? void 0 : r !== void 0 ? number5(r) : this.r !== void 0 ? this.r : 3;\n if (R) R = valueof(R.value, scales2[R.scale] || identity7, Float64Array);\n let [ky2, ty] = anchor(dimensions);\n const compare = ky2 ? compareAscending : compareSymmetric;\n const Y3 = new Float64Array(X3.length);\n const radius2 = R ? (i) => R[i] : () => cr;\n for (let I of facets) {\n const tree2 = (0, import_interval_tree_1d.default)();\n I = I.filter(R ? (i) => finite2(X3[i]) && positive(R[i]) : (i) => finite2(X3[i]));\n const intervals2 = new Float64Array(2 * I.length + 2);\n for (const i of I) {\n const ri = radius2(i);\n const y06 = ky2 ? ri + padding2 : 0;\n const l = X3[i] - ri;\n const h = X3[i] + ri;\n let k2 = 2;\n tree2.queryInterval(l - padding2, h + padding2, ([, , j]) => {\n const yj = Y3[j] - y06;\n const dx = X3[i] - X3[j];\n const dr = padding2 + (R ? R[i] + R[j] : 2 * cr);\n const dy = Math.sqrt(dr * dr - dx * dx);\n intervals2[k2++] = yj - dy;\n intervals2[k2++] = yj + dy;\n });\n let candidates = intervals2.slice(0, k2);\n if (ky2) candidates = candidates.filter((y4) => y4 >= 0);\n out: for (const y4 of candidates.sort(compare)) {\n for (let j = 0; j < k2; j += 2) {\n if (intervals2[j] + 1e-6 < y4 && y4 < intervals2[j + 1] - 1e-6) {\n continue out;\n }\n }\n Y3[i] = y4 + y06;\n break;\n }\n tree2.insert([l, h, i]);\n }\n }\n if (!ky2) ky2 = 1;\n for (const I of facets) {\n for (const i of I) {\n Y3[i] = Y3[i] * ky2 + ty;\n }\n }\n return {\n data,\n facets,\n channels: {\n [y3]: { value: Y3, source: null },\n // don’t show in tooltip\n [x3]: { value: X3, source: channels[x3] },\n ...R && { r: { value: R, source: channels.r } }\n }\n };\n });\n}\nfunction compareSymmetric(a2, b) {\n return Math.abs(a2) - Math.abs(b);\n}\nfunction compareAscending(a2, b) {\n return a2 - b;\n}\n\n// ../../node_modules/@observablehq/plot/src/transforms/normalize.js\nfunction normalizeX(basis2, options) {\n if (arguments.length === 1) ({ basis: basis2, ...options } = basis2);\n return mapX(normalize3(basis2), options);\n}\nfunction normalizeY(basis2, options) {\n if (arguments.length === 1) ({ basis: basis2, ...options } = basis2);\n return mapY(normalize3(basis2), options);\n}\nfunction normalize3(basis2) {\n if (basis2 === void 0) return normalizeFirst;\n if (typeof basis2 === \"function\") return normalizeBasis(taker(basis2));\n if (/^p\\d{2}$/i.test(basis2)) return normalizeAccessor(percentile(basis2));\n switch (`${basis2}`.toLowerCase()) {\n case \"deviation\":\n return normalizeDeviation;\n case \"first\":\n return normalizeFirst;\n case \"last\":\n return normalizeLast;\n case \"max\":\n return normalizeMax;\n case \"mean\":\n return normalizeMean;\n case \"median\":\n return normalizeMedian;\n case \"min\":\n return normalizeMin;\n case \"sum\":\n return normalizeSum;\n case \"extent\":\n return normalizeExtent;\n }\n throw new Error(`invalid basis: ${basis2}`);\n}\nfunction normalizeBasis(basis2) {\n return {\n mapIndex(I, S, T) {\n const b = +basis2(I, S);\n for (const i of I) {\n T[i] = S[i] === null ? NaN : S[i] / b;\n }\n }\n };\n}\nfunction normalizeAccessor(f) {\n return normalizeBasis((I, S) => f(I, (i) => S[i]));\n}\nvar normalizeExtent = {\n mapIndex(I, S, T) {\n const [s1, s2] = extent(I, (i) => S[i]);\n const d = s2 - s1;\n for (const i of I) {\n T[i] = S[i] === null ? NaN : (S[i] - s1) / d;\n }\n }\n};\nvar normalizeFirst = normalizeBasis((I, S) => {\n for (let i = 0; i < I.length; ++i) {\n const s2 = S[I[i]];\n if (defined(s2)) return s2;\n }\n});\nvar normalizeLast = normalizeBasis((I, S) => {\n for (let i = I.length - 1; i >= 0; --i) {\n const s2 = S[I[i]];\n if (defined(s2)) return s2;\n }\n});\nvar normalizeDeviation = {\n mapIndex(I, S, T) {\n const m = mean2(I, (i) => S[i]);\n const d = deviation(I, (i) => S[i]);\n for (const i of I) {\n T[i] = S[i] === null ? NaN : d ? (S[i] - m) / d : 0;\n }\n }\n};\nvar normalizeMax = normalizeAccessor(max2);\nvar normalizeMean = normalizeAccessor(mean2);\nvar normalizeMedian = normalizeAccessor(median2);\nvar normalizeMin = normalizeAccessor(min2);\nvar normalizeSum = normalizeAccessor(sum2);\n\n// ../../node_modules/@observablehq/plot/src/transforms/shift.js\nfunction shiftX(interval3, options) {\n return shiftK(\"x\", interval3, options);\n}\nfunction shiftY(interval3, options) {\n return shiftK(\"y\", interval3, options);\n}\nfunction shiftK(x3, interval3, options = {}) {\n let offset2;\n let k2 = 1;\n if (typeof interval3 === \"number\") {\n k2 = interval3;\n offset2 = (x4, k3) => +x4 + k3;\n } else {\n if (typeof interval3 === \"string\") {\n const sign3 = interval3.startsWith(\"-\") ? -1 : 1;\n [interval3, k2] = parseTimeInterval(interval3.replace(/^[+-]/, \"\"));\n k2 *= sign3;\n }\n interval3 = maybeInterval(interval3);\n offset2 = (x4, k3) => interval3.offset(x4, k3);\n }\n const x12 = `${x3}1`;\n const x22 = `${x3}2`;\n const mapped = map4(\n {\n [x12]: (D3) => D3.map((d) => offset2(d, k2)),\n [x22]: (D3) => D3\n },\n options\n );\n const t = mapped[x22].transform;\n mapped[x22].transform = () => {\n const V = t();\n const [x06, x13] = extent(V);\n V.domain = k2 < 0 ? [x06, offset2(x13, k2)] : [offset2(x06, k2), x13];\n return V;\n };\n return mapped;\n}\n\n// ../../node_modules/@observablehq/plot/src/transforms/select.js\nfunction select(selector, options = {}) {\n if (typeof selector === \"string\") {\n switch (selector.toLowerCase()) {\n case \"first\":\n return selectFirst(options);\n case \"last\":\n return selectLast(options);\n }\n }\n if (typeof selector === \"function\") {\n return selectChannel(null, selector, options);\n }\n let key, value;\n for (key in selector) {\n if (value !== void 0) throw new Error(\"ambiguous selector; multiple inputs\");\n value = maybeSelector(selector[key]);\n }\n if (value === void 0) throw new Error(`invalid selector: ${selector}`);\n return selectChannel(key, value, options);\n}\nfunction maybeSelector(selector) {\n if (typeof selector === \"function\") return selector;\n switch (`${selector}`.toLowerCase()) {\n case \"min\":\n return selectorMin;\n case \"max\":\n return selectorMax;\n }\n throw new Error(`unknown selector: ${selector}`);\n}\nfunction selectFirst(options) {\n return selectChannel(null, selectorFirst, options);\n}\nfunction selectLast(options) {\n return selectChannel(null, selectorLast, options);\n}\nfunction selectMinX(options) {\n return selectChannel(\"x\", selectorMin, options);\n}\nfunction selectMinY(options) {\n return selectChannel(\"y\", selectorMin, options);\n}\nfunction selectMaxX(options) {\n return selectChannel(\"x\", selectorMax, options);\n}\nfunction selectMaxY(options) {\n return selectChannel(\"y\", selectorMax, options);\n}\nfunction* selectorFirst(I) {\n yield I[0];\n}\nfunction* selectorLast(I) {\n yield I[I.length - 1];\n}\nfunction* selectorMin(I, X3) {\n yield least(I, (i) => X3[i]);\n}\nfunction* selectorMax(I, X3) {\n yield greatest(I, (i) => X3[i]);\n}\nfunction selectChannel(v2, selector, options) {\n if (v2 != null) {\n if (options[v2] == null) throw new Error(`missing channel: ${v2}`);\n v2 = options[v2];\n }\n const z = maybeZ(options);\n return basic(options, (data, facets) => {\n const Z = valueof(data, z);\n const V = valueof(data, v2);\n const selectFacets = [];\n for (const facet of facets) {\n const selectFacet = [];\n for (const I of Z ? group(facet, (i) => Z[i]).values() : [facet]) {\n for (const i of selector(I, V)) {\n selectFacet.push(i);\n }\n }\n selectFacets.push(selectFacet);\n }\n return { data, facets: selectFacets };\n });\n}\n\n// ../../node_modules/@observablehq/plot/src/index.js\nMark.prototype.plot = function({ marks: marks2 = [], ...options } = {}) {\n return plot({ ...options, marks: [...marks2, this] });\n};\n\n// ../plot/src/plot-attributes.js\nvar attributeMap = /* @__PURE__ */ new Map([\n [\"style\", \"style\"],\n [\"width\", \"width\"],\n [\"height\", \"height\"],\n [\"margin\", \"margin\"],\n [\"marginLeft\", \"marginLeft\"],\n [\"marginRight\", \"marginRight\"],\n [\"marginTop\", \"marginTop\"],\n [\"marginBottom\", \"marginBottom\"],\n [\"align\", \"align\"],\n [\"aspectRatio\", \"aspectRatio\"],\n [\"axis\", \"axis\"],\n [\"inset\", \"inset\"],\n [\"grid\", \"grid\"],\n [\"label\", \"label\"],\n [\"padding\", \"padding\"],\n [\"xScale\", \"x.type\"],\n [\"xDomain\", \"x.domain\"],\n [\"xRange\", \"x.range\"],\n [\"xNice\", \"x.nice\"],\n [\"xInset\", \"x.inset\"],\n [\"xInsetLeft\", \"x.insetLeft\"],\n [\"xInsetRight\", \"x.insetRight\"],\n [\"xClamp\", \"x.clamp\"],\n [\"xRound\", \"x.round\"],\n [\"xAlign\", \"x.align\"],\n [\"xPadding\", \"x.padding\"],\n [\"xPaddingInner\", \"x.paddingInner\"],\n [\"xPaddingOuter\", \"x.paddingOuter\"],\n [\"xAxis\", \"x.axis\"],\n [\"xTicks\", \"x.ticks\"],\n [\"xTickSize\", \"x.tickSize\"],\n [\"xTickSpacing\", \"x.tickSpacing\"],\n [\"xTickPadding\", \"x.tickPadding\"],\n [\"xTickFormat\", \"x.tickFormat\"],\n [\"xTickRotate\", \"x.tickRotate\"],\n [\"xGrid\", \"x.grid\"],\n [\"xLine\", \"x.line\"],\n [\"xLabel\", \"x.label\"],\n [\"xLabelAnchor\", \"x.labelAnchor\"],\n [\"xLabelArrow\", \"x.labelArrow\"],\n [\"xLabelOffset\", \"x.labelOffset\"],\n [\"xFontVariant\", \"x.fontVariant\"],\n [\"xAriaLabel\", \"x.ariaLabel\"],\n [\"xAriaDescription\", \"x.ariaDescription\"],\n [\"xPercent\", \"x.percent\"],\n [\"xReverse\", \"x.reverse\"],\n [\"xZero\", \"x.zero\"],\n [\"xBase\", \"x.base\"],\n [\"xExponent\", \"x.exponent\"],\n [\"xConstant\", \"x.constant\"],\n [\"yScale\", \"y.type\"],\n [\"yDomain\", \"y.domain\"],\n [\"yRange\", \"y.range\"],\n [\"yNice\", \"y.nice\"],\n [\"yInset\", \"y.inset\"],\n [\"yInsetTop\", \"y.insetTop\"],\n [\"yInsetBottom\", \"y.insetBottom\"],\n [\"yClamp\", \"y.clamp\"],\n [\"yRound\", \"y.round\"],\n [\"yAlign\", \"y.align\"],\n [\"yPadding\", \"y.padding\"],\n [\"yPaddingInner\", \"y.paddingInner\"],\n [\"yPaddingOuter\", \"y.paddingOuter\"],\n [\"yAxis\", \"y.axis\"],\n [\"yTicks\", \"y.ticks\"],\n [\"yTickSize\", \"y.tickSize\"],\n [\"yTickSpacing\", \"y.tickSpacing\"],\n [\"yTickPadding\", \"y.tickPadding\"],\n [\"yTickFormat\", \"y.tickFormat\"],\n [\"yTickRotate\", \"y.tickRotate\"],\n [\"yGrid\", \"y.grid\"],\n [\"yLine\", \"y.line\"],\n [\"yLabel\", \"y.label\"],\n [\"yLabelAnchor\", \"y.labelAnchor\"],\n [\"yLabelArrow\", \"y.labelArrow\"],\n [\"yLabelOffset\", \"y.labelOffset\"],\n [\"yFontVariant\", \"y.fontVariant\"],\n [\"yAriaLabel\", \"y.ariaLabel\"],\n [\"yAriaDescription\", \"y.ariaDescription\"],\n [\"yPercent\", \"y.percent\"],\n [\"yReverse\", \"y.reverse\"],\n [\"yZero\", \"y.zero\"],\n [\"yBase\", \"y.base\"],\n [\"yExponent\", \"y.exponent\"],\n [\"yConstant\", \"y.constant\"],\n [\"facetMargin\", \"facet.margin\"],\n [\"facetMarginTop\", \"facet.marginTop\"],\n [\"facetMarginBottom\", \"facet.marginBottom\"],\n [\"facetMarginLeft\", \"facet.marginLeft\"],\n [\"facetMarginRight\", \"facet.marginRight\"],\n [\"facetGrid\", \"facet.grid\"],\n [\"facetLabel\", \"facet.label\"],\n [\"fxDomain\", \"fx.domain\"],\n [\"fxRange\", \"fx.range\"],\n [\"fxInset\", \"fx.inset\"],\n [\"fxInsetLeft\", \"fx.insetLeft\"],\n [\"fxInsetRight\", \"fx.insetRight\"],\n [\"fxRound\", \"fx.round\"],\n [\"fxAlign\", \"fx.align\"],\n [\"fxPadding\", \"fx.padding\"],\n [\"fxPaddingInner\", \"fx.paddingInner\"],\n [\"fxPaddingOuter\", \"fx.paddingOuter\"],\n [\"fxAxis\", \"fx.axis\"],\n [\"fxTicks\", \"fx.ticks\"],\n [\"fxTickSize\", \"fx.tickSize\"],\n [\"fxTickSpacing\", \"fx.tickSpacing\"],\n [\"fxTickPadding\", \"fx.tickPadding\"],\n [\"fxTickFormat\", \"fx.tickFormat\"],\n [\"fxTickRotate\", \"fx.tickRotate\"],\n [\"fxGrid\", \"fx.grid\"],\n [\"fxLine\", \"fx.line\"],\n [\"fxLabel\", \"fx.label\"],\n [\"fxLabelAnchor\", \"fx.labelAnchor\"],\n [\"fxLabelOffset\", \"fx.labelOffset\"],\n [\"fxFontVariant\", \"fx.fontVariant\"],\n [\"fxAriaLabel\", \"fx.ariaLabel\"],\n [\"fxAriaDescription\", \"fx.ariaDescription\"],\n [\"fxReverse\", \"fx.reverse\"],\n [\"fyDomain\", \"fy.domain\"],\n [\"fyRange\", \"fy.range\"],\n [\"fyInset\", \"fy,inset\"],\n [\"fyInsetTop\", \"fy.insetTop\"],\n [\"fyInsetBottom\", \"fy.insetBottom\"],\n [\"fyRound\", \"fy.round\"],\n [\"fyAlign\", \"fy.align\"],\n [\"fyPadding\", \"fy.padding\"],\n [\"fyPaddingInner\", \"fy.paddingInner\"],\n [\"fyPaddingOuter\", \"fy.paddingOuter\"],\n [\"fyAxis\", \"fy.axis\"],\n [\"fyTicks\", \"fy.ticks\"],\n [\"fyTickSize\", \"fy.tickSize\"],\n [\"fyTickSpacing\", \"fy.tickSpacing\"],\n [\"fyTickPadding\", \"fy.tickPadding\"],\n [\"fyTickFormat\", \"fy.tickFormat\"],\n [\"fyTickRotate\", \"fy.tickRotate\"],\n [\"fyGrid\", \"fy.grid\"],\n [\"fyLine\", \"fy.line\"],\n [\"fyLabel\", \"fy.label\"],\n [\"fyLabelAnchor\", \"fy.labelAnchor\"],\n [\"fyLabelOffset\", \"fy.labelOffset\"],\n [\"fyFontVariant\", \"fy.fontVariant\"],\n [\"fyAriaLabel\", \"fy.ariaLabel\"],\n [\"fyAriaDescription\", \"fy.ariaDescription\"],\n [\"fyReverse\", \"fy.reverse\"],\n [\"colorScale\", \"color.type\"],\n [\"colorDomain\", \"color.domain\"],\n [\"colorRange\", \"color.range\"],\n [\"colorClamp\", \"color.clamp\"],\n [\"colorN\", \"color.n\"],\n [\"colorNice\", \"color.nice\"],\n [\"colorScheme\", \"color.scheme\"],\n [\"colorInterpolate\", \"color.interpolate\"],\n [\"colorPivot\", \"color.pivot\"],\n [\"colorSymmetric\", \"color.symmetric\"],\n [\"colorLabel\", \"color.label\"],\n [\"colorPercent\", \"color.percent\"],\n [\"colorReverse\", \"color.reverse\"],\n [\"colorZero\", \"color.zero\"],\n [\"colorTickFormat\", \"color.tickFormat\"],\n [\"colorBase\", \"color.base\"],\n [\"colorExponent\", \"color.exponent\"],\n [\"colorConstant\", \"color.constant\"],\n [\"opacityScale\", \"opacity.type\"],\n [\"opacityDomain\", \"opacity.domain\"],\n [\"opacityRange\", \"opacity.range\"],\n [\"opacityClamp\", \"opacity.clamp\"],\n [\"opacityNice\", \"opacity.nice\"],\n [\"opacityLabel\", \"opacity.label\"],\n [\"opacityPercent\", \"opacity.percent\"],\n [\"opacityReverse\", \"opacity.reverse\"],\n [\"opacityZero\", \"opacity.zero\"],\n [\"opacityTickFormat\", \"opacity.tickFormat\"],\n [\"opacityBase\", \"opacity.base\"],\n [\"opacityExponent\", \"opacity.exponent\"],\n [\"opacityConstant\", \"opacity.constant\"],\n [\"symbolScale\", \"symbol.type\"],\n [\"symbolDomain\", \"symbol.domain\"],\n [\"symbolRange\", \"symbol.range\"],\n [\"rScale\", \"r.type\"],\n [\"rDomain\", \"r.domain\"],\n [\"rRange\", \"r.range\"],\n [\"rClamp\", \"r.clamp\"],\n [\"rNice\", \"r.nice\"],\n [\"rLabel\", \"r.label\"],\n [\"rPercent\", \"r.percent\"],\n [\"rZero\", \"r.zero\"],\n [\"rBase\", \"r.base\"],\n [\"rExponent\", \"r.exponent\"],\n [\"rConstant\", \"r.constant\"],\n [\"lengthScale\", \"length.type\"],\n [\"lengthDomain\", \"length.domain\"],\n [\"lengthRange\", \"length.range\"],\n [\"lengthClamp\", \"length.clamp\"],\n [\"lengthNice\", \"length.nice\"],\n [\"lengthPercent\", \"length.percent\"],\n [\"lengthZero\", \"length.zero\"],\n [\"lengthBase\", \"length.base\"],\n [\"lengthExponent\", \"length.exponent\"],\n [\"lengthConstant\", \"length.constant\"],\n [\"projectionType\", \"projection.type\"],\n [\"projectionParallels\", \"projection.parallels\"],\n [\"projectionPrecision\", \"projection.precision\"],\n [\"projectionRotate\", \"projection.rotate\"],\n [\"projectionDomain\", \"projection.domain\"],\n [\"projectionInset\", \"projection.inset\"],\n [\"projectionInsetLeft\", \"projection.insetLeft\"],\n [\"projectionInsetRight\", \"projection.insetRight\"],\n [\"projectionInsetTop\", \"projection.insetTop\"],\n [\"projectionInsetBottom\", \"projection.insetBottom\"],\n [\"projectionClip\", \"projection.clip\"]\n]);\nfunction setProperty(object, path2, value) {\n for (let i = 0; i < path2.length; ++i) {\n const key = path2[i];\n if (i === path2.length - 1) {\n object[key] = value;\n } else {\n object = object[key] || (object[key] = {});\n }\n }\n}\nfunction setAttributes(attributes2, spec, symbols3) {\n for (const key in attributes2) {\n const specKey = attributeMap.get(key);\n if (specKey == null) {\n throw new Error(`Unrecognized plot attribute: ${key}`);\n }\n const value = attributes2[key];\n if (typeof value === \"symbol\") {\n symbols3.push(key);\n } else if (value !== void 0) {\n setProperty(spec, specKey.split(\".\"), value);\n }\n }\n}\n\n// ../plot/src/plot-renderer.js\nvar OPTIONS_ONLY_MARKS = /* @__PURE__ */ new Set([\n \"frame\",\n \"hexgrid\",\n \"sphere\",\n \"graticule\"\n]);\nvar SELECT_TRANSFORMS = /* @__PURE__ */ new Map([\n [\"first\", selectFirst],\n [\"last\", selectLast],\n [\"maxX\", selectMaxX],\n [\"maxY\", selectMaxY],\n [\"minX\", selectMinX],\n [\"minY\", selectMinY],\n [\"nearest\", pointer],\n [\"nearestX\", pointerX],\n [\"nearestXY\", pointerY]\n]);\nasync function plotRenderer(plot3) {\n const spec = { marks: [] };\n const symbols3 = [];\n const { attributes: attributes2, marks: marks2 } = plot3;\n setAttributes(attributes2, spec, symbols3);\n const indices2 = [];\n for (const mark2 of marks2) {\n for (const { type: type2, data, options } of mark2.plotSpecs()) {\n const { select: select2, ...rest } = options;\n const opt = SELECT_TRANSFORMS.get(select2)?.(rest) ?? rest;\n const arg = OPTIONS_ONLY_MARKS.has(type2) ? [opt] : [data, opt];\n spec.marks.push(src_exports[type2](...arg));\n indices2.push(mark2.index);\n }\n }\n inferLabels(spec, plot3);\n const svg = plot(spec);\n annotatePlot(svg, indices2);\n setSymbolAttributes(plot3, svg, attributes2, symbols3);\n for (const interactor2 of plot3.interactors) {\n await interactor2.init(svg);\n }\n return svg;\n}\nfunction setSymbolAttributes(plot3, svg, attributes2, symbols3) {\n symbols3.forEach((key) => {\n const value = attributes2[key];\n if (value === Fixed) {\n if (!key.endsWith(\"Domain\")) {\n throw new Error(`Unsupported fixed attribute: ${key}`);\n }\n const type2 = key.slice(0, -\"Domain\".length);\n const scale3 = svg.scale(type2);\n if (scale3?.domain) {\n plot3.setAttribute(key, attributes2[`${type2}Reverse`] ? scale3.domain.slice().reverse() : scale3.domain);\n }\n } else {\n throw new Error(`Unrecognized symbol: ${value}`);\n }\n });\n}\nfunction inferLabels(spec, plot3) {\n const { marks: marks2 } = plot3;\n inferLabel(\"x\", spec, marks2);\n inferLabel(\"y\", spec, marks2);\n inferLabel(\"fx\", spec, marks2);\n inferLabel(\"fy\", spec, marks2);\n}\nfunction inferLabel(key, spec, marks2) {\n const scale3 = spec[key] || {};\n if (scale3.axis === null || scale3.label !== void 0) return;\n const fields = marks2.map((mark2) => mark2.channelField(key)?.field);\n if (fields.every((x3) => x3 == null)) return;\n let candCol;\n let candLabel;\n let type2;\n for (let i = 0; i < fields.length; ++i) {\n const { column: column3, label: label2 } = fields[i] || {};\n if (column3 === void 0 && label2 === void 0) {\n continue;\n } else if (candCol === void 0 && candLabel === void 0) {\n candCol = column3;\n candLabel = label2;\n type2 = getType(marks2[i].data, key) || \"number\";\n } else if (candLabel !== label2) {\n candLabel = void 0;\n } else if (candCol !== column3) {\n candCol = void 0;\n }\n }\n let candidate = candLabel || candCol;\n if (candidate === void 0) return;\n if ((type2 === \"number\" || type2 === \"date\") && (key === \"x\" || key === \"y\")) {\n if (scale3.percent) candidate = `${candidate} (%)`;\n const order = (key === \"x\" ? 1 : -1) * (scale3.reverse ? -1 : 1);\n if (key === \"x\" || scale3.labelAnchor === \"center\") {\n candidate = key === \"x\" === order < 0 ? `\\u2190 ${candidate}` : `${candidate} \\u2192`;\n } else {\n candidate = `${order < 0 ? \"\\u2191 \" : \"\\u2193 \"}${candidate}`;\n }\n }\n spec[key] = { ...scale3, label: candidate };\n}\nfunction annotatePlot(svg, indices2) {\n const facets = svg.querySelectorAll('g[aria-label=\"facet\"]');\n if (facets.length) {\n for (const facet of facets) {\n annotateMarks(facet, indices2);\n }\n } else {\n annotateMarks(svg, indices2);\n }\n}\nfunction annotateMarks(svg, indices2) {\n let index2 = -1;\n for (const child of svg.children) {\n const aria = child.getAttribute(\"aria-label\") || \"\";\n const skip = child.nodeName === \"style\" || aria.includes(\"-axis\") || aria.includes(\"-grid\");\n if (!skip) {\n child.setAttribute(\"data-index\", indices2[++index2]);\n }\n }\n}\nfunction getType(data, channel) {\n if (!data) return;\n const { columns } = data;\n const col = columns[channel] ?? columns[channel + \"1\"] ?? columns[channel + \"2\"];\n if (col) {\n for (const v2 of col) {\n if (v2 != null) {\n return v2 instanceof Date ? \"date\" : typeof v2;\n }\n }\n }\n}\n\n// ../plot/src/plot.js\nvar DEFAULT_ATTRIBUTES = {\n width: 640,\n marginLeft: 40,\n marginRight: 20,\n marginTop: 20,\n marginBottom: 30\n};\nvar Plot = class {\n constructor(element) {\n this.attributes = { ...DEFAULT_ATTRIBUTES };\n this.listeners = null;\n this.interactors = [];\n this.legends = [];\n this.marks = [];\n this.markset = null;\n this.element = element || document.createElement(\"div\");\n this.element.setAttribute(\"class\", \"plot\");\n this.element.style.display = \"flex\";\n this.element.value = this;\n this.params = /* @__PURE__ */ new Map();\n this.synch = synchronizer();\n }\n margins() {\n return {\n left: this.getAttribute(\"marginLeft\"),\n top: this.getAttribute(\"marginTop\"),\n bottom: this.getAttribute(\"marginBottom\"),\n right: this.getAttribute(\"marginRight\")\n };\n }\n innerWidth() {\n const { left: left2, right: right2 } = this.margins();\n return this.getAttribute(\"width\") - left2 - right2;\n }\n innerHeight(defaultValue = 400) {\n const { top: top2, bottom: bottom2 } = this.margins();\n let h = this.getAttribute(\"height\");\n if (h == null) {\n h = maybeAspectRatio(this, top2, bottom2) || defaultValue;\n this.setAttribute(\"height\", h, { silent: true });\n }\n return h - top2 - bottom2;\n }\n pending(mark2) {\n this.synch.pending(mark2);\n }\n update(mark2) {\n if (this.synch.ready(mark2) && !this.pendingRender) {\n this.pendingRender = true;\n requestAnimationFrame(() => this.render());\n }\n return this.synch.promise;\n }\n async render() {\n this.pendingRender = false;\n const svg = await plotRenderer(this);\n const legends = this.legends.flatMap(({ legend: legend3, include }) => {\n const el = legend3.init(svg);\n return include ? el : [];\n });\n this.element.replaceChildren(svg, ...legends);\n this.synch.resolve();\n }\n /**\n * @param {string} name The attribute to return.\n * @returns {*} The value of the attribute.\n */\n getAttribute(name2) {\n return this.attributes[name2];\n }\n /**\n * @param {string} name The name of the attribute to set.\n * @param {*} value The value to set.\n * @param {{silent: boolean}} [options] Options for setting the attribute.\n * @returns {boolean} whether the value changed.\n */\n setAttribute(name2, value, options) {\n if (distinct(this.attributes[name2], value)) {\n if (value === void 0) {\n delete this.attributes[name2];\n } else {\n this.attributes[name2] = value;\n }\n if (!options?.silent) {\n this.listeners?.get(name2)?.forEach((cb) => cb(name2, value));\n }\n return true;\n }\n return false;\n }\n /**\n * @param {string} name The attribute name.\n * @param {*} callback The function to call when the attribute changes.\n * @returns {this}\n */\n addAttributeListener(name2, callback) {\n const map5 = this.listeners || (this.listeners = /* @__PURE__ */ new Map());\n if (!map5.has(name2)) map5.set(name2, /* @__PURE__ */ new Set());\n map5.get(name2).add(callback);\n return this;\n }\n /**\n * @param {string} name The attribute name.\n * @param {*} callback The function to call when the attribute changes.\n * @returns {void}\n */\n removeAttributeListener(name2, callback) {\n return this.listeners?.get(name2)?.delete(callback);\n }\n addParams(mark2, paramSet) {\n const { params } = this;\n for (const param of paramSet) {\n if (params.has(param)) {\n params.get(param).push(mark2);\n } else {\n params.set(param, [mark2]);\n param.addEventListener(\"value\", () => {\n return Promise.allSettled(\n params.get(param).map((mark3) => mark3.initialize())\n );\n });\n }\n }\n }\n addMark(mark2) {\n mark2.setPlot(this, this.marks.length);\n this.marks.push(mark2);\n this.markset = null;\n return this;\n }\n get markSet() {\n return this.markset || (this.markset = new Set(this.marks));\n }\n addInteractor(sel) {\n this.interactors.push(sel);\n return this;\n }\n addLegend(legend3, include = true) {\n legend3.setPlot(this);\n this.legends.push({ legend: legend3, include });\n }\n};\nfunction maybeAspectRatio(plot3, top2, bottom2) {\n const ar = plot3.getAttribute(\"aspectRatio\");\n if (ar == null) return;\n const x3 = plot3.getAttribute(\"xDomain\");\n const y3 = plot3.getAttribute(\"yDomain\");\n if (!x3 || !y3) return;\n const dx = Math.abs(x3[1] - x3[0]);\n const dy = Math.abs(y3[1] - y3[0]);\n return dy * plot3.innerWidth() / (ar * dx) + top2 + bottom2;\n}\n\n// ../plot/src/marks/util/is-color.js\nfunction isColor2(value) {\n if (typeof value !== \"string\") return false;\n value = value.toLowerCase().trim();\n return value === \"none\" || value === \"currentcolor\" || value.startsWith(\"url(\") && value.endsWith(\")\") || // , e.g. pattern or gradient\n value.startsWith(\"var(\") && value.endsWith(\")\") || // CSS variable\n color(value) !== null;\n}\n\n// ../plot/src/marks/util/is-constant-option.js\nvar constantOptions = /* @__PURE__ */ new Set([\n \"order\",\n \"sort\",\n \"label\",\n \"anchor\",\n \"curve\",\n \"tension\",\n \"marker\",\n \"markerStart\",\n \"markerMid\",\n \"markerEnd\",\n \"textAnchor\",\n \"lineAnchor\",\n \"lineHeight\",\n \"textOverflow\",\n \"monospace\",\n \"fontFamily\",\n \"fontSize\",\n \"fontStyle\",\n \"fontVariant\",\n \"fontWeight\",\n \"frameAnchor\",\n \"strokeLinejoin\",\n \"strokeLinecap\",\n \"strokeMiterlimit\",\n \"strokeDasharray\",\n \"strokeDashoffset\",\n \"mixBlendMode\",\n \"shapeRendering\",\n \"imageRendering\",\n \"preserveAspectRatio\",\n \"interpolate\",\n \"crossOrigin\",\n \"paintOrder\",\n \"pointerEvents\",\n \"target\",\n \"select\"\n]);\nfunction isConstantOption(value) {\n return constantOptions.has(value);\n}\n\n// ../plot/src/marks/util/is-symbol.js\nvar symbols2 = /* @__PURE__ */ new Set([\n \"asterisk\",\n \"circle\",\n \"cross\",\n \"diamond\",\n \"diamond2\",\n \"hexagon\",\n \"plus\",\n \"square\",\n \"square2\",\n \"star\",\n \"times\",\n \"triangle\",\n \"triangle2\",\n \"wye\"\n]);\nfunction isSymbol2(value) {\n return symbols2.has(`${value}`.toLowerCase());\n}\n\n// ../plot/src/marks/Mark.js\nvar isColorChannel = (channel) => channel === \"stroke\" || channel === \"fill\";\nvar isOpacityChannel = (channel) => /opacity$/i.test(channel);\nvar isSymbolChannel = (channel) => channel === \"symbol\";\nvar isFieldObject = (channel, field3) => {\n return channel !== \"sort\" && channel !== \"tip\" && field3 != null && !Array.isArray(field3);\n};\nvar fieldEntry = (channel, field3) => ({\n channel,\n field: field3,\n as: field3 instanceof Ref ? field3.column : channel\n});\nvar valueEntry = (channel, value) => ({ channel, value });\nvar isDataArray = (source) => Array.isArray(source);\nvar Mark2 = class extends MosaicClient {\n constructor(type2, source, encodings, reqs = {}) {\n super(source?.options?.filterBy);\n this.type = type2;\n this.reqs = reqs;\n this.source = source;\n if (isDataArray(this.source)) {\n this.data = toDataColumns(this.source);\n }\n const channels = this.channels = [];\n const detail = this.detail = /* @__PURE__ */ new Set();\n const params = this.params = /* @__PURE__ */ new Set();\n const process = (channel, entry) => {\n const type3 = typeof entry;\n if (channel === \"channels\") {\n for (const name2 in entry) {\n detail.add(name2);\n process(name2, entry[name2]);\n }\n } else if (type3 === \"function\" && entry[Transform]) {\n const enc = entry(this, channel);\n for (const key in enc) {\n process(key, enc[key]);\n }\n } else if (type3 === \"string\") {\n if (isConstantOption(channel) || isColorChannel(channel) && isColor2(entry) || isSymbolChannel(channel) && isSymbol2(entry)) {\n channels.push(valueEntry(channel, entry));\n } else {\n channels.push(fieldEntry(channel, column(entry)));\n }\n } else if (isParamLike(entry)) {\n if (Array.isArray(entry.columns)) {\n channels.push(fieldEntry(channel, entry));\n params.add(entry);\n } else {\n const c4 = valueEntry(channel, entry.value);\n channels.push(c4);\n entry.addEventListener(\"value\", (value) => {\n c4.value = value;\n return this.update();\n });\n }\n } else if (type3 === \"object\" && isFieldObject(channel, entry)) {\n channels.push(fieldEntry(channel, entry));\n } else if (entry !== void 0) {\n channels.push(valueEntry(channel, entry));\n }\n };\n for (const channel in encodings) {\n process(channel, encodings[channel]);\n }\n }\n /**\n * @param {import('../plot.js').Plot} plot The plot.\n * @param {number} index\n */\n setPlot(plot3, index2) {\n this.plot = plot3;\n this.index = index2;\n plot3.addParams(this, this.params);\n if (this.source?.table) this.queryPending();\n }\n hasOwnData() {\n return this.source == null || isDataArray(this.source);\n }\n hasFieldInfo() {\n return !!this._fieldInfo;\n }\n channel(channel) {\n return this.channels.find((c4) => c4.channel === channel);\n }\n channelField(channel, { exact = false } = {}) {\n const c4 = exact ? this.channel(channel) : this.channels.find((c5) => c5.channel.startsWith(channel));\n return c4?.field ? c4 : null;\n }\n fields() {\n if (this.hasOwnData()) return null;\n const { source: { table: table3 }, channels, reqs } = this;\n const fields = /* @__PURE__ */ new Map();\n for (const { channel, field: field3 } of channels) {\n if (!field3) continue;\n const stats = field3.stats?.stats || [];\n const key = field3.stats?.column ?? field3;\n const entry = fields.get(key) ?? fields.set(key, /* @__PURE__ */ new Set()).get(key);\n stats.forEach((s2) => entry.add(s2));\n reqs[channel]?.forEach((s2) => entry.add(s2));\n }\n return Array.from(fields, ([c4, s2]) => ({ table: table3, column: c4, stats: s2 }));\n }\n fieldInfo(info) {\n const lookup = Object.fromEntries(info.map((x3) => [x3.column, x3]));\n for (const entry of this.channels) {\n const { field: field3 } = entry;\n if (field3) {\n Object.assign(entry, lookup[field3.stats?.column ?? field3]);\n }\n }\n this._fieldInfo = true;\n return this;\n }\n /**\n * Return a query specifying the data needed by this Mark client.\n * @param {*} [filter] The filtering criteria to apply in the query.\n * @returns {*} The client query\n */\n query(filter3 = []) {\n if (this.hasOwnData()) return null;\n const { channels, source: { table: table3 } } = this;\n return markQuery(channels, table3).where(filter3);\n }\n queryPending() {\n this.plot.pending(this);\n return this;\n }\n /**\n * Provide query result data to the mark.\n */\n queryResult(data) {\n this.data = toDataColumns(data);\n return this;\n }\n update() {\n return this.plot.update(this);\n }\n /**\n * Generate an array of Plot mark specifications.\n * @returns {object[]}\n */\n plotSpecs() {\n const { type: type2, data, detail, channels } = this;\n return markPlotSpec(type2, detail, channels, data);\n }\n};\nfunction channelOption(c4, columns) {\n const value = columns?.[c4.as] ?? c4.as;\n return Object.hasOwn(c4, \"value\") ? c4.value : isColorChannel(c4.channel) ? { value, scale: \"color\" } : isOpacityChannel(c4.channel) ? { value, scale: \"opacity\" } : value;\n}\nfunction markQuery(channels, table3, skip = []) {\n const q = Query.from({ source: table3 });\n const dims = /* @__PURE__ */ new Set();\n let aggr = false;\n for (const c4 of channels) {\n const { channel, field: field3, as } = c4;\n if (skip.includes(channel)) continue;\n if (channel === \"orderby\") {\n q.orderby(c4.value);\n } else if (field3) {\n if (field3.aggregate) {\n aggr = true;\n } else {\n if (dims.has(as)) continue;\n dims.add(as);\n }\n q.select({ [as]: field3 });\n }\n }\n if (aggr) {\n q.groupby(Array.from(dims));\n }\n return q;\n}\nfunction markPlotSpec(type2, detail, channels, data, options = {}) {\n const { numRows: length4, values: values2, columns } = data ?? {};\n const side = {};\n for (const c4 of channels) {\n const obj = detail.has(c4.channel) ? side : options;\n obj[c4.channel] = channelOption(c4, columns);\n }\n if (detail.size) options.channels = side;\n const specData = values2 ?? (data ? { length: length4 } : null);\n const spec = [{ type: type2, data: specData, options }];\n return spec;\n}\n\n// ../plot/src/marks/util/channel-scale.js\nfunction channelScale(mark2, channel) {\n const { plot: plot3 } = mark2;\n let scaleType = plot3.getAttribute(`${channel}Scale`);\n if (!scaleType) {\n const { type: type2 } = mark2.channelField(channel);\n scaleType = type2 === \"date\" ? \"time\" : \"linear\";\n }\n const options = { type: scaleType };\n switch (scaleType) {\n case \"log\":\n options.base = plot3.getAttribute(`${channel}Base`) ?? 10;\n break;\n case \"pow\":\n options.exponent = plot3.getAttribute(`${channel}Exponent`) ?? 1;\n break;\n case \"symlog\":\n options.constant = plot3.getAttribute(`${channel}Constant`) ?? 1;\n break;\n }\n return scaleTransform(options);\n}\n\n// ../plot/src/marks/util/bin-expr.js\nfunction binExpr(mark2, channel, n, extent4, pad3 = 1, expr) {\n const { field: field3 } = mark2.channelField(channel);\n expr = expr ?? field3;\n const { type: type2, apply: apply2, sqlApply } = channelScale(mark2, channel);\n const reverse3 = !!mark2.plot.getAttribute(`${channel}Reverse`);\n const [lo, hi] = extent4.map((v3) => apply2(v3));\n const v2 = sqlApply(expr);\n const f = type2 === \"time\" || type2 === \"utc\" ? v2 : expr;\n const d = hi === lo ? 0 : (n - pad3) / (hi - lo);\n const s2 = d !== 1 ? ` * ${d}::DOUBLE` : \"\";\n const bin3 = reverse3 ? sql`(${hi} - ${v2}::DOUBLE)${s2}` : sql`(${v2}::DOUBLE - ${lo})${s2}`;\n return [bin3, f];\n}\n\n// ../plot/src/marks/util/extent.js\nvar xext = { x: [\"min\", \"max\"] };\nvar yext = { y: [\"min\", \"max\"] };\nvar xyext = { ...xext, ...yext };\nfunction plotExtent(mark2, filter3, channel, domainAttr, niceAttr) {\n const { plot: plot3 } = mark2;\n const domain = plot3.getAttribute(domainAttr);\n const nice3 = plot3.getAttribute(niceAttr);\n if (Array.isArray(domain) && !domain[Transient]) {\n return domain;\n } else {\n const { column: column3, min: min5, max: max4 } = mark2.channelField(channel);\n const dom = filteredExtent(filter3, column3) || (nice3 ? linear2().domain([min5, max4]).nice().domain() : [min5, max4]);\n if (domain !== Fixed) dom[Transient] = true;\n plot3.setAttribute(domainAttr, dom, { silent: true });\n return dom;\n }\n}\nfunction extentX(mark2, filter3) {\n return plotExtent(mark2, filter3, \"x\", \"xDomain\", \"xNice\");\n}\nfunction extentY(mark2, filter3) {\n return plotExtent(mark2, filter3, \"y\", \"yDomain\", \"yNice\");\n}\nfunction filteredExtent(filter3, column3) {\n if (!filter3) return;\n let lo;\n let hi;\n const visitor = (type2, clause) => {\n if (type2 === \"BETWEEN\" && `${clause.field}` === column3) {\n const { range: range3 } = clause;\n if (range3 && (lo == null || range3[0] < lo)) lo = range3[0];\n if (range3 && (hi == null || range3[1] > hi)) hi = range3[1];\n }\n };\n if (Array.isArray(filter3)) {\n filter3.forEach((p) => p.visit?.(visitor));\n } else if (filter3.visit) {\n filter3.visit(visitor);\n }\n return lo != null && hi != null && lo !== hi ? [lo, hi] : void 0;\n}\n\n// ../plot/src/marks/ConnectedMark.js\nvar ConnectedMark = class extends Mark2 {\n constructor(type2, source, encodings) {\n const dim = type2.endsWith(\"X\") ? \"y\" : type2.endsWith(\"Y\") ? \"x\" : null;\n const req = dim ? { [dim]: [\"min\", \"max\"] } : void 0;\n super(type2, source, encodings, req);\n this.dim = dim;\n }\n /**\n * Return a query specifying the data needed by this Mark client.\n * @param {*} [filter] The filtering criteria to apply in the query.\n * @returns {*} The client query\n */\n query(filter3 = []) {\n const { plot: plot3, dim, source } = this;\n const { optimize = true } = source.options || {};\n const q = super.query(filter3);\n if (!dim) return q;\n const ortho = dim === \"x\" ? \"y\" : \"x\";\n const value = this.channelField(ortho, { exact: true })?.as;\n const { field: field3, as, type: type2, min: min5, max: max4 } = this.channelField(dim);\n const isContinuous = type2 === \"date\" || type2 === \"number\";\n if (optimize && isContinuous && value) {\n const size = dim === \"x\" ? plot3.innerWidth() : plot3.innerHeight();\n const [lo, hi] = filteredExtent(filter3, field3) || [min5, max4];\n const [expr] = binExpr(this, dim, size, [lo, hi], 1, as);\n const cols = q.select().map((c4) => c4.as).filter((c4) => c4 !== as && c4 !== value);\n return m4(q, expr, as, value, cols);\n } else {\n return q.orderby(field3);\n }\n }\n};\nfunction m4(input3, bin3, x3, y3, cols = []) {\n const pixel = sql`FLOOR(${bin3})::INTEGER`;\n const q = (sel) => Query.from(input3).select(sel).groupby(pixel, cols);\n return Query.union(\n q([{ [x3]: min(x3), [y3]: argmin(y3, x3) }, ...cols]),\n q([{ [x3]: max(x3), [y3]: argmax(y3, x3) }, ...cols]),\n q([{ [x3]: argmin(x3, y3), [y3]: min(y3) }, ...cols]),\n q([{ [x3]: argmax(x3, y3), [y3]: max(y3) }, ...cols])\n ).orderby(cols, x3);\n}\n\n// ../plot/src/marks/util/grid.js\nfunction array3(size, proto = []) {\n return new proto.constructor(size);\n}\nfunction grid1d(size, index2, value) {\n const G = array3(size, value);\n const n = value.length;\n for (let i = 0; i < n; ++i) {\n G[index2[i]] = value[i];\n }\n return G;\n}\nfunction grid2d(w, h, index2, columns, aggregates, groupby, interpolate) {\n const numRows = index2.length;\n const size = w * h;\n const values2 = aggregates.map((name2) => columns[name2]);\n const result = {};\n const cells = [];\n const group3 = new Int32Array(numRows);\n if (groupby?.length) {\n const gvalues = groupby.map((name2) => columns[name2]);\n const cellMap = {};\n for (let row = 0; row < numRows; ++row) {\n const key = gvalues.map((group4) => group4[row]);\n group3[row] = cellMap[key] ??= cells.push(key) - 1;\n }\n for (let i = 0; i < groupby.length; ++i) {\n result[groupby[i]] = cells.map((cell3) => cell3[i]);\n }\n } else {\n cells.push([]);\n }\n if (interpolate) {\n const X3 = index2.map((k2) => k2 % w);\n const Y3 = index2.map((k2) => Math.floor(k2 / w));\n const I = cells.map(() => []);\n for (let row = 0; row < numRows; ++row) {\n I[group3[row]].push(row);\n }\n aggregates.forEach((name2, i) => {\n const V = values2[i];\n result[name2] = cells.map((_, j) => interpolate(I[j], w, h, X3, Y3, V));\n });\n } else {\n aggregates.forEach((name2, i) => {\n const V = values2[i];\n const G = result[name2] = cells.map(() => array3(size, V));\n for (let row = 0; row < numRows; ++row) {\n G[group3[row]][index2[row]] = V[row];\n }\n });\n }\n return { numRows: cells.length, columns: result };\n}\nfunction gridDomainContinuous(grids) {\n let lo = Infinity, hi = -Infinity;\n grids.forEach((G) => {\n const n = G.length;\n for (let i = 0; i < n; ++i) {\n const v2 = G[i];\n if (v2 < lo) lo = v2;\n if (v2 > hi) hi = v2;\n }\n });\n return Number.isFinite(lo) && Number.isFinite(hi) ? [lo, hi] : [0, 1];\n}\nfunction gridDomainDiscrete(grids) {\n const values2 = new InternSet();\n grids.forEach((G) => {\n const n = G.length;\n for (let i = 0; i < n; ++i) {\n values2.add(G[i]);\n }\n });\n return Array.from(values2).sort(ascending);\n}\n\n// ../plot/src/marks/util/handle-param.js\nfunction handleParam(value, update2) {\n return isParam(value) ? (value.addEventListener(\"value\", update2), value.value) : value;\n}\n\n// ../plot/src/marks/util/density.js\nfunction dericheConfig(sigma, negative2 = false) {\n const a2 = new Float64Array(5);\n const bc4 = new Float64Array(4);\n dericheCausalCoeff(a2, bc4, sigma);\n const ba = Float64Array.of(\n 0,\n bc4[1] - a2[1] * bc4[0],\n bc4[2] - a2[2] * bc4[0],\n bc4[3] - a2[3] * bc4[0],\n -a2[4] * bc4[0]\n );\n const accum_denom = 1 + a2[1] + a2[2] + a2[3] + a2[4];\n const sum_causal = (bc4[0] + bc4[1] + bc4[2] + bc4[3]) / accum_denom;\n const sum_anticausal = (ba[1] + ba[2] + ba[3] + ba[4]) / accum_denom;\n return {\n sigma,\n negative: negative2,\n a: a2,\n b_causal: bc4,\n b_anticausal: ba,\n sum_causal,\n sum_anticausal\n };\n}\nfunction dericheCausalCoeff(a_out, b_out, sigma) {\n const K2 = 4;\n const alpha = Float64Array.of(\n 0.84,\n 1.8675,\n 0.84,\n -1.8675,\n -0.34015,\n -0.1299,\n -0.34015,\n 0.1299\n );\n const x12 = Math.exp(-1.783 / sigma);\n const x22 = Math.exp(-1.723 / sigma);\n const y12 = 0.6318 / sigma;\n const y22 = 1.997 / sigma;\n const beta = Float64Array.of(\n -x12 * Math.cos(y12),\n x12 * Math.sin(y12),\n -x12 * Math.cos(-y12),\n x12 * Math.sin(-y12),\n -x22 * Math.cos(y22),\n x22 * Math.sin(y22),\n -x22 * Math.cos(-y22),\n x22 * Math.sin(-y22)\n );\n const denom = sigma * 2.5066282746310007;\n const b = Float64Array.of(alpha[0], alpha[1], 0, 0, 0, 0, 0, 0);\n const a2 = Float64Array.of(1, 0, beta[0], beta[1], 0, 0, 0, 0, 0, 0);\n let j, k2;\n for (k2 = 2; k2 < 8; k2 += 2) {\n b[k2] = beta[k2] * b[k2 - 2] - beta[k2 + 1] * b[k2 - 1];\n b[k2 + 1] = beta[k2] * b[k2 - 1] + beta[k2 + 1] * b[k2 - 2];\n for (j = k2 - 2; j > 0; j -= 2) {\n b[j] += beta[k2] * b[j - 2] - beta[k2 + 1] * b[j - 1];\n b[j + 1] += beta[k2] * b[j - 1] + beta[k2 + 1] * b[j - 2];\n }\n for (j = 0; j <= k2; j += 2) {\n b[j] += alpha[k2] * a2[j] - alpha[k2 + 1] * a2[j + 1];\n b[j + 1] += alpha[k2] * a2[j + 1] + alpha[k2 + 1] * a2[j];\n }\n a2[k2 + 2] = beta[k2] * a2[k2] - beta[k2 + 1] * a2[k2 + 1];\n a2[k2 + 3] = beta[k2] * a2[k2 + 1] + beta[k2 + 1] * a2[k2];\n for (j = k2; j > 0; j -= 2) {\n a2[j] += beta[k2] * a2[j - 2] - beta[k2 + 1] * a2[j - 1];\n a2[j + 1] += beta[k2] * a2[j - 1] + beta[k2 + 1] * a2[j - 2];\n }\n }\n for (k2 = 0; k2 < K2; ++k2) {\n j = k2 << 1;\n b_out[k2] = b[j] / denom;\n a_out[k2 + 1] = a2[j + 2];\n }\n}\nfunction dericheConv2d(cx, cy, grid2, [nx, ny]) {\n const yc = new Float64Array(Math.max(nx, ny));\n const ya = new Float64Array(Math.max(nx, ny));\n const h = new Float64Array(5);\n const d = new Float64Array(grid2.length);\n for (let row = 0, r0 = 0; row < ny; ++row, r0 += nx) {\n const dx = d.subarray(r0);\n dericheConv1d(cx, grid2.subarray(r0), nx, 1, yc, ya, h, dx);\n }\n for (let c0 = 0; c0 < nx; ++c0) {\n const dy = d.subarray(c0);\n dericheConv1d(cy, dy, ny, nx, yc, ya, h, dy);\n }\n return d;\n}\nfunction dericheConv1d(c4, src, N, stride = 1, y_causal = new Float64Array(N), y_anticausal = new Float64Array(N), h = new Float64Array(5), d = y_causal, init2 = dericheInitZeroPad) {\n const stride_2 = stride * 2;\n const stride_3 = stride * 3;\n const stride_4 = stride * 4;\n const stride_N = stride * N;\n let i, n;\n init2(\n y_causal,\n src,\n N,\n stride,\n c4.b_causal,\n 3,\n c4.a,\n 4,\n c4.sum_causal,\n h,\n c4.sigma\n );\n for (n = 4, i = stride_4; n < N; ++n, i += stride) {\n y_causal[n] = c4.b_causal[0] * src[i] + c4.b_causal[1] * src[i - stride] + c4.b_causal[2] * src[i - stride_2] + c4.b_causal[3] * src[i - stride_3] - c4.a[1] * y_causal[n - 1] - c4.a[2] * y_causal[n - 2] - c4.a[3] * y_causal[n - 3] - c4.a[4] * y_causal[n - 4];\n }\n init2(\n y_anticausal,\n src,\n N,\n -stride,\n c4.b_anticausal,\n 4,\n c4.a,\n 4,\n c4.sum_anticausal,\n h,\n c4.sigma\n );\n for (n = 4, i = stride_N - stride * 5; n < N; ++n, i -= stride) {\n y_anticausal[n] = c4.b_anticausal[1] * src[i + stride] + c4.b_anticausal[2] * src[i + stride_2] + c4.b_anticausal[3] * src[i + stride_3] + c4.b_anticausal[4] * src[i + stride_4] - c4.a[1] * y_anticausal[n - 1] - c4.a[2] * y_anticausal[n - 2] - c4.a[3] * y_anticausal[n - 3] - c4.a[4] * y_anticausal[n - 4];\n }\n if (c4.negative) {\n for (n = 0, i = 0; n < N; ++n, i += stride) {\n d[i] = y_causal[n] + y_anticausal[N - n - 1];\n }\n } else {\n for (n = 0, i = 0; n < N; ++n, i += stride) {\n d[i] = Math.max(0, y_causal[n] + y_anticausal[N - n - 1]);\n }\n }\n return d;\n}\nfunction dericheInitZeroPad(dest, src, N, stride, b, p, a2, q, sum4, h, sigma, tol = 0.5) {\n const stride_N = Math.abs(stride) * N;\n const off = stride < 0 ? stride_N + stride : 0;\n let i, n, m;\n for (n = 0; n <= q; ++n) {\n h[n] = n <= p ? b[n] : 0;\n for (m = 1; m <= q && m <= n; ++m) {\n h[n] -= a2[m] * h[n - m];\n }\n }\n for (m = 0; m < q; ++m) {\n for (dest[m] = 0, n = 1; n <= m; ++n) {\n i = off + stride * n;\n if (i >= 0 && i < stride_N) {\n dest[m] += h[m - n] * src[i];\n }\n }\n }\n const cur = src[off];\n const max_iter = Math.ceil(sigma * 10);\n for (n = 0; n < max_iter; ++n) {\n for (m = 0; m < q; ++m) {\n dest[m] += h[m] * cur;\n }\n sum4 -= Math.abs(h[0]);\n if (sum4 <= tol) break;\n h[q] = n + q <= p ? b[n + q] : 0;\n for (m = 1; m <= q; ++m) {\n h[q] -= a2[m] * h[q - m];\n }\n for (m = 0; m < q; ++m) {\n h[m] = h[m + 1];\n }\n }\n return;\n}\n\n// ../plot/src/marks/Grid2DMark.js\nvar DENSITY = \"density\";\nvar Grid2DMark = class extends Mark2 {\n constructor(type2, source, options) {\n const {\n bandwidth = 0,\n interpolate = \"none\",\n pixelSize = 1,\n pad: pad3 = 1,\n width: width2,\n height: height2,\n ...channels\n } = options;\n const densityMap = createDensityMap(channels);\n super(type2, source, channels, xyext);\n this.densityMap = densityMap;\n this.bandwidth = handleParam(bandwidth, (value) => {\n this.bandwidth = value;\n return this.grids ? this.convolve().update() : null;\n });\n this.interpolate = handleParam(interpolate, (value) => {\n return this.interpolate = value, this.requestUpdate();\n });\n this.pixelSize = handleParam(pixelSize, (value) => {\n return this.pixelSize = value, this.requestUpdate();\n });\n this.pad = handleParam(pad3, (value) => {\n return this.pad = value, this.requestUpdate();\n });\n this.width = handleParam(width2, (value) => {\n return this.width = value, this.requestUpdate();\n });\n this.height = handleParam(height2, (value) => {\n return this.height = value, this.requestUpdate();\n });\n }\n /**\n * @param {import('../plot.js').Plot} plot The plot.\n * @param {number} index\n */\n setPlot(plot3, index2) {\n const update2 = () => {\n if (this.hasFieldInfo()) this.requestUpdate();\n };\n plot3.addAttributeListener(\"xDomain\", update2);\n plot3.addAttributeListener(\"yDomain\", update2);\n super.setPlot(plot3, index2);\n }\n get filterIndexable() {\n const xdom = this.plot.getAttribute(\"xDomain\");\n const ydom = this.plot.getAttribute(\"yDomain\");\n return xdom && ydom && !xdom[Transient] && !ydom[Transient];\n }\n query(filter3 = []) {\n const { interpolate, pad: pad3, channels, densityMap, source } = this;\n const [x06, x12] = this.extentX = extentX(this, filter3);\n const [y06, y12] = this.extentY = extentY(this, filter3);\n const [nx, ny] = this.bins = this.binDimensions();\n const [x3, bx] = binExpr(this, \"x\", nx, [x06, x12], pad3);\n const [y3, by] = binExpr(this, \"y\", ny, [y06, y12], pad3);\n const bounds = pad3 ? [isBetween(bx, [+x06, +x12]), isBetween(by, [+y06, +y12])] : [lte(+x06, bx), lt(bx, +x12), lte(+y06, by), lt(by, +y12)];\n const q = Query.from(source.table).where(filter3.concat(bounds));\n const groupby = this.groupby = [];\n const aggrMap = {};\n for (const c4 of channels) {\n if (Object.hasOwn(c4, \"field\")) {\n const { as, channel, field: field3 } = c4;\n if (field3.aggregate) {\n aggrMap[channel] = field3;\n densityMap[channel] = true;\n } else if (channel === \"weight\") {\n aggrMap[DENSITY] = sum(field3);\n } else if (channel !== \"x\" && channel !== \"y\") {\n q.select({ [as]: field3 });\n groupby.push(as);\n }\n }\n }\n const aggr = this.aggr = Object.keys(aggrMap);\n if (aggrMap.density && aggr.length > 1) {\n throw new Error(\"Weight option can not be used with custom aggregates.\");\n }\n if (!aggr.length) {\n aggr.push(DENSITY);\n aggrMap.density = count();\n }\n if (interpolate === \"linear\") {\n if (aggr.length > 1) {\n throw new Error(\"Linear binning not applicable to multiple aggregates.\");\n }\n if (!aggrMap.density) {\n throw new Error(\"Linear binning not applicable to custom aggregates.\");\n }\n return binLinear2d(q, x3, y3, aggrMap[DENSITY], nx, groupby);\n } else {\n return bin2d(q, x3, y3, aggrMap, nx, groupby);\n }\n }\n /**\n * @returns {[number, number]} The bin dimensions.\n */\n binDimensions() {\n const { plot: plot3, pixelSize, width: width2, height: height2 } = this;\n return [\n width2 ?? Math.round(plot3.innerWidth() / pixelSize),\n height2 ?? Math.round(plot3.innerHeight() / pixelSize)\n ];\n }\n queryResult(data) {\n const [w, h] = this.bins;\n const interp = maybeInterpolate2(this.interpolate);\n const { columns } = toDataColumns(data);\n this.grids0 = grid2d(w, h, columns.index, columns, this.aggr, this.groupby, interp);\n return this.convolve();\n }\n convolve() {\n const { aggr, bandwidth, bins: bins2, grids0, plot: plot3 } = this;\n this.grids = grids0;\n if (bandwidth > 0) {\n const prop = aggr.length === 1 ? aggr[0] : aggr.includes(DENSITY) ? DENSITY : null;\n if (!prop) {\n console.warn(\"No compatible grid found for smoothing.\");\n return this;\n }\n const g = grids0.columns[prop];\n const w = plot3.innerWidth();\n const h = plot3.innerHeight();\n const [nx, ny] = bins2;\n const neg = g.some((grid2) => grid2.some((v2) => v2 < 0));\n const configX = dericheConfig(bandwidth * (nx - 1) / w, neg);\n const configY = dericheConfig(bandwidth * (ny - 1) / h, neg);\n this.grids = {\n numRows: grids0.numRows,\n columns: {\n ...grids0.columns,\n // @ts-ignore\n [prop]: g.map((grid2) => dericheConv2d(configX, configY, grid2, bins2))\n }\n };\n }\n return this;\n }\n};\nfunction createDensityMap(channels) {\n const densityMap = {};\n for (const key in channels) {\n if (channels[key] === \"density\") {\n delete channels[key];\n densityMap[key] = true;\n }\n }\n return densityMap;\n}\nfunction maybeInterpolate2(interpolate = \"none\") {\n if (typeof interpolate === \"function\") return interpolate;\n switch (interpolate.toLowerCase()) {\n case \"none\":\n case \"linear\":\n return void 0;\n // no special interpolation need\n case \"nearest\":\n return interpolateNearest;\n case \"barycentric\":\n return interpolatorBarycentric();\n case \"random-walk\":\n return interpolatorRandomWalk();\n }\n throw new Error(`invalid interpolate: ${interpolate}`);\n}\nfunction bin2d(q, xp, yp, aggs, xn, groupby) {\n return q.select({\n index: sql`FLOOR(${xp})::INTEGER + FLOOR(${yp})::INTEGER * ${xn}`,\n ...aggs\n }).groupby(\"index\", groupby);\n}\nfunction binLinear2d(q, xp, yp, density3, xn, groupby) {\n const w = density3?.column ? `* ${density3.column}` : \"\";\n const subq = (i, w2) => q.clone().select({ xp, yp, i, w: w2 });\n const a2 = subq(\n sql`FLOOR(xp)::INTEGER + FLOOR(yp)::INTEGER * ${xn}`,\n sql`(FLOOR(xp)::INTEGER + 1 - xp) * (FLOOR(yp)::INTEGER + 1 - yp)${w}`\n );\n const b = subq(\n sql`FLOOR(xp)::INTEGER + (FLOOR(yp)::INTEGER + 1) * ${xn}`,\n sql`(FLOOR(xp)::INTEGER + 1 - xp) * (yp - FLOOR(yp)::INTEGER)${w}`\n );\n const c4 = subq(\n sql`FLOOR(xp)::INTEGER + 1 + FLOOR(yp)::INTEGER * ${xn}`,\n sql`(xp - FLOOR(xp)::INTEGER) * (FLOOR(yp)::INTEGER + 1 - yp)${w}`\n );\n const d = subq(\n sql`FLOOR(xp)::INTEGER + 1 + (FLOOR(yp)::INTEGER + 1) * ${xn}`,\n sql`(xp - FLOOR(xp)::INTEGER) * (yp - FLOOR(yp)::INTEGER)${w}`\n );\n return Query.from(Query.unionAll(a2, b, c4, d)).select({ index: \"i\", density: sum(\"w\") }, groupby).groupby(\"index\", groupby).having(neq(\"density\", 0));\n}\n\n// ../plot/src/marks/ContourMark.js\nvar ContourMark = class extends Grid2DMark {\n constructor(source, options) {\n const { thresholds = 10, ...channels } = options;\n super(\"geo\", source, {\n bandwidth: 20,\n interpolate: \"linear\",\n pixelSize: 2,\n ...channels\n });\n this.thresholds = handleParam(thresholds, (value) => {\n this.thresholds = value;\n return this.grids ? this.contours().update() : null;\n });\n }\n convolve() {\n return super.convolve().contours();\n }\n contours() {\n const { bins: bins2, densityMap, grids, thresholds, plot: plot3 } = this;\n const { numRows, columns } = grids;\n let t = thresholds;\n let tz;\n if (Array.isArray(t)) {\n tz = t;\n } else {\n const [, hi] = gridDomainContinuous(columns.density);\n tz = Array.from({ length: t - 1 }, (_, i) => hi * (i + 1) / t);\n }\n if (densityMap.fill || densityMap.stroke) {\n if (this.plot.getAttribute(\"colorScale\") !== \"log\") {\n this.plot.setAttribute(\"colorZero\", true);\n }\n }\n const [nx, ny] = bins2;\n const [x06, x12] = plot3.getAttribute(\"xDomain\");\n const [y06, y12] = plot3.getAttribute(\"yDomain\");\n const sx = (x12 - x06) / nx;\n const sy = (y12 - y06) / ny;\n const xo = +x06;\n const yo = +y06;\n const x3 = (v2) => xo + v2 * sx;\n const y3 = (v2) => yo + v2 * sy;\n const contour3 = contours_default().size(bins2);\n const data = this.contourData = Array(numRows * tz.length);\n const { density: density3, ...groupby } = columns;\n const groups2 = Object.entries(groupby);\n for (let i = 0, k2 = 0; i < numRows; ++i) {\n const grid2 = density3[i];\n const rest = groups2.reduce((o, [name2, col]) => (o[name2] = col[i], o), {});\n for (let j = 0; j < tz.length; ++j, ++k2) {\n data[k2] = Object.assign(\n transform2(contour3.contour(grid2, tz[j]), x3, y3),\n rest\n );\n }\n }\n return this;\n }\n plotSpecs() {\n const { type: type2, channels, densityMap, contourData: data } = this;\n const options = {};\n for (const c4 of channels) {\n const { channel } = c4;\n if (channel !== \"x\" && channel !== \"y\") {\n options[channel] = channelOption(c4);\n }\n }\n for (const channel in densityMap) {\n if (!densityMap[channel]) continue;\n options[channel] = channelOption({ channel, as: \"value\" });\n }\n return [{ type: type2, data, options }];\n }\n};\nfunction transform2(geometry, x3, y3) {\n function transformPolygon(coordinates) {\n coordinates.forEach(transformRing);\n }\n function transformRing(coordinates) {\n coordinates.forEach(transformPoint);\n }\n function transformPoint(coordinates) {\n coordinates[0] = x3(coordinates[0]);\n coordinates[1] = y3(coordinates[1]);\n }\n geometry.coordinates.forEach(transformPolygon);\n return geometry;\n}\n\n// ../plot/src/marks/util/permute.js\nfunction indices(length4) {\n return Array.from({ length: length4 }, (_, i) => i);\n}\nfunction permute2(data, order) {\n const ord = order.reduce((acc, val, i) => (acc[val] = i, acc), {});\n const idx = indices(data.length);\n idx.sort((a2, b) => ord[data[a2]] - ord[data[b]]);\n return idx;\n}\n\n// ../plot/src/marks/util/raster.js\nfunction createCanvas(w, h) {\n if (typeof document !== \"undefined\") {\n const c4 = document.createElement(\"canvas\");\n c4.setAttribute(\"width\", w);\n c4.setAttribute(\"height\", h);\n return c4;\n }\n throw new Error(\"Can not create a canvas instance.\");\n}\nfunction alphaConstant(v2 = 1) {\n const a2 = 255 * v2 | 0;\n return (data, w, h) => {\n for (let j = 0, k2 = 0; j < h; ++j) {\n for (let i = 0; i < w; ++i, k2 += 4) {\n data[k2 + 3] = a2;\n }\n }\n };\n}\nfunction alphaScheme(scale3) {\n const { apply: apply2 } = scale3;\n return (data, w, h, grid2) => {\n for (let j = 0, k2 = 0; j < h; ++j) {\n for (let i = 0, row = (h - j - 1) * w; i < w; ++i, k2 += 4) {\n data[k2 + 3] = 255 * apply2(grid2[i + row]) | 0;\n }\n }\n };\n}\nfunction colorConstant(v2 = {}) {\n const { r = 0, g = 0, b = 0, opacity: opacity2 = 1 } = typeof v2 === \"string\" ? rgb(v2) : v2;\n const c4 = new Uint8ClampedArray([r, g, b, 255 * opacity2 | 0]);\n return (data, w, h) => {\n for (let j = 0, k2 = 0; j < h; ++j) {\n for (let i = 0; i < w; ++i, k2 += 4) {\n data[k2 + 0] = c4[0];\n data[k2 + 1] = c4[1];\n data[k2 + 2] = c4[2];\n data[k2 + 3] = c4[3];\n }\n }\n };\n}\nfunction colorCategory(scale3) {\n const { domain, range: range3 } = scale3;\n const idx = /* @__PURE__ */ Object.create(null);\n const p = new Uint8ClampedArray(4 * domain.length);\n const n = domain.length - 1;\n const m = range3.length;\n for (let i = 0; i <= n; ++i) {\n const v2 = range3[i % m];\n const { r, g, b, opacity: opacity2 = 1 } = typeof v2 === \"string\" ? rgb(v2) : v2;\n const k2 = i << 2;\n p[k2 + 0] = r;\n p[k2 + 1] = g;\n p[k2 + 2] = b;\n p[k2 + 3] = 255 * opacity2 | 0;\n idx[domain[i]] = k2;\n }\n return (data, w, h, grid2) => {\n if (grid2.map) {\n for (let j = 0, k2 = 0; j < h; ++j) {\n for (let i = 0, row = (h - j - 1) * w; i < w; ++i, k2 += 4) {\n const c4 = idx[grid2[i + row]];\n data[k2 + 0] = p[c4 + 0];\n data[k2 + 1] = p[c4 + 1];\n data[k2 + 2] = p[c4 + 2];\n data[k2 + 3] = p[c4 + 3];\n }\n }\n } else {\n const c4 = idx[grid2];\n for (let j = 0, k2 = 0; j < h; ++j) {\n for (let i = 0; i < w; ++i, k2 += 4) {\n data[k2 + 0] = p[c4 + 0];\n data[k2 + 1] = p[c4 + 1];\n data[k2 + 2] = p[c4 + 2];\n data[k2 + 3] = p[c4 + 3];\n }\n }\n }\n };\n}\nfunction colorScheme(size, scale3, frac) {\n const { interpolate } = scale3;\n const p = new Uint8ClampedArray(4 * size);\n const n = size - 1;\n for (let i = 0; i <= n; ++i) {\n const v2 = interpolate(i / n);\n const { r, g, b, opacity: opacity2 = 1 } = typeof v2 === \"string\" ? rgb(v2) : v2;\n const k2 = i << 2;\n p[k2 + 0] = r;\n p[k2 + 1] = g;\n p[k2 + 2] = b;\n p[k2 + 3] = 255 * opacity2 | 0;\n }\n return (data, w, h, grid2) => {\n for (let j = 0, k2 = 0; j < h; ++j) {\n for (let i = 0, row = (h - j - 1) * w; i < w; ++i, k2 += 4) {\n const c4 = n * frac(grid2[i + row]) << 2;\n data[k2 + 0] = p[c4 + 0];\n data[k2 + 1] = p[c4 + 1];\n data[k2 + 2] = p[c4 + 2];\n data[k2 + 3] = p[c4 + 3];\n }\n }\n };\n}\n\n// ../plot/src/marks/RasterMark.js\nvar RasterMark = class extends Grid2DMark {\n constructor(source, options) {\n super(\"image\", source, options);\n this.image = null;\n }\n setPlot(plot3, index2) {\n const update2 = () => {\n if (this.hasFieldInfo()) this.rasterize();\n };\n plot3.addAttributeListener(\"schemeColor\", update2);\n super.setPlot(plot3, index2);\n }\n convolve() {\n return super.convolve().rasterize();\n }\n rasterize() {\n const { bins: bins2, grids } = this;\n const [w, h] = bins2;\n const { numRows, columns } = grids;\n const { canvas, ctx, img } = imageData(this, w, h);\n const { alpha, alphaProp, color: color3, colorProp } = rasterEncoding(this);\n const alphaData = columns[alphaProp] ?? [];\n const colorData = columns[colorProp] ?? [];\n const idx = numRows > 1 && colorProp && this.groupby?.includes(colorProp) ? permute2(colorData, this.plot.getAttribute(\"colorDomain\")) : indices(numRows);\n this.data = {\n numRows,\n columns: {\n src: Array.from({ length: numRows }, (_, i) => {\n color3?.(img.data, w, h, colorData[idx[i]]);\n alpha?.(img.data, w, h, alphaData[idx[i]]);\n ctx.putImageData(img, 0, 0);\n return canvas.toDataURL();\n })\n }\n };\n return this;\n }\n plotSpecs() {\n const { type: type2, plot: plot3, data: { numRows: length4, columns } } = this;\n const options = {\n src: columns.src,\n width: plot3.innerWidth(),\n height: plot3.innerHeight(),\n preserveAspectRatio: \"none\",\n imageRendering: this.channel(\"imageRendering\")?.value,\n frameAnchor: \"middle\"\n };\n return [{ type: type2, data: { length: length4 }, options }];\n }\n};\nvar HeatmapMark = class extends RasterMark {\n constructor(source, options) {\n super(source, {\n bandwidth: 20,\n interpolate: \"linear\",\n pixelSize: 2,\n ...options\n });\n }\n};\nfunction rasterEncoding(mark2) {\n const { aggr, densityMap, groupby, plot: plot3 } = mark2;\n const hasDensity = aggr.includes(DENSITY);\n const hasFillOpacity = aggr.includes(\"fillOpacity\");\n const fillEntry = mark2.channel(\"fill\");\n const opacEntry = mark2.channel(\"fillOpacity\");\n if (aggr.length > 2 || hasDensity && hasFillOpacity) {\n throw new Error(\"Invalid raster encodings. Try dropping an aggregate?\");\n }\n if (groupby.includes(opacEntry?.as)) {\n throw new Error(\"Raster fillOpacity must be an aggregate or constant.\");\n }\n const fill = densityMap.fill || aggr.includes(\"fill\") ? \"grid\" : groupby.includes(fillEntry?.as) ? \"group\" : isColor2(fillEntry?.value) ? fillEntry.value : hasDensity && plot3.getAttribute(\"colorScheme\") ? \"grid\" : void 0;\n const opac = densityMap.fillOpacity || aggr.includes(\"fillOpacity\") ? \"grid\" : typeof opacEntry?.value === \"number\" ? opacEntry.value : hasDensity && fill !== \"grid\" ? \"grid\" : void 0;\n if (fill !== \"grid\" && opac !== \"grid\") {\n throw new Error(\"Raster mark missing density values.\");\n }\n const colorProp = fillEntry?.as ?? (fill === \"grid\" ? DENSITY : null);\n const alphaProp = opacEntry?.as ?? (opac === \"grid\" ? DENSITY : null);\n const color3 = fill !== \"grid\" && fill !== \"group\" ? colorConstant(fill) : colorScale(mark2, colorProp);\n const alpha = opac !== \"grid\" ? alphaConstant(opac) : alphaScale(mark2, alphaProp);\n return { alphaProp, colorProp, alpha, color: color3 };\n}\nfunction alphaScale(mark2, prop) {\n const { plot: plot3, grids } = mark2;\n const domainAttr = plot3.getAttribute(\"opacityDomain\");\n const domainFixed = domainAttr === Fixed;\n const domainTransient = domainAttr?.[Transient];\n const domain = !domainFixed && !domainTransient && domainAttr || gridDomainContinuous(grids.columns[prop]);\n if (domainFixed || domainTransient || !domainAttr) {\n if (!domainFixed) domain[Transient] = true;\n plot3.setAttribute(\"opacityDomain\", domain);\n }\n const s2 = scale2({\n opacity: {\n type: plot3.getAttribute(\"opacityScale\"),\n domain,\n clamp: plot3.getAttribute(\"opacityClamp\"),\n nice: plot3.getAttribute(\"opacityNice\"),\n reverse: plot3.getAttribute(\"opacityReverse\"),\n zero: plot3.getAttribute(\"opacityZero\"),\n base: plot3.getAttribute(\"opacityBase\"),\n exponent: plot3.getAttribute(\"opacityExponent\"),\n constant: plot3.getAttribute(\"opacityConstant\")\n }\n });\n return alphaScheme(s2);\n}\nfunction colorScale(mark2, prop) {\n const { plot: plot3, grids } = mark2;\n const data = grids.columns[prop];\n const flat = !data[0]?.map;\n const discrete = flat || Array.isArray(data[0]);\n const domainAttr = plot3.getAttribute(\"colorDomain\");\n const domainFixed = domainAttr === Fixed;\n const domainTransient = domainAttr?.[Transient];\n const domain = !domainFixed && !domainTransient && domainAttr || (flat ? data.slice().sort(ascending) : discrete ? gridDomainDiscrete(data) : gridDomainContinuous(data));\n if (domainFixed || domainTransient || !domainAttr) {\n if (!domainFixed) domain[Transient] = true;\n plot3.setAttribute(\"colorDomain\", domain);\n }\n const s2 = scale2({\n color: {\n type: plot3.getAttribute(\"colorScale\"),\n domain,\n range: plot3.getAttribute(\"colorRange\"),\n clamp: plot3.getAttribute(\"colorClamp\"),\n n: plot3.getAttribute(\"colorN\"),\n nice: plot3.getAttribute(\"colorNice\"),\n reverse: plot3.getAttribute(\"colorReverse\"),\n scheme: plot3.getAttribute(\"colorScheme\"),\n interpolate: plot3.getAttribute(\"colorInterpolate\"),\n pivot: plot3.getAttribute(\"colorPivot\"),\n symmetric: plot3.getAttribute(\"colorSymmetric\"),\n zero: plot3.getAttribute(\"colorZero\"),\n base: plot3.getAttribute(\"colorBase\"),\n exponent: plot3.getAttribute(\"colorExponent\"),\n constant: plot3.getAttribute(\"colorConstant\")\n }\n });\n if (discrete) {\n return colorCategory(s2);\n } else {\n const frac = scale2({\n x: {\n type: inferScaleType2(s2.type),\n domain: s2.domain,\n reverse: s2.reverse,\n range: [0, 1],\n clamp: s2.clamp,\n base: s2.base,\n exponent: s2.exponent,\n constant: s2.constant\n }\n });\n return colorScheme(1024, s2, frac.apply);\n }\n}\nfunction inferScaleType2(type2) {\n if (type2.endsWith(\"symlog\")) return \"symlog\";\n if (type2.endsWith(\"log\")) return \"log\";\n if (type2.endsWith(\"pow\")) return \"pow\";\n if (type2.endsWith(\"sqrt\")) return \"sqrt\";\n if (type2 === \"diverging\") return \"linear\";\n return type2;\n}\nfunction imageData(mark2, w, h) {\n if (!mark2.image || mark2.image.w !== w || mark2.image.h !== h) {\n const canvas = createCanvas(w, h);\n const ctx = canvas.getContext(\"2d\", { willReadFrequently: true });\n const img = ctx.getImageData(0, 0, w, h);\n mark2.image = { canvas, ctx, img, w, h };\n }\n return mark2.image;\n}\n\n// ../plot/src/marks/DenseLineMark.js\nvar DenseLineMark = class extends RasterMark {\n constructor(source, options) {\n const { normalize: normalize4 = true, ...rest } = options;\n super(source, rest);\n this.normalize = handleParam(normalize4, (value) => {\n return this.normalize = value, this.requestUpdate();\n });\n }\n query(filter3 = []) {\n const { channels, normalize: normalize4, source, pad: pad3 } = this;\n const [nx, ny] = this.bins = this.binDimensions();\n const [x3] = binExpr(this, \"x\", nx, extentX(this, filter3), pad3);\n const [y3] = binExpr(this, \"y\", ny, extentY(this, filter3), pad3);\n const q = Query.from(source.table).where(stripXY(this, filter3));\n this.aggr = [\"density\"];\n const groupby = this.groupby = [];\n const z = [];\n for (const c4 of channels) {\n if (Object.hasOwn(c4, \"field\")) {\n const { channel, field: field3 } = c4;\n if (channel === \"z\") {\n q.select({ [channel]: field3 });\n z.push(\"z\");\n } else if (channel !== \"x\" && channel !== \"y\") {\n q.select({ [channel]: field3 });\n groupby.push(channel);\n }\n }\n }\n return lineDensity(q, x3, y3, z, nx, ny, groupby, normalize4);\n }\n};\nfunction stripXY(mark2, filter3) {\n if (Array.isArray(filter3) && !filter3.length) return filter3;\n const { column: xc } = mark2.channelField(\"x\");\n const { column: yc } = mark2.channelField(\"y\");\n const test = (p) => {\n const col = `${p.field}`;\n return p.op !== \"BETWEEN\" || col !== xc && col !== yc;\n };\n const filterAnd = (p) => p.op === \"AND\" ? and(p.children.filter((c4) => test(c4))) : p;\n return Array.isArray(filter3) ? filter3.filter((p) => test(p)).map((p) => filterAnd(p)) : filterAnd(filter3);\n}\nfunction lineDensity(q, x3, y3, z, xn, yn, groupby = [], normalize4 = true) {\n q.select({\n x: sql`FLOOR(${x3})::INTEGER`,\n y: sql`FLOOR(${y3})::INTEGER`\n });\n const groups2 = groupby.concat(z);\n const pairPart = groups2.length ? `PARTITION BY ${groups2.join(\", \")} ` : \"\";\n const pairs3 = Query.from(q).select(groups2, {\n x0: \"x\",\n y0: \"y\",\n dx: sql`(lead(x) OVER sw - x)`,\n dy: sql`(lead(y) OVER sw - y)`\n }).window({ sw: sql`${pairPart}ORDER BY x ASC` }).qualify(and(\n sql`(x0 < ${xn} OR x0 + dx < ${xn})`,\n sql`(y0 < ${yn} OR y0 + dy < ${yn})`,\n sql`(x0 > 0 OR x0 + dx > 0)`,\n sql`(y0 > 0 OR y0 + dy > 0)`\n ));\n const num = Query.select({ x: sql`GREATEST(MAX(ABS(dx)), MAX(ABS(dy)))` }).from(\"pairs\");\n const indices2 = Query.select({ i: sql`UNNEST(range((${num})))::INTEGER` });\n const raster3 = Query.unionAll(\n Query.select(groups2, {\n x: sql`x0 + i`,\n y: sql`y0 + ROUND(i * dy / dx::FLOAT)::INTEGER`\n }).from(\"pairs\", \"indices\").where(sql`ABS(dy) <= ABS(dx) AND i < ABS(dx)`),\n Query.select(groups2, {\n x: sql`x0 + ROUND(SIGN(dy) * i * dx / dy::FLOAT)::INTEGER`,\n y: sql`y0 + SIGN(dy) * i`\n }).from(\"pairs\", \"indices\").where(sql`ABS(dy) > ABS(dx) AND i < ABS(dy)`),\n Query.select(groups2, { x: \"x0\", y: \"y0\" }).from(\"pairs\").where(isNull(\"dx\"))\n );\n const pointPart = [\"x\"].concat(groups2).join(\", \");\n const points2 = Query.from(\"raster\").select(\n groups2,\n \"x\",\n \"y\",\n normalize4 ? { w: sql`1.0 / COUNT(*) OVER (PARTITION BY ${pointPart})` } : null\n ).where(and(isBetween(\"x\", [0, xn], true), isBetween(\"y\", [0, yn], true)));\n return Query.with({ pairs: pairs3, indices: indices2, raster: raster3, points: points2 }).from(\"points\").select(groupby, {\n index: sql`x + y * ${xn}::INTEGER`,\n density: normalize4 ? sum(\"w\") : count()\n }).groupby(\"index\", groupby);\n}\n\n// ../plot/src/marks/Density1DMark.js\nvar Density1DMark = class extends Mark2 {\n constructor(type2, source, options) {\n const { bins: bins2 = 1024, bandwidth = 20, ...channels } = options;\n const dim = type2.endsWith(\"X\") ? \"y\" : \"x\";\n super(type2, source, channels, dim === \"x\" ? xext : yext);\n this.dim = dim;\n this.bins = handleParam(bins2, (value) => {\n return this.bins = value, this.requestUpdate();\n });\n this.bandwidth = handleParam(bandwidth, (value) => {\n this.bandwidth = value;\n return this.grid ? this.convolve().update() : null;\n });\n }\n get filterIndexable() {\n const name2 = this.dim === \"x\" ? \"xDomain\" : \"yDomain\";\n const dom = this.plot.getAttribute(name2);\n return dom && !dom[Transient];\n }\n query(filter3 = []) {\n if (this.hasOwnData()) throw new Error(\"Density1DMark requires a data source\");\n const { bins: bins2, channels, dim, source: { table: table3 } } = this;\n const extent4 = this.extent = (dim === \"x\" ? extentX : extentY)(this, filter3);\n const [x3, bx] = binExpr(this, dim, bins2, extent4);\n const q = markQuery(channels, table3, [dim]).where(filter3.concat(isBetween(bx, extent4)));\n const v2 = this.channelField(\"weight\") ? \"weight\" : null;\n return binLinear1d(q, x3, v2);\n }\n queryResult(data) {\n const { columns: { index: index2, density: density3 } } = toDataColumns(data);\n this.grid = grid1d(this.bins, index2, density3);\n return this.convolve();\n }\n convolve() {\n const { bins: bins2, bandwidth, dim, grid: grid2, plot: plot3, extent: [lo, hi] } = this;\n const neg = grid2.some((v3) => v3 < 0);\n const size = dim === \"x\" ? plot3.innerWidth() : plot3.innerHeight();\n const config = dericheConfig(bandwidth * (bins2 - 1) / size, neg);\n const result = dericheConv1d(config, grid2, bins2);\n const v2 = dim === \"x\" ? \"y\" : \"x\";\n const b = this.channelField(dim).as;\n const b0 = +lo;\n const delta = (hi - b0) / (bins2 - 1);\n const scale3 = 1 / delta;\n const _b = new Float64Array(bins2);\n const _v = new Float64Array(bins2);\n for (let i = 0; i < bins2; ++i) {\n _b[i] = b0 + i * delta;\n _v[i] = result[i] * scale3;\n }\n this.data = { numRows: bins2, columns: { [b]: _b, [v2]: _v } };\n return this;\n }\n plotSpecs() {\n const { type: type2, data: { numRows: length4, columns }, channels, dim } = this;\n const options = dim === \"x\" ? { y: columns.y } : { x: columns.x };\n for (const c4 of channels) {\n options[c4.channel] = channelOption(c4, columns);\n }\n return [{ type: type2, data: { length: length4 }, options }];\n }\n};\nfunction binLinear1d(q, p, density3) {\n const w = density3 ? `* ${density3}` : \"\";\n const u4 = q.clone().select({\n p,\n i: sql`FLOOR(p)::INTEGER`,\n w: sql`(FLOOR(p) + 1 - p)${w}`\n });\n const v2 = q.clone().select({\n p,\n i: sql`FLOOR(p)::INTEGER + 1`,\n w: sql`(p - FLOOR(p))${w}`\n });\n return Query.from(Query.unionAll(u4, v2)).select({ index: \"i\", density: sum(\"w\") }).groupby(\"index\").having(gt(\"density\", 0));\n}\n\n// ../plot/src/marks/Density2DMark.js\nvar Density2DMark = class extends Grid2DMark {\n constructor(source, options) {\n const { type: type2 = \"dot\", ...channels } = options;\n super(type2, source, {\n bandwidth: 20,\n interpolate: \"linear\",\n pad: 0,\n pixelSize: 2,\n ...channels\n });\n }\n convolve() {\n super.convolve();\n const { bins: bins2, pad: pad3, extentX: extentX2, extentY: extentY2 } = this;\n const [nx, ny] = bins2;\n const scaleX = channelScale(this, \"x\");\n const scaleY = channelScale(this, \"y\");\n const [x06, x12] = extentX2.map((v2) => scaleX.apply(v2));\n const [y06, y12] = extentY2.map((v2) => scaleY.apply(v2));\n const deltaX = (x12 - x06) / (nx - pad3);\n const deltaY = (y12 - y06) / (ny - pad3);\n const offset2 = pad3 ? 0 : 0.5;\n this.data = points(\n this.grids,\n bins2,\n x06,\n y06,\n deltaX,\n deltaY,\n scaleX.invert,\n scaleY.invert,\n offset2\n );\n return this;\n }\n plotSpecs() {\n const { type: type2, channels, densityMap, data: { numRows: length4, columns } } = this;\n const options = {};\n for (const c4 of channels) {\n const { channel } = c4;\n options[channel] = channel === \"x\" || channel === \"y\" ? columns[channel] : channelOption(c4, columns);\n }\n for (const channel in densityMap) {\n if (densityMap[channel]) {\n options[channel] = columns.density;\n }\n }\n return [{ type: type2, data: { length: length4 }, options }];\n }\n};\nfunction points(data, bins2, x06, y06, deltaX, deltaY, invertX, invertY, offset2) {\n const scale3 = 1 / (deltaX * deltaY);\n const [nx, ny] = bins2;\n const batch = nx * ny;\n const numRows = batch * data.numRows;\n const x3 = new Float64Array(numRows);\n const y3 = new Float64Array(numRows);\n const density3 = new Float64Array(numRows);\n const columns = { x: x3, y: y3, density: density3 };\n const { density: grids, ...rest } = data.columns;\n for (const name2 in rest) {\n columns[name2] = new rest[name2].constructor(numRows);\n }\n let r = 0;\n for (let row = 0; row < data.numRows; ++row) {\n for (const name2 in rest) {\n columns[name2].fill(rest[name2][row], r, r + batch);\n }\n const grid2 = grids[row];\n for (let k2 = 0, j = 0; j < ny; ++j) {\n for (let i = 0; i < nx; ++i, ++r, ++k2) {\n x3[r] = invertX(x06 + (i + offset2) * deltaX);\n y3[r] = invertY(y06 + (j + offset2) * deltaY);\n density3[r] = grid2[k2] * scale3;\n }\n }\n }\n return { numRows, columns };\n}\n\n// ../plot/src/marks/util/stats.js\nfunction ibetainv2(p, a2, b) {\n var EPS2 = 1e-8;\n var a1 = a2 - 1;\n var b1 = b - 1;\n var j = 0;\n var lna, lnb, pp, t, u4, err, x3, al, h, w, afac;\n if (p <= 0) return 0;\n if (p >= 1) return 1;\n if (a2 >= 1 && b >= 1) {\n pp = p < 0.5 ? p : 1 - p;\n t = Math.sqrt(-2 * Math.log(pp));\n x3 = (2.30753 + t * 0.27061) / (1 + t * (0.99229 + t * 0.04481)) - t;\n if (p < 0.5) x3 = -x3;\n al = (x3 * x3 - 3) / 6;\n h = 2 / (1 / (2 * a2 - 1) + 1 / (2 * b - 1));\n w = x3 * Math.sqrt(al + h) / h - (1 / (2 * b - 1) - 1 / (2 * a2 - 1)) * (al + 5 / 6 - 2 / (3 * h));\n x3 = a2 / (a2 + b * Math.exp(2 * w));\n } else {\n lna = Math.log(a2 / (a2 + b));\n lnb = Math.log(b / (a2 + b));\n t = Math.exp(a2 * lna) / a2;\n u4 = Math.exp(b * lnb) / b;\n w = t + u4;\n if (p < t / w) x3 = Math.pow(a2 * w * p, 1 / a2);\n else x3 = 1 - Math.pow(b * w * (1 - p), 1 / b);\n }\n afac = -gammaln2(a2) - gammaln2(b) + gammaln2(a2 + b);\n for (; j < 10; j++) {\n if (x3 === 0 || x3 === 1) return x3;\n err = ibeta2(x3, a2, b) - p;\n t = Math.exp(a1 * Math.log(x3) + b1 * Math.log(1 - x3) + afac);\n u4 = err / t;\n x3 -= t = u4 / (1 - 0.5 * Math.min(1, u4 * (a1 / x3 - b1 / (1 - x3))));\n if (x3 <= 0) x3 = 0.5 * (x3 + t);\n if (x3 >= 1) x3 = 0.5 * (x3 + t + 1);\n if (Math.abs(t) < EPS2 * x3 && j > 0) break;\n }\n return x3;\n}\nfunction ibeta2(x3, a2, b) {\n var bt = x3 === 0 || x3 === 1 ? 0 : Math.exp(gammaln2(a2 + b) - gammaln2(a2) - gammaln2(b) + a2 * Math.log(x3) + b * Math.log(1 - x3));\n if (x3 < 0 || x3 > 1) return 0;\n if (x3 < (a2 + 1) / (a2 + b + 2))\n return bt * betacf2(x3, a2, b) / a2;\n return 1 - bt * betacf2(1 - x3, b, a2) / b;\n}\nfunction betacf2(x3, a2, b) {\n var fpmin = 1e-30;\n var m = 1;\n var qab = a2 + b;\n var qap = a2 + 1;\n var qam = a2 - 1;\n var c4 = 1;\n var d = 1 - qab * x3 / qap;\n var m2, aa2, del, h;\n if (Math.abs(d) < fpmin) d = fpmin;\n d = 1 / d;\n h = d;\n for (; m <= 100; m++) {\n m2 = 2 * m;\n aa2 = m * (b - m) * x3 / ((qam + m2) * (a2 + m2));\n d = 1 + aa2 * d;\n if (Math.abs(d) < fpmin) d = fpmin;\n c4 = 1 + aa2 / c4;\n if (Math.abs(c4) < fpmin) c4 = fpmin;\n d = 1 / d;\n h *= d * c4;\n aa2 = -(a2 + m) * (qab + m) * x3 / ((a2 + m2) * (qap + m2));\n d = 1 + aa2 * d;\n if (Math.abs(d) < fpmin) d = fpmin;\n c4 = 1 + aa2 / c4;\n if (Math.abs(c4) < fpmin) c4 = fpmin;\n d = 1 / d;\n del = d * c4;\n h *= del;\n if (Math.abs(del - 1) < 3e-7) break;\n }\n return h;\n}\nfunction gammaln2(x3) {\n var j = 0;\n var cof = [\n 76.18009172947146,\n -86.5053203294167,\n 24.01409824083091,\n -1.231739572450155,\n 0.001208650973866179,\n -5395239384953e-18\n ];\n var ser = 1.000000000190015;\n var xx, y3, tmp;\n tmp = (y3 = xx = x3) + 5.5;\n tmp -= (xx + 0.5) * Math.log(tmp);\n for (; j < 6; j++) ser += cof[j] / ++y3;\n return Math.log(2.506628274631 * ser / xx) - tmp;\n}\nfunction qt2(p, dof) {\n var x3 = ibetainv2(2 * Math.min(p, 1 - p), 0.5 * dof, 0.5);\n x3 = Math.sqrt(dof * (1 - x3) / x3);\n return p > 0.5 ? x3 : -x3;\n}\nfunction erfinv(x3) {\n let w = -Math.log((1 - x3) * (1 + x3));\n let p;\n if (w < 6.25) {\n w -= 3.125;\n p = -364441206401782e-35;\n p = -16850591381820166e-35 + p * w;\n p = 128584807152564e-32 + p * w;\n p = 11157877678025181e-33 + p * w;\n p = -1333171662854621e-31 + p * w;\n p = 20972767875968562e-33 + p * w;\n p = 6637638134358324e-30 + p * w;\n p = -4054566272975207e-29 + p * w;\n p = -8151934197605472e-29 + p * w;\n p = 26335093153082323e-28 + p * w;\n p = -12975133253453532e-27 + p * w;\n p = -5415412054294628e-26 + p * w;\n p = 10512122733215323e-25 + p * w;\n p = -4112633980346984e-24 + p * w;\n p = -29070369957882005e-24 + p * w;\n p = 42347877827932404e-23 + p * w;\n p = -13654692000834679e-22 + p * w;\n p = -13882523362786469e-21 + p * w;\n p = 18673420803405714e-20 + p * w;\n p = -740702534166267e-18 + p * w;\n p = -0.006033670871430149 + p * w;\n p = 0.24015818242558962 + p * w;\n p = 1.6536545626831027 + p * w;\n } else if (w < 16) {\n w = Math.sqrt(w) - 3.25;\n p = 22137376921775787e-25;\n p = 9075656193888539e-23 + p * w;\n p = -27517406297064545e-23 + p * w;\n p = 18239629214389228e-24 + p * w;\n p = 15027403968909828e-22 + p * w;\n p = -4013867526981546e-21 + p * w;\n p = 29234449089955446e-22 + p * w;\n p = 12475304481671779e-21 + p * w;\n p = -47318229009055734e-21 + p * w;\n p = 6828485145957318e-20 + p * w;\n p = 24031110387097894e-21 + p * w;\n p = -3550375203628475e-19 + p * w;\n p = 9532893797373805e-19 + p * w;\n p = -0.0016882755560235047 + p * w;\n p = 0.002491442096107851 + p * w;\n p = -0.003751208507569241 + p * w;\n p = 0.005370914553590064 + p * w;\n p = 1.0052589676941592 + p * w;\n p = 3.0838856104922208 + p * w;\n } else if (Number.isFinite(w)) {\n w = Math.sqrt(w) - 5;\n p = -27109920616438573e-27;\n p = -2555641816996525e-25 + p * w;\n p = 15076572693500548e-25 + p * w;\n p = -3789465440126737e-24 + p * w;\n p = 761570120807834e-23 + p * w;\n p = -1496002662714924e-23 + p * w;\n p = 2914795345090108e-23 + p * w;\n p = -6771199775845234e-23 + p * w;\n p = 22900482228026655e-23 + p * w;\n p = -99298272942317e-20 + p * w;\n p = 4526062597223154e-21 + p * w;\n p = -1968177810553167e-20 + p * w;\n p = 7599527703001776e-20 + p * w;\n p = -21503011930044477e-20 + p * w;\n p = -13871931833623122e-20 + p * w;\n p = 1.0103004648645344 + p * w;\n p = 4.849906401408584 + p * w;\n } else {\n p = Infinity;\n }\n return p * x3;\n}\n\n// ../plot/src/marks/ErrorBarMark.js\nvar ErrorBarMark = class extends Mark2 {\n constructor(type2, source, options) {\n const dim = type2.endsWith(\"X\") ? \"y\" : \"x\";\n const { ci = 0.95, ...channels } = options;\n super(type2, source, channels);\n this.dim = dim;\n this.field = this.channelField(dim).field;\n this.channels = this.channels.filter((c4) => c4.channel !== dim);\n this.ci = handleParam(ci, (value) => {\n return this.ci = value, this.update();\n });\n }\n query(filter3 = []) {\n const { channels, field: field3, source: { table: table3 } } = this;\n const fields = channels.concat([\n { field: avg(field3), as: \"__avg__\" },\n { field: count(field3), as: \"__n__\" },\n { field: stddev(field3), as: \"__sd__\" }\n ]);\n return markQuery(fields, table3).where(filter3);\n }\n queryResult(data) {\n this.data = toDataColumns(data);\n return this;\n }\n plotSpecs() {\n const { type: type2, dim, detail, data, ci, channels } = this;\n const p = Math.SQRT2 * erfinv(ci);\n const { columns: { __avg__: u4, __sd__: s2, __n__: n } } = data;\n const options = {\n [`${dim}1`]: u4.map((u5, i) => u5 - p * s2[i] / Math.sqrt(n[i])),\n [`${dim}2`]: u4.map((u5, i) => u5 + p * s2[i] / Math.sqrt(n[i]))\n };\n return markPlotSpec(type2, detail, channels, data, options);\n }\n};\n\n// ../plot/src/marks/GeoMark.js\nvar DEFAULT_GEOMETRY_COLUMN = \"geom\";\nvar GeoMark = class extends Mark2 {\n constructor(source, encodings = {}, reqs) {\n if (!isDataArray(source) && !encodings?.geometry) {\n encodings.geometry = geojson(DEFAULT_GEOMETRY_COLUMN);\n }\n super(\"geo\", source, encodings, reqs);\n }\n queryResult(data) {\n super.queryResult(data);\n const geom = this.channelField(\"geometry\")?.as;\n if (geom) {\n const { columns } = this.data;\n if (typeof columns[geom][0] === \"string\") {\n columns[geom] = columns[geom].map((s2) => JSON.parse(s2));\n }\n }\n return this;\n }\n};\n\n// ../plot/src/marks/HexbinMark.js\nvar HexbinMark = class extends Mark2 {\n constructor(source, options) {\n const { type: type2 = \"hexagon\", binWidth = 20, ...channels } = options;\n super(type2, source, { r: binWidth / 2, clip: true, ...channels }, xyext);\n this.binWidth = handleParam(binWidth, (value) => {\n return this.binWidth = value, this.requestUpdate();\n });\n }\n get filterIndexable() {\n const xdom = this.plot.getAttribute(\"xDomain\");\n const ydom = this.plot.getAttribute(\"yDomain\");\n return xdom && ydom && !xdom[Transient] && !ydom[Transient];\n }\n query(filter3 = []) {\n if (this.hasOwnData()) return null;\n const { plot: plot3, binWidth, channels, source } = this;\n let x3, y3;\n const dims = /* @__PURE__ */ new Set();\n const cols = {};\n for (const c4 of channels) {\n if (c4.channel === \"orderby\") {\n } else if (c4.channel === \"x\") {\n x3 = c4;\n } else if (c4.channel === \"y\") {\n y3 = c4;\n } else if (Object.hasOwn(c4, \"field\")) {\n const { as, field: field3 } = c4;\n cols[as] = field3;\n if (!field3.aggregate) {\n dims.add(as);\n }\n }\n }\n const [x12, x22] = extentX(this, filter3);\n const [y12, y22] = extentY(this, filter3);\n const ox2 = 0.5 - plot3.getAttribute(\"marginLeft\");\n const oy2 = 0 - plot3.getAttribute(\"marginTop\");\n const dx = `${binWidth}::DOUBLE`;\n const dy = `${binWidth * (1.5 / Math.sqrt(3))}::DOUBLE`;\n const xr = `${plot3.innerWidth() / (x22 - x12)}::DOUBLE`;\n const yr = `${plot3.innerHeight() / (y22 - y12)}::DOUBLE`;\n return Query.select({\n [x3.as]: sql`${x12}::DOUBLE + ((_x + 0.5 * (_y & 1)) * ${dx} + ${ox2})::DOUBLE / ${xr}`,\n [y3.as]: sql`${y22}::DOUBLE - (_y * ${dy} + ${oy2})::DOUBLE / ${yr}`,\n ...cols\n }).groupby(\"_x\", \"_y\", ...dims).from(\n // Subquery performs hex binning in screen space and also passes\n // original columns through (the DB should optimize this).\n Query.select({\n _py: sql`(${yr} * (${y22}::DOUBLE - ${y3.field}) - ${oy2}) / ${dy}`,\n _pj: sql`ROUND(_py)::INTEGER`,\n _px: sql`(${xr} * (${x3.field} - ${x12}::DOUBLE) - ${ox2}) / ${dx} - 0.5 * (_pj & 1)`,\n _pi: sql`ROUND(_px)::INTEGER`,\n _tt: sql`ABS(_py-_pj) * 3 > 1 AND (_px-_pi)**2 + (_py-_pj)**2 > (_px - _pi - 0.5 * CASE WHEN _px < _pi THEN -1 ELSE 1 END)**2 + (_py - _pj - CASE WHEN _py < _pj THEN -1 ELSE 1 END)**2`,\n _x: sql`CASE WHEN _tt THEN (_pi + (CASE WHEN _px < _pi THEN -0.5 ELSE 0.5 END) + (CASE WHEN _pj & 1 <> 0 THEN 0.5 ELSE -0.5 END))::INTEGER ELSE _pi END`,\n _y: sql`CASE WHEN _tt THEN (_pj + CASE WHEN _py < _pj THEN -1 ELSE 1 END)::INTEGER ELSE _pj END`\n }, \"*\").from(source.table).where(isNotNull(x3.field), isNotNull(y3.field), filter3)\n );\n }\n};\n\n// ../plot/src/marks/RasterTileMark.js\nvar RasterTileMark = class extends Grid2DMark {\n constructor(source, options) {\n const { origin = [0, 0], dim = \"xy\", ...markOptions2 } = options;\n super(\"image\", source, markOptions2);\n this.image = null;\n this.origin = origin;\n this.tileX = dim.toLowerCase().includes(\"x\");\n this.tileY = dim.toLowerCase().includes(\"y\");\n }\n setPlot(plot3, index2) {\n const update2 = () => {\n if (this.hasFieldInfo()) this.rasterize();\n };\n plot3.addAttributeListener(\"schemeColor\", update2);\n super.setPlot(plot3, index2);\n }\n requestQuery() {\n return this.requestTiles();\n }\n query(filter3 = []) {\n this._filter = filter3;\n return null;\n }\n tileQuery(extent4) {\n const { interpolate, pad: pad3, channels, densityMap, source } = this;\n const [[x06, x12], [y06, y12]] = extent4;\n const [nx, ny] = this.bins;\n const [x3, bx] = binExpr(this, \"x\", nx, [x06, x12], pad3);\n const [y3, by] = binExpr(this, \"y\", ny, [y06, y12], pad3);\n const bounds = pad3 ? [isBetween(bx, [+x06, +x12]), isBetween(by, [+y06, +y12])] : [lte(+x06, bx), lt(bx, +x12), lte(+y06, by), lt(by, +y12)];\n const q = Query.from(source.table).where(bounds);\n const groupby = this.groupby = [];\n const aggrMap = {};\n for (const c4 of channels) {\n if (Object.hasOwn(c4, \"field\")) {\n const { as, channel, field: field3 } = c4;\n if (field3.aggregate) {\n aggrMap[channel] = field3;\n densityMap[channel] = true;\n } else if (channel === \"weight\") {\n aggrMap.density = sum(field3);\n } else if (channel !== \"x\" && channel !== \"y\") {\n q.select({ [as]: field3 });\n groupby.push(as);\n }\n }\n }\n const aggr = this.aggr = Object.keys(aggrMap);\n if (aggrMap.density && aggr.length > 1) {\n throw new Error(\"Weight option can not be used with custom aggregates.\");\n }\n if (!aggr.length) {\n aggr.push(\"density\");\n aggrMap.density = count();\n }\n if (interpolate === \"linear\") {\n if (aggr.length > 1) {\n throw new Error(\"Linear binning not applicable to multiple aggregates.\");\n }\n if (!aggrMap.density) {\n throw new Error(\"Linear binning not applicable to custom aggregates.\");\n }\n return binLinear2d2(q, x3, y3, aggrMap.density, nx, groupby);\n } else {\n return bin2d2(q, x3, y3, aggrMap, nx, groupby);\n }\n }\n async requestTiles() {\n const mc = coordinator();\n if (this.prefetch) mc.cancel(this.prefetch);\n const { pad: pad3, tileX, tileY, origin: [tx, ty] } = this;\n const [m, n] = this.bins = this.binDimensions();\n const [x06, x12] = extentX(this, this._filter);\n const [y06, y12] = extentY(this, this._filter);\n const xspan = x12 - x06;\n const yspan = y12 - y06;\n const xx = Math.floor((x06 - tx) * (m - pad3) / xspan);\n const yy = Math.floor((y06 - ty) * (n - pad3) / yspan);\n const tileExtent = (i, j) => [\n [tx + i * xspan, tx + (i + 1) * xspan],\n [ty + j * yspan, ty + (j + 1) * yspan]\n ];\n const i0 = Math.floor((x06 - tx) / xspan);\n const i1 = tileX ? tileFloor((x12 - tx) / xspan) : i0;\n const j0 = Math.floor((y06 - ty) / yspan);\n const j1 = tileY ? tileFloor((y12 - ty) / yspan) : j0;\n const coords = [];\n for (let i = i0; i <= i1; ++i) {\n for (let j = j0; j <= j1; ++j) {\n coords.push([i, j]);\n }\n }\n const queries = coords.map(\n ([i, j]) => mc.query(this.tileQuery(tileExtent(i, j)))\n );\n const prefetchCoords = [];\n if (tileX) {\n for (let j = j0; j <= j1; ++j) {\n prefetchCoords.push([i1 + 1, j]);\n prefetchCoords.push([i0 - 1, j]);\n }\n }\n if (tileY) {\n const x07 = tileX ? i0 - 1 : i0;\n const x13 = tileX ? i1 + 1 : i1;\n for (let i = x07; i <= x13; ++i) {\n prefetchCoords.push([i, j1 + 1]);\n prefetchCoords.push([i, j0 - 1]);\n }\n }\n this.prefetch = prefetchCoords.map(\n ([i, j]) => mc.prefetch(this.tileQuery(tileExtent(i, j)))\n );\n const tiles = await Promise.all(queries);\n const density3 = processTiles(m, n, xx, yy, coords, tiles);\n this.grids0 = {\n numRows: density3.length,\n columns: { density: [density3] }\n };\n this.convolve().update();\n }\n convolve() {\n return super.convolve().rasterize();\n }\n rasterize() {\n const { bins: bins2, grids } = this;\n const [w, h] = bins2;\n const { numRows, columns } = grids;\n const { canvas, ctx, img } = imageData2(this, w, h);\n const { alpha, alphaProp, color: color3, colorProp } = rasterEncoding(this);\n const alphaData = columns[alphaProp] ?? [];\n const colorData = columns[colorProp] ?? [];\n const idx = numRows > 1 && colorProp && this.groupby?.includes(colorProp) ? permute2(colorData, this.plot.getAttribute(\"colorDomain\")) : indices(numRows);\n this.data = {\n numRows,\n columns: {\n src: Array.from({ length: numRows }, (_, i) => {\n color3?.(img.data, w, h, colorData[idx[i]]);\n alpha?.(img.data, w, h, alphaData[idx[i]]);\n ctx.putImageData(img, 0, 0);\n return canvas.toDataURL();\n })\n }\n };\n return this;\n }\n plotSpecs() {\n const { type: type2, plot: plot3, data: { numRows: length4, columns } } = this;\n const options = {\n src: columns.src,\n width: plot3.innerWidth(),\n height: plot3.innerHeight(),\n preserveAspectRatio: \"none\",\n imageRendering: this.channel(\"imageRendering\")?.value,\n frameAnchor: \"middle\"\n };\n return [{ type: type2, data: { length: length4 }, options }];\n }\n};\nfunction processTiles(m, n, x3, y3, coords, tiles) {\n const grid2 = new Float64Array(m * n);\n tiles.forEach((data, index2) => {\n const [i, j] = coords[index2];\n const tx = i * m - x3;\n const ty = j * n - y3;\n copy3(m, n, grid2, data, tx, ty);\n });\n return grid2;\n}\nfunction copy3(m, n, grid2, values2, tx, ty) {\n const num = values2.numRows;\n if (num === 0) return;\n const index2 = values2.getChild(\"index\").toArray();\n const value = values2.getChild(\"density\").toArray();\n for (let row = 0; row < num; ++row) {\n const idx = index2[row];\n const i = tx + idx % m;\n const j = ty + Math.floor(idx / m);\n if (0 <= i && i < m && 0 <= j && j < n) {\n grid2[i + j * m] = value[row];\n }\n }\n}\nfunction imageData2(mark2, w, h) {\n if (!mark2.image || mark2.image.w !== w || mark2.image.h !== h) {\n const canvas = createCanvas(w, h);\n const ctx = canvas.getContext(\"2d\", { willReadFrequently: true });\n const img = ctx.getImageData(0, 0, w, h);\n mark2.image = { canvas, ctx, img, w, h };\n }\n return mark2.image;\n}\nfunction bin2d2(q, xp, yp, aggs, xn, groupby) {\n return q.select({\n index: sql`FLOOR(${xp})::INTEGER + FLOOR(${yp})::INTEGER * ${xn}`,\n ...aggs\n }).groupby(\"index\", groupby);\n}\nfunction binLinear2d2(q, xp, yp, value, xn, groupby) {\n const w = value.column ? `* ${value.column}` : \"\";\n const subq = (i, w2) => q.clone().select({ xp, yp, i, w: w2 });\n const a2 = subq(\n sql`FLOOR(xp)::INTEGER + FLOOR(yp)::INTEGER * ${xn}`,\n sql`(FLOOR(xp)::INTEGER + 1 - xp) * (FLOOR(yp)::INTEGER + 1 - yp)${w}`\n );\n const b = subq(\n sql`FLOOR(xp)::INTEGER + (FLOOR(yp)::INTEGER + 1) * ${xn}`,\n sql`(FLOOR(xp)::INTEGER + 1 - xp) * (yp - FLOOR(yp)::INTEGER)${w}`\n );\n const c4 = subq(\n sql`FLOOR(xp)::INTEGER + 1 + FLOOR(yp)::INTEGER * ${xn}`,\n sql`(xp - FLOOR(xp)::INTEGER) * (FLOOR(yp)::INTEGER + 1 - yp)${w}`\n );\n const d = subq(\n sql`FLOOR(xp)::INTEGER + 1 + (FLOOR(yp)::INTEGER + 1) * ${xn}`,\n sql`(xp - FLOOR(xp)::INTEGER) * (yp - FLOOR(yp)::INTEGER)${w}`\n );\n return Query.from(Query.unionAll(a2, b, c4, d)).select({ index: \"i\", density: sum(\"w\") }, groupby).groupby(\"index\", groupby).having(neq(\"density\", 0));\n}\nfunction tileFloor(value) {\n const floored = Math.floor(value);\n return floored === value ? floored - 1 : floored;\n}\n\n// ../plot/src/marks/RegressionMark.js\nvar RegressionMark = class extends Mark2 {\n constructor(source, options) {\n const { ci = 0.95, precision = 4, ...channels } = options;\n super(\"line\", source, channels);\n const update2 = () => this.modelFit ? this.confidenceBand().update() : null;\n this.ci = handleParam(ci, (value) => {\n return this.ci = value, update2();\n });\n this.precision = handleParam(precision, (value) => {\n return this.precision = value, update2();\n });\n }\n query(filter3 = []) {\n const x3 = this.channelField(\"x\").as;\n const y3 = this.channelField(\"y\").as;\n const groupby = Array.from(new Set(\n [\"stroke\", \"z\", \"fx\", \"fy\"].flatMap((c4) => this.channelField(c4)?.as || [])\n ));\n return Query.from(super.query(filter3)).select({\n intercept: regrIntercept(y3, x3),\n slope: regrSlope(y3, x3),\n n: regrCount(y3, x3),\n ssy: regrSYY(y3, x3),\n ssx: regrSXX(y3, x3),\n xm: regrAvgX(y3, x3),\n x0: castDouble(min(x3).where(isNotNull(y3))),\n x1: castDouble(max(x3).where(isNotNull(y3)))\n }).select(groupby).groupby(groupby);\n }\n queryResult(data) {\n this.modelFit = toDataColumns(data);\n this.lineData = linePoints(this.modelFit);\n return this.confidenceBand();\n }\n confidenceBand() {\n const { ci, modelFit, precision, plot: plot3 } = this;\n const width2 = plot3.innerWidth();\n this.areaData = ci ? areaPoints(modelFit, ci, precision, width2) : null;\n return this;\n }\n plotSpecs() {\n const { lineData, areaData, channels, ci } = this;\n const lcols = lineData.columns;\n const acols = ci ? areaData.columns : {};\n const lopt = { x: lcols.x, y: lcols.y };\n const aopt = { x: acols.x, y1: acols.y1, y2: acols.y2, fillOpacity: 0.1 };\n for (const c4 of channels) {\n switch (c4.channel) {\n case \"x\":\n case \"y\":\n case \"fill\":\n break;\n case \"tip\":\n aopt.tip = channelOption(c4, acols);\n break;\n case \"stroke\":\n lopt.stroke = channelOption(c4, lcols);\n aopt.fill = channelOption(c4, acols);\n break;\n case \"strokeOpacity\":\n lopt.strokeOpacity = channelOption(c4, lcols);\n break;\n case \"fillOpacity\":\n aopt.fillOpacity = channelOption(c4, acols);\n break;\n default:\n lopt[c4.channel] = channelOption(c4, lcols);\n aopt[c4.channel] = channelOption(c4, acols);\n break;\n }\n }\n return [\n ...ci ? [{ type: \"areaY\", data: { length: areaData.numRows }, options: aopt }] : [],\n { type: \"line\", data: { length: lineData.numRows }, options: lopt }\n ];\n }\n};\nfunction concat(a2, b) {\n if (a2.concat) return a2.concat(b);\n const array4 = new a2.constructor(a2.length + b.length);\n array4.set(a2, 0);\n array4.set(b, a2.length);\n return array4;\n}\nfunction linePoints(fit2) {\n const { x0: x06 = [], x1: x12 = [], xm, intercept, slope, n, ssx, ssy, ...rest } = fit2.columns;\n const predict = (x4, i) => intercept[i] + x4 * slope[i];\n const x3 = concat(x06, x12);\n const y3 = concat(x06.map(predict), x12.map(predict));\n for (const name2 in rest) {\n rest[name2] = concat(rest[name2], rest[name2]);\n }\n return { numRows: x3.length, columns: { x: x3, y: y3, ...rest } };\n}\nfunction areaPoints(fit2, ci, precision, width2) {\n const len = fit2.numRows;\n const { x0: x06, x1: x12, xm, intercept, slope, n, ssx, ssy, ...rest } = fit2.columns;\n const other = Object.keys(rest);\n const columns = { x: [], y1: [], y2: [] };\n other.forEach((name2) => columns[name2] = []);\n for (let i = 0; i < len; ++i) {\n const pp = precision * (x12[i] - x06[i]) / width2;\n const t_sy = qt2((1 - ci) / 2, n[i] - 2) * Math.sqrt(ssy[i] / (n[i] - 2));\n range(x06[i], x12[i] - pp / 2, pp).concat(x12[i]).forEach((x3) => {\n const y3 = intercept[i] + x3 * slope[i];\n const ye = t_sy * Math.sqrt(1 / n[i] + (x3 - xm[i]) ** 2 / ssx[i]);\n columns.x.push(x3);\n columns.y1.push(y3 - ye);\n columns.y2.push(y3 + ye);\n other.forEach((name2) => columns[name2].push(rest[name2][i]));\n });\n }\n return { numRows: columns.x.length, columns };\n}\n\n// ../plot/src/interactors/util/to-kebab-case.js\nfunction toKebabCase(cc2) {\n const lc = cc2.toLowerCase();\n const n = cc2.length;\n let kc = \"\";\n for (let i = 0; i < n; ++i) {\n kc += (cc2[i] !== lc[i] ? \"-\" : \"\") + lc[i];\n }\n return kc;\n}\n\n// ../plot/src/interactors/util/sanitize-styles.js\nfunction sanitizeStyles(styles2) {\n const s2 = {};\n for (const name2 in styles2) {\n s2[toKebabCase(name2)] = styles2[name2];\n }\n return s2;\n}\n\n// ../plot/src/interactors/Highlight.js\nfunction configureMark(mark2) {\n const { channels } = mark2;\n const dims = /* @__PURE__ */ new Set();\n let ordered = false;\n let aggregate = false;\n for (const c4 of channels) {\n const { channel, field: field3, as } = c4;\n if (channel === \"orderby\") {\n ordered = true;\n } else if (field3) {\n if (field3.aggregate) {\n aggregate = true;\n } else {\n if (dims.has(as)) continue;\n dims.add(as);\n }\n }\n }\n if (!ordered && aggregate && dims.size) {\n mark2.channels.push({ channel: \"orderby\", value: Array.from(dims) });\n }\n return mark2;\n}\nvar Highlight = class {\n constructor(mark2, {\n selection: selection2,\n channels = {}\n }) {\n this.mark = configureMark(mark2);\n this.selection = selection2;\n const c4 = Object.entries(sanitizeStyles(channels));\n this.channels = c4.length ? c4 : [[\"opacity\", 0.2]];\n this.selection.addEventListener(\"value\", throttle(() => this.update()));\n }\n init(svg) {\n this.svg = svg;\n const values2 = this.values = [];\n const index2 = this.mark.index;\n const nodes = this.nodes = svg.querySelectorAll(`[data-index=\"${index2}\"] > *`);\n const { channels } = this;\n for (let i = 0; i < nodes.length; ++i) {\n const node = nodes[i];\n values2.push(channels.map((c4) => node.getAttribute(c4[0])));\n }\n return this.update();\n }\n async update() {\n const { svg, nodes, channels, values: values2, mark: mark2, selection: selection2 } = this;\n if (!svg) return;\n const test = await predicateFunction(mark2, selection2);\n for (let i = 0; i < nodes.length; ++i) {\n const node = nodes[i];\n const base = values2[i];\n const data = node.__data__;\n const t = test(Array.isArray(data) ? data[0] : data);\n for (let j = 0; j < channels.length; ++j) {\n const [attr, value] = channels[j];\n node.setAttribute(attr, t ? base[j] : value);\n }\n }\n }\n};\nasync function predicateFunction(mark2, selection2) {\n const pred = selection2?.predicate(mark2);\n if (!pred || pred.length === 0) {\n return () => true;\n }\n const filter3 = mark2.filterBy?.predicate(mark2, true);\n const s2 = { __: and(pred) };\n const q = mark2.query(filter3);\n (q.queries || [q]).forEach((q2) => {\n q2.groupby().length ? q2.select(s2) : q2.$select(s2);\n });\n const data = await mark2.coordinator.query(q);\n const v2 = data.getChild?.(\"__\");\n return !(data.numRows || data.length) ? () => false : v2 ? (i) => v2.at(i) : (i) => data[i].__;\n}\n\n// ../plot/src/interactors/util/brush.js\nfunction wrap2(brush3) {\n const brushOn = brush3.on;\n let enabled = true;\n function silence(callback) {\n enabled = false;\n callback();\n enabled = true;\n }\n brush3.reset = (...args) => {\n silence(() => brush3.clear(...args));\n };\n brush3.moveSilent = (...args) => {\n silence(() => brush3.move(...args));\n };\n brush3.on = (...args) => {\n if (args.length > 1 && args[1]) {\n const callback = args[1];\n args[1] = (...event) => enabled && callback(...event);\n }\n return brushOn(...args);\n };\n return brush3;\n}\nfunction brush2() {\n return wrap2(brush_default());\n}\nfunction brushX2() {\n return wrap2(brushX());\n}\nfunction brushY2() {\n return wrap2(brushY());\n}\n\n// ../plot/src/interactors/util/close-to.js\nvar EPS = 1e-12;\nfunction closeTo(a2, b) {\n return a2 === b || a2 && b && Math.abs(a2[0] - b[0]) < EPS && Math.abs(a2[1] - b[1]) < EPS || false;\n}\n\n// ../plot/src/interactors/util/get-field.js\nfunction getField(mark2, channel) {\n const field3 = mark2.channelField(channel)?.field;\n return field3?.basis || field3;\n}\n\n// ../plot/src/interactors/util/invert.js\nfunction invert(value, scale3, pixelSize = 1) {\n return scale3.invert(pixelSize * Math.floor(value / pixelSize));\n}\n\n// ../plot/src/interactors/util/patchScreenCTM.js\nfunction patchScreenCTM() {\n const node = this;\n const getScreenCTM = node.getScreenCTM;\n let memo2;\n node.getScreenCTM = () => {\n return node.isConnected ? memo2 = getScreenCTM.call(node) : memo2;\n };\n}\n\n// ../plot/src/interactors/Interval1D.js\nvar Interval1D = class {\n constructor(mark2, {\n channel,\n selection: selection2,\n field: field3 = void 0,\n pixelSize = 1,\n peers = true,\n brush: style2\n }) {\n this.mark = mark2;\n this.channel = channel;\n this.pixelSize = pixelSize || 1;\n this.selection = selection2;\n this.peers = peers;\n this.field = field3 || getField(mark2, channel);\n this.style = style2 && sanitizeStyles(style2);\n this.brush = channel === \"y\" ? brushY2() : brushX2();\n this.brush.on(\"brush end\", ({ selection: selection3 }) => this.publish(selection3));\n }\n reset() {\n this.value = void 0;\n if (this.g) this.brush.reset(this.g);\n }\n activate() {\n this.selection.activate(this.clause(this.value || [0, 1]));\n }\n publish(extent4) {\n let range3 = void 0;\n if (extent4) {\n range3 = extent4.map((v2) => invert(v2, this.scale, this.pixelSize)).sort((a2, b) => a2 - b);\n }\n if (!closeTo(range3, this.value)) {\n this.value = range3;\n this.g.call(this.brush.moveSilent, extent4);\n this.selection.update(this.clause(range3));\n }\n }\n clause(value) {\n const { mark: mark2, pixelSize, field: field3, scale: scale3 } = this;\n return clauseInterval(field3, value, {\n source: this,\n clients: this.peers ? mark2.plot.markSet : (/* @__PURE__ */ new Set()).add(mark2),\n scale: scale3,\n pixelSize\n });\n }\n init(svg, root2) {\n const { brush: brush3, channel, style: style2 } = this;\n this.scale = svg.scale(channel);\n const rx = svg.scale(\"x\").range;\n const ry = svg.scale(\"y\").range;\n brush3.extent([[min2(rx), min2(ry)], [max2(rx), max2(ry)]]);\n const range3 = this.value?.map(this.scale.apply).sort(ascending);\n const facets = select_default2(svg).selectAll('g[aria-label=\"facet\"]');\n root2 = facets.size() ? facets : select_default2(root2 ?? svg);\n this.g = root2.append(\"g\").attr(\"class\", `interval-${channel}`).each(patchScreenCTM).call(brush3).call(brush3.moveSilent, range3);\n if (style2) {\n const brushes = this.g.selectAll(\"rect.selection\");\n for (const name2 in style2) {\n brushes.attr(name2, style2[name2]);\n }\n }\n svg.addEventListener(\"pointerenter\", (evt) => {\n if (!evt.buttons) this.activate();\n });\n }\n};\n\n// ../plot/src/interactors/Interval2D.js\nvar Interval2D = class {\n constructor(mark2, {\n selection: selection2,\n xfield,\n yfield,\n pixelSize = 1,\n peers = true,\n brush: style2\n }) {\n this.mark = mark2;\n this.pixelSize = pixelSize || 1;\n this.selection = selection2;\n this.peers = peers;\n this.xfield = xfield || getField(mark2, \"x\");\n this.yfield = yfield || getField(mark2, \"y\");\n this.style = style2 && sanitizeStyles(style2);\n this.brush = brush2();\n this.brush.on(\"brush end\", ({ selection: selection3 }) => this.publish(selection3));\n }\n reset() {\n this.value = void 0;\n if (this.g) this.brush.reset(this.g);\n }\n activate() {\n this.selection.activate(this.clause(this.value || [[0, 1], [0, 1]]));\n }\n publish(extent4) {\n const { value, pixelSize, xscale, yscale } = this;\n let xr = void 0;\n let yr = void 0;\n if (extent4) {\n const [a2, b] = extent4;\n xr = [a2[0], b[0]].map((v2) => invert(v2, xscale, pixelSize)).sort(ascending);\n yr = [a2[1], b[1]].map((v2) => invert(v2, yscale, pixelSize)).sort(ascending);\n }\n if (!closeTo(xr, value?.[0]) || !closeTo(yr, value?.[1])) {\n this.value = extent4 ? [xr, yr] : void 0;\n this.g.call(this.brush.moveSilent, extent4);\n this.selection.update(this.clause(this.value));\n }\n }\n clause(value) {\n const { mark: mark2, pixelSize, xfield, yfield, xscale, yscale } = this;\n return clauseIntervals([xfield, yfield], value, {\n source: this,\n clients: this.peers ? mark2.plot.markSet : (/* @__PURE__ */ new Set()).add(mark2),\n scales: [xscale, yscale],\n pixelSize\n });\n }\n init(svg) {\n const { brush: brush3, style: style2 } = this;\n const xscale = this.xscale = svg.scale(\"x\");\n const yscale = this.yscale = svg.scale(\"y\");\n const rx = xscale.range;\n const ry = yscale.range;\n brush3.extent([[min2(rx), min2(ry)], [max2(rx), max2(ry)]]);\n const facets = select_default2(svg).selectAll('g[aria-label=\"facet\"]');\n const root2 = facets.size() ? facets : select_default2(svg);\n this.g = root2.append(\"g\").attr(\"class\", `interval-xy`).each(patchScreenCTM).call(brush3);\n if (style2) {\n const brushes = this.g.selectAll(\"rect.selection\");\n for (const name2 in style2) {\n brushes.attr(name2, style2[name2]);\n }\n }\n if (this.value) {\n const [x12, x22] = this.value[0].map(xscale.apply).sort(ascending);\n const [y12, y22] = this.value[1].map(yscale.apply).sort(ascending);\n this.g.call(brush3.moveSilent, [[x12, y12], [x22, y22]]);\n }\n svg.addEventListener(\"pointerenter\", (evt) => {\n if (!evt.buttons) this.activate();\n });\n }\n};\n\n// ../plot/src/interactors/Nearest.js\nvar Nearest = class {\n constructor(mark2, {\n selection: selection2,\n pointer: pointer2,\n channels,\n fields,\n maxRadius = 40\n }) {\n this.mark = mark2;\n this.selection = selection2;\n this.clients = (/* @__PURE__ */ new Set()).add(mark2);\n this.pointer = pointer2;\n this.channels = channels || (pointer2 === \"x\" ? [\"x\"] : pointer2 === \"y\" ? [\"y\"] : [\"x\", \"y\"]);\n this.fields = fields || this.channels.map((c4) => getField(mark2, [c4]));\n this.maxRadius = maxRadius;\n this.valueIndex = -1;\n }\n clause(value) {\n const { clients, fields } = this;\n const opt = { source: this, clients };\n return fields.length > 1 ? clausePoints(fields, value ? [value] : value, opt) : clausePoint(fields[0], value?.[0], opt);\n }\n init(svg) {\n const that = this;\n const { mark: mark2, channels, selection: selection2, maxRadius } = this;\n const { data: { columns } } = mark2;\n const keys = channels.map((c4) => mark2.channelField(c4).as);\n const param = !isSelection(selection2);\n const facets = select_default2(svg).selectAll('g[aria-label=\"facet\"]');\n const root2 = facets.size() ? facets : select_default2(svg);\n const xscale = svg.scale(\"x\").apply;\n const yscale = svg.scale(\"y\").apply;\n const X3 = Array.from(columns[mark2.channelField(\"x\").as], xscale);\n const Y3 = Array.from(columns[mark2.channelField(\"y\").as], yscale);\n const sx = this.pointer === \"y\" ? 0.01 : 1;\n const sy = this.pointer === \"x\" ? 0.01 : 1;\n root2.on(\"pointerenter pointerdown pointermove\", function(evt) {\n const [px, py] = pointer_default(evt, this);\n const i = findNearest(X3, Y3, px, py, sx, sy, maxRadius);\n if (i !== this.valueIndex) {\n this.valueIndex = i;\n const v2 = i < 0 ? void 0 : keys.map((k2) => columns[k2][i]);\n selection2.update(\n // provide value for param, clause for selection\n param ? !v2 || v2.length > 1 ? v2 : v2[0] : that.clause(v2)\n );\n }\n });\n if (param) return;\n root2.on(\"pointerleave\", () => {\n selection2.update(that.clause(void 0));\n });\n svg.addEventListener(\"pointerenter\", (evt) => {\n if (!evt.buttons) {\n const v2 = this.channels.map(() => 0);\n selection2.activate(this.clause(v2));\n }\n });\n }\n};\nfunction findNearest(x3, y3, px, py, sx, sy, maxRadius) {\n let dist2 = maxRadius * maxRadius;\n let nearest2 = -1;\n for (let i = 0; i < x3.length; ++i) {\n const dx = sx * (x3[i] - px);\n const dy = sy * (y3[i] - py);\n const dd = dx * dx + dy * dy;\n if (dd <= dist2) {\n dist2 = dd;\n nearest2 = i;\n }\n }\n return nearest2;\n}\n\n// ../plot/src/interactors/PanZoom.js\nvar asc = (a2, b) => a2 - b;\nvar PanZoom = class {\n constructor(mark2, {\n x: x3 = new Selection(),\n y: y3 = new Selection(),\n xfield,\n yfield,\n zoom: zoom2 = true,\n panx = true,\n pany = true\n }) {\n this.mark = mark2;\n this.xsel = x3;\n this.ysel = y3;\n this.xfield = xfield || getField(mark2, \"x\");\n this.yfield = yfield || getField(mark2, \"y\");\n this.zoom = extent3(zoom2, [0, Infinity], [1, 1]);\n this.panx = this.xsel && panx;\n this.pany = this.ysel && pany;\n const { plot: plot3 } = mark2;\n if (panx) {\n this.xsel.addEventListener(\"value\", (value) => {\n if (plot3.setAttribute(\"xDomain\", value)) plot3.update();\n });\n }\n if (pany) {\n this.ysel.addEventListener(\"value\", (value) => {\n if (plot3.setAttribute(\"yDomain\", value)) plot3.update();\n });\n }\n }\n publish(transform3) {\n if (this.panx) {\n const xdom = rescaleX(transform3, this.xscale);\n this.xsel.update(this.clause(xdom, this.xfield, this.xscale));\n }\n if (this.pany) {\n const ydom = rescaleY(transform3, this.yscale);\n this.ysel.update(this.clause(ydom, this.yfield, this.yscale));\n }\n }\n clause(value, field3, scale3) {\n return clauseInterval(field3, value, {\n source: this,\n clients: this.mark.plot.markSet,\n scale: scale3\n });\n }\n init(svg) {\n this.svg = svg;\n if (this.initialized) return;\n else this.initialized = true;\n const { panx, pany, mark: { plot: { element } }, xsel, ysel } = this;\n this.xscale = svg.scale(\"x\");\n this.yscale = svg.scale(\"y\");\n const rx = this.xscale.range.slice().sort(asc);\n const ry = this.yscale.range.slice().sort(asc);\n const tx = extent3(panx, [-Infinity, Infinity], rx);\n const ty = extent3(pany, [-Infinity, Infinity], ry);\n const z = zoom_default2().extent([[rx[0], ry[0]], [rx[1], ry[1]]]).scaleExtent(this.zoom).translateExtent([[tx[0], ty[0]], [tx[1], ty[1]]]).on(\"start\", () => {\n this.xscale = this.svg.scale(\"x\");\n this.yscale = this.svg.scale(\"y\");\n }).on(\"end\", () => element.__zoom = new Transform2(1, 0, 0)).on(\"zoom\", ({ transform: transform3 }) => this.publish(transform3));\n select_default2(element).call(z);\n if (panx || pany) {\n let enter = false;\n element.addEventListener(\"pointerenter\", (evt) => {\n if (enter) return;\n else enter = true;\n if (evt.buttons) return;\n if (panx) {\n const { xscale, xfield } = this;\n xsel.activate(this.clause(xscale.domain, xfield, xscale));\n }\n if (pany) {\n const { yscale, yfield } = this;\n ysel.activate(this.clause(yscale.domain, yfield, yscale));\n }\n });\n element.addEventListener(\"pointerleave\", () => enter = false);\n }\n }\n};\nfunction extent3(ext, defaultTrue, defaultFalse) {\n return ext ? Array.isArray(ext) ? ext : defaultTrue : defaultFalse;\n}\nfunction rescaleX(transform3, scale3) {\n return scale3.range.map(transform3.invertX, transform3).map(scale3.invert, scale3);\n}\nfunction rescaleY(transform3, scale3) {\n return scale3.range.map(transform3.invertY, transform3).map(scale3.invert, scale3);\n}\n\n// ../plot/src/interactors/Toggle.js\nvar Toggle = class {\n /**\n * @param {*} mark The mark to interact with.\n * @param {*} options The interactor options.\n */\n constructor(mark2, {\n selection: selection2,\n channels,\n peers = true\n }) {\n this.value = null;\n this.mark = mark2;\n this.selection = selection2;\n this.peers = peers;\n const fields = this.fields = [];\n const as = this.as = [];\n channels.forEach((c4) => {\n const q = c4 === \"color\" ? [\"color\", \"fill\", \"stroke\"] : c4 === \"x\" ? [\"x\", \"x1\", \"x2\"] : c4 === \"y\" ? [\"y\", \"y1\", \"y2\"] : [c4];\n for (let i = 0; i < q.length; ++i) {\n const f = mark2.channelField(q[i], { exact: true });\n if (f) {\n fields.push(f.field?.basis || f.field);\n as.push(f.as);\n return;\n }\n }\n throw new Error(`Missing channel: ${c4}`);\n });\n }\n clause(value) {\n const { fields, mark: mark2 } = this;\n return clausePoints(fields, value, {\n source: this,\n clients: this.peers ? mark2.plot.markSet : (/* @__PURE__ */ new Set()).add(mark2)\n });\n }\n init(svg, selector, accessor) {\n const { mark: mark2, as, selection: selection2 } = this;\n const { data: { columns = {} } = {} } = mark2;\n accessor ??= (target) => as.map((name2) => {\n const data = target.__data__;\n return columns[name2][Array.isArray(data) ? data[0] : data];\n });\n selector ??= `[data-index=\"${mark2.index}\"]`;\n const groups2 = new Set(svg.querySelectorAll(selector));\n svg.addEventListener(\"pointerdown\", (evt) => {\n const state = selection2.single ? selection2.value : this.value;\n const target = evt.target;\n let value = null;\n if (isTargetElement(groups2, target)) {\n const point6 = accessor(target);\n if ((evt.shiftKey || evt.metaKey) && state?.length) {\n value = state.filter((s2) => neq2(s2, point6));\n if (value.length === state.length) value.push(point6);\n } else if (state?.length === 1 && !neq2(state[0], point6)) {\n value = null;\n } else {\n value = [point6];\n }\n }\n this.value = value;\n if (neqSome(state, value)) {\n selection2.update(this.clause(value));\n }\n });\n svg.addEventListener(\"pointerenter\", (evt) => {\n if (evt.buttons) return;\n this.selection.activate(this.clause([this.fields.map(() => 0)]));\n });\n }\n};\nfunction isTargetElement(groups2, node) {\n return groups2.has(node) || groups2.has(node.parentNode) || groups2.has(node.parentNode?.parentNode);\n}\nfunction neqSome(a2, b) {\n return a2 == null || b == null ? a2 != null || b != null : a2.length !== b.length || a2.some((x3, i) => neq2(x3, b[i]));\n}\nfunction neq2(a2, b) {\n const n = a2.length;\n if (b.length !== n) return true;\n for (let i = 0; i < n; ++i) {\n if (a2[i] !== b[i]) return true;\n }\n return false;\n}\n\n// ../plot/src/legend.js\nvar TOGGLE_SELECTOR = \":scope > div, :scope > span\";\nvar SWATCH = \"swatch\";\nvar RAMP = \"ramp\";\nvar Legend = class {\n constructor(channel, options) {\n const { as, field: field3, ...rest } = options;\n this.channel = channel;\n this.options = rest;\n this.type = null;\n this.handler = null;\n this.selection = as;\n this.field = field3;\n this.legend = null;\n this.element = document.createElement(\"div\");\n this.element.setAttribute(\"class\", \"legend\");\n Object.defineProperty(this.element, \"value\", { value: this });\n }\n setPlot(plot3) {\n this.plot = plot3;\n }\n init(svg) {\n const el = createLegend(this, svg);\n this.element.replaceChildren(el);\n return this.element;\n }\n update() {\n if (!this.legend) return;\n const { selection: selection2, handler } = this;\n const { single, value } = selection2;\n const vals = single ? value : selection2.valueFor(handler);\n const curr = vals && vals.length ? new Set(vals.map((v2) => v2[0])) : null;\n const nodes = this.legend.querySelectorAll(TOGGLE_SELECTOR);\n for (const node of nodes) {\n const selected = curr ? curr.has(node.__data__) : true;\n node.style.opacity = selected ? 1 : 0.2;\n }\n }\n};\nfunction createLegend(legend3, svg) {\n const { channel, plot: plot3, selection: selection2 } = legend3;\n const scale3 = svg.scale(channel);\n const type2 = scale3.type === \"ordinal\" ? SWATCH : RAMP;\n const options = {\n label: plot3.getAttribute(`${channel}Label`) ?? null,\n ...legend3.options\n };\n const opt = type2 === SWATCH ? options : options.label ? { tickSize: 2, ...options } : { tickSize: 2, marginTop: 1, height: 29, ...options };\n const el = svg.legend(channel, opt);\n legend3.legend = el;\n let interactive = !!selection2;\n if (interactive && type2 === RAMP) {\n const width2 = opt.width ?? 240;\n const spatial = spatialScale(scale3, width2);\n if (spatial) {\n el.scale = function(type3) {\n return type3 === \"x\" ? { range: [0, width2] } : type3 === \"y\" ? { range: [-10, 0] } : type3 === channel ? spatial : void 0;\n };\n } else {\n interactive = false;\n }\n }\n if (interactive) {\n const handler = getInteractor(legend3, type2);\n if (type2 === SWATCH) {\n handler.init(el, TOGGLE_SELECTOR, (el2) => [el2.__data__]);\n legend3.update();\n } else {\n handler.init(el, el.querySelector(\"g:last-of-type\"));\n }\n }\n return el;\n}\nfunction getInteractor(legend3, type2) {\n const { channel, handler, selection: selection2 } = legend3;\n if (handler) return handler;\n const mark2 = interactorMark(legend3);\n if (type2 === SWATCH) {\n legend3.handler = new Toggle(mark2, {\n selection: selection2,\n channels: [channel],\n peers: false\n });\n selection2.addEventListener(\"value\", () => legend3.update());\n } else {\n legend3.handler = new Interval1D(mark2, {\n selection: selection2,\n channel,\n brush: { fill: \"none\", stroke: \"currentColor\" },\n peers: false\n });\n }\n return legend3.handler;\n}\nfunction interactorMark(legend3) {\n const { channel, plot: plot3 } = legend3;\n const field3 = legend3.field ?? findField(plot3.marks, channel) ?? \"value\";\n if (field3) {\n const f = { field: field3 };\n return { plot: plot3, channelField: (c4) => channel === c4 ? f : void 0 };\n }\n}\nfunction findField(marks2, channel) {\n const channels = channel === \"color\" ? [\"fill\", \"stroke\"] : channel === \"opacity\" ? [\"opacity\", \"fillOpacity\", \"strokeOpacity\"] : null;\n if (channels == null) return null;\n for (let i = marks2.length - 1; i > -1; --i) {\n for (const c4 of channels) {\n const field3 = marks2[i].channelField(c4, { exact: true });\n if (field3) return field3.field;\n }\n }\n return null;\n}\nfunction spatialScale(sourceScale, width2) {\n const { apply: apply2, invert: invert2, interpolate, ...rest } = sourceScale;\n let src = sourceScale.type;\n if (src.startsWith(\"diverging-\")) src = src.slice(11);\n let type2;\n switch (src) {\n case \"log\":\n case \"pow\":\n case \"sqrt\":\n case \"symlog\":\n type2 = src;\n break;\n case \"threshold\":\n case \"quantize\":\n case \"quantile\":\n console.warn(`Legends do not yet support ${src} scales.`);\n return null;\n default:\n type2 = \"linear\";\n }\n return scale2({ x: { ...rest, type: type2, range: [0, width2] } });\n}\n\n// ../plot/src/transforms/bin-step.js\nfunction binStep(span, steps, minstep = 0, logb = Math.LN10) {\n let v2;\n const level = Math.ceil(Math.log(steps) / logb);\n let step = Math.max(\n minstep,\n Math.pow(10, Math.round(Math.log(span) / logb) - level)\n );\n while (Math.ceil(span / step) > steps) {\n step *= 10;\n }\n const div = [5, 2];\n for (let i = 0, n = div.length; i < n; ++i) {\n v2 = step / div[i];\n if (v2 >= minstep && span / v2 <= steps) step = v2;\n }\n return step;\n}\nfunction bins(min5, max4, options) {\n let { step, steps, minstep = 0, nice: nice3 = true } = options;\n if (nice3 !== false) {\n const span = max4 - min5;\n const logb = Math.LN10;\n step = step || binStep(span, steps || 25, minstep, logb);\n let v2 = Math.log(step);\n const precision = v2 >= 0 ? 0 : ~~(-v2 / logb) + 1;\n const eps2 = Math.pow(10, -precision - 1);\n v2 = Math.floor(min5 / step + eps2) * step;\n min5 = min5 < v2 ? v2 - step : v2;\n max4 = Math.ceil(max4 / step) * step;\n steps = Math.round((max4 - min5) / step);\n }\n return { min: min5, max: max4, steps };\n}\n\n// ../plot/src/transforms/time-interval.js\nvar YEAR = \"year\";\nvar MONTH = \"month\";\nvar DAY = \"day\";\nvar HOUR = \"hour\";\nvar MINUTE = \"minute\";\nvar SECOND = \"second\";\nvar MILLISECOND = \"millisecond\";\nvar durationSecond3 = 1e3;\nvar durationMinute3 = durationSecond3 * 60;\nvar durationHour3 = durationMinute3 * 60;\nvar durationDay3 = durationHour3 * 24;\nvar durationWeek3 = durationDay3 * 7;\nvar durationMonth3 = durationDay3 * 30;\nvar durationYear3 = durationDay3 * 365;\nvar intervals = [\n [SECOND, 1, durationSecond3],\n [SECOND, 5, 5 * durationSecond3],\n [SECOND, 15, 15 * durationSecond3],\n [SECOND, 30, 30 * durationSecond3],\n [MINUTE, 1, durationMinute3],\n [MINUTE, 5, 5 * durationMinute3],\n [MINUTE, 15, 15 * durationMinute3],\n [MINUTE, 30, 30 * durationMinute3],\n [HOUR, 1, durationHour3],\n [HOUR, 3, 3 * durationHour3],\n [HOUR, 6, 6 * durationHour3],\n [HOUR, 12, 12 * durationHour3],\n [DAY, 1, durationDay3],\n [DAY, 7, durationWeek3],\n [MONTH, 1, durationMonth3],\n [MONTH, 3, 3 * durationMonth3],\n [YEAR, 1, durationYear3]\n];\nfunction timeInterval3(min5, max4, steps) {\n const span = max4 - min5;\n const target = span / steps;\n let i = bisector((i2) => i2[2]).right(intervals, target);\n if (i === intervals.length) {\n return { interval: YEAR, step: binStep(span / durationYear3, steps) };\n } else if (i) {\n i = intervals[target / intervals[i - 1][2] < intervals[i][2] / target ? i - 1 : i];\n return { interval: i[0], step: i[1] };\n } else {\n return { interval: MILLISECOND, step: binStep(span, steps, 1) };\n }\n}\n\n// ../plot/src/transforms/bin.js\nvar EXTENT = /* @__PURE__ */ new Set([\n \"rectY-x\",\n \"rectX-y\",\n \"rect-x\",\n \"rect-y\",\n \"ruleY-x\",\n \"ruleX-y\"\n]);\nfunction hasExtent(mark2, channel) {\n return EXTENT.has(`${mark2.type}-${channel}`);\n}\nfunction bin2(field3, options = {}) {\n const fn = (mark2, channel) => {\n if (hasExtent(mark2, channel)) {\n return {\n [`${channel}1`]: binField(mark2, channel, field3, options),\n [`${channel}2`]: binField(mark2, channel, field3, { ...options, offset: 1 })\n };\n } else {\n return {\n [channel]: binField(mark2, channel, field3, options)\n };\n }\n };\n fn[Transform] = true;\n return fn;\n}\nfunction binField(mark2, channel, column3, options) {\n return {\n column: column3,\n label: column3,\n get columns() {\n return [column3];\n },\n get basis() {\n return column3;\n },\n get stats() {\n return { column: column3, stats: [\"min\", \"max\"] };\n },\n toString() {\n const { type: type2, min: min5, max: max4 } = mark2.channelField(channel);\n const { interval: i, steps, offset: offset2 = 0 } = options;\n const interval3 = i ?? (type2 === \"date\" || hasTimeScale(mark2, channel) ? \"date\" : \"number\");\n if (interval3 === \"number\") {\n const { apply: apply2, sqlApply, sqlInvert } = channelScale(mark2, channel);\n const b = bins(apply2(min5), apply2(max4), options);\n const col = sqlApply(column3);\n const base = b.min === 0 ? col : `(${col} - ${b.min})`;\n const alpha = `${(b.max - b.min) / b.steps}::DOUBLE`;\n const off = offset2 ? `${offset2} + ` : \"\";\n const expr = `${b.min} + ${alpha} * (${off}FLOOR(${base} / ${alpha}))`;\n return `${sqlInvert(expr)}`;\n } else {\n const { interval: unit3, step = 1 } = interval3 === \"date\" ? timeInterval3(min5, max4, steps || 40) : options;\n const off = offset2 ? ` + INTERVAL ${offset2 * step} ${unit3}` : \"\";\n return `(${dateBin(column3, unit3, step)}${off})`;\n }\n }\n };\n}\nfunction hasTimeScale(mark2, channel) {\n const scale3 = mark2.plot.getAttribute(`${channel}Scale`);\n return scale3 === \"utc\" || scale3 === \"time\";\n}\n\n// ../inputs/src/Menu.js\nvar isObject2 = (v2) => {\n return v2 && typeof v2 === \"object\" && !Array.isArray(v2);\n};\nvar Menu = class extends MosaicClient {\n /**\n * Create a new menu input.\n * @param {object} [options] Options object\n * @param {HTMLElement} [options.element] The parent DOM element in which to\n * place the menu elements. If undefined, a new `div` element is created.\n * @param {Selection} [options.filterBy] A selection to filter the database\n * table indicated by the *from* option.\n * @param {Param} [options.as] The output param or selection. A selection\n * clause is added for the currently selected menu option.\n * @param {string} [options.field] The database column name to use within\n * generated selection clause predicates. Defaults to the *column* option.\n * @param {(any | { value: any, label?: string })[]} [options.options] An\n * array of menu options, as literal values or option objects. Option\n * objects have a `value` property and an optional `label` property. If no\n * label or *format* function is provided, the string-coerced value is used.\n * @param {(value: any) => string} [options.format] A format function that\n * takes an option value as input and generates a string label. The format\n * function is not applied when an explicit label is provided in an option\n * object.\n * @param {*} [options.value] The initial selected menu value.\n * @param {string} [options.from] The name of a database table to use as a data\n * source for this widget. Used in conjunction with the *column* option.\n * @param {string} [options.column] The name of a database column from which\n * to pull menu options. The unique column values are used as menu options.\n * Used in conjunction with the *from* option.\n * @param {string} [options.label] A text label for this input.\n */\n constructor({\n element,\n filterBy,\n from: from2,\n column: column3,\n label: label2 = column3,\n format: format3 = (x3) => x3,\n // TODO\n options,\n value,\n field: field3 = column3,\n as\n } = {}) {\n super(filterBy);\n this.from = from2;\n this.column = column3;\n this.format = format3;\n this.field = field3;\n const selection2 = this.selection = as;\n this.element = element ?? document.createElement(\"div\");\n this.element.setAttribute(\"class\", \"input\");\n Object.defineProperty(this.element, \"value\", { value: this });\n const lab3 = document.createElement(\"label\");\n lab3.innerText = label2 || column3;\n this.element.appendChild(lab3);\n this.select = document.createElement(\"select\");\n this.element.appendChild(this.select);\n if (options) {\n this.data = options.map((value2) => isObject2(value2) ? value2 : { value: value2 });\n this.selectedValue(value ?? \"\");\n this.update();\n }\n if (selection2) {\n const isParam2 = !isSelection(selection2);\n if (value != null && (!isParam2 || selection2.value === void 0)) {\n this.publish(value);\n }\n this.select.addEventListener(\"input\", () => {\n this.publish(this.selectedValue() ?? null);\n });\n if (isParam2) {\n this.selection.addEventListener(\"value\", (value2) => {\n if (value2 !== this.select.value) {\n this.selectedValue(value2);\n }\n });\n }\n }\n }\n selectedValue(value) {\n if (arguments.length === 0) {\n const index2 = this.select.selectedIndex;\n return this.data[index2].value;\n } else {\n const index2 = this.data?.findIndex((opt) => opt.value === value);\n if (index2 >= 0) {\n this.select.selectedIndex = index2;\n } else {\n this.select.value = String(value);\n }\n }\n }\n reset() {\n this.select.selectedIndex = this.from ? 0 : -1;\n }\n publish(value) {\n const { selection: selection2, field: field3 } = this;\n if (isSelection(selection2)) {\n if (value === \"\") value = void 0;\n const clause = clausePoint(field3, value, { source: this });\n selection2.update(clause);\n } else if (isParam(selection2)) {\n selection2.update(value);\n }\n }\n query(filter3 = []) {\n const { from: from2, column: column3 } = this;\n if (!from2) return null;\n return Query.from(from2).select({ value: column3 }).distinct().where(filter3).orderby(column3);\n }\n queryResult(data) {\n this.data = [{ value: \"\", label: \"All\" }, ...data];\n return this;\n }\n update() {\n const { data, format: format3, select: select2, selection: selection2 } = this;\n select2.replaceChildren();\n for (const { value, label: label2 } of data) {\n const opt = document.createElement(\"option\");\n opt.setAttribute(\"value\", value);\n opt.innerText = label2 ?? format3(value);\n this.select.appendChild(opt);\n }\n if (selection2) {\n const value = isSelection(selection2) ? selection2.valueFor(this) : selection2.value;\n this.selectedValue(value ?? \"\");\n }\n return this;\n }\n};\n\n// ../inputs/src/Search.js\nvar _id = 0;\nvar Search = class extends MosaicClient {\n /**\n * Create a new text search input.\n * @param {object} [options] Options object\n * @param {HTMLElement} [options.element] The parent DOM element in which to\n * place the search elements. If undefined, a new `div` element is created.\n * @param {Selection} [options.filterBy] A selection to filter the database\n * table indicated by the *from* option.\n * @param {Param} [options.as] The output param or selection. A selection\n * clause is added based on the current text search query.\n * @param {string} [options.field] The database column name to use within\n * generated selection clause predicates. Defaults to the *column* option.\n * @param {'contains' | 'prefix' | 'suffix' | 'regexp'} [options.type] The\n * type of text search query to perform. One of:\n * - `\"contains\"` (default): the query string may appear anywhere in the text\n * - `\"prefix\"`: the query string must appear at the start of the text\n * - `\"suffix\"`: the query string must appear at the end of the text\n * - `\"regexp\"`: the query string is a regular expression the text must match\n * @param {string} [options.from] The name of a database table to use as an\n * autocomplete data source for this widget. Used in conjunction with the\n * *column* option.\n * @param {string} [options.column] The name of a database column from which\n * to pull valid search results. The unique column values are used as search\n * autocomplete values. Used in conjunction with the *from* option.\n * @param {string} [options.label] A text label for this input.\n */\n constructor({\n element,\n filterBy,\n from: from2,\n column: column3,\n label: label2,\n type: type2 = \"contains\",\n field: field3 = column3,\n as\n } = {}) {\n super(filterBy);\n this.id = \"search_\" + ++_id;\n this.type = type2;\n this.from = from2;\n this.column = column3;\n this.selection = as;\n this.field = field3;\n this.element = element ?? document.createElement(\"div\");\n this.element.setAttribute(\"class\", \"input\");\n Object.defineProperty(this.element, \"value\", { value: this });\n if (label2) {\n const lab3 = document.createElement(\"label\");\n lab3.setAttribute(\"for\", this.id);\n lab3.innerText = label2;\n this.element.appendChild(lab3);\n }\n this.searchbox = document.createElement(\"input\");\n this.searchbox.setAttribute(\"id\", this.id);\n this.searchbox.setAttribute(\"type\", \"text\");\n this.searchbox.setAttribute(\"placeholder\", \"Query\");\n this.element.appendChild(this.searchbox);\n if (this.selection) {\n this.searchbox.addEventListener(\"input\", () => {\n this.publish(this.searchbox.value || null);\n });\n if (!isSelection(this.selection)) {\n this.selection.addEventListener(\"value\", (value) => {\n if (value !== this.searchbox.value) {\n this.searchbox.value = value;\n }\n });\n }\n }\n }\n reset() {\n this.searchbox.value = \"\";\n }\n publish(value) {\n const { selection: selection2, field: field3, type: type2 } = this;\n if (isSelection(selection2)) {\n const clause = clauseMatch(field3, value, { source: this, method: type2 });\n selection2.update(clause);\n } else if (isParam(selection2)) {\n selection2.update(value);\n }\n }\n query(filter3 = []) {\n const { from: from2, column: column3 } = this;\n if (!from2) return null;\n return Query.from(from2).select({ list: column3 }).distinct().where(filter3);\n }\n queryResult(data) {\n this.data = data;\n return this;\n }\n update() {\n const list2 = document.createElement(\"datalist\");\n const id2 = `${this.id}_list`;\n list2.setAttribute(\"id\", id2);\n for (const d of this.data) {\n const opt = document.createElement(\"option\");\n opt.setAttribute(\"value\", d.list);\n list2.append(opt);\n }\n if (this.datalist) this.datalist.remove();\n this.element.appendChild(this.datalist = list2);\n this.searchbox.setAttribute(\"list\", id2);\n return this;\n }\n};\n\n// ../inputs/src/Slider.js\nvar _id2 = 0;\nvar Slider = class extends MosaicClient {\n /**\n * Create a new slider input.\n * @param {object} [options] Options object\n * @param {HTMLElement} [options.element] The parent DOM element in which to\n * place the slider elements. If undefined, a new `div` element is created.\n * @param {Selection} [options.filterBy] A selection to filter the database\n * table indicated by the *from* option.\n * @param {Param} [options.as] The output param or selection. A selection\n * clause is added based on the currently selected slider option.\n * @param {string} [options.field] The database column name to use within\n * generated selection clause predicates. Defaults to the *column* option.\n * @param {'point' | 'interval'} [options.select] The type of selection clause\n * predicate to generate if the **as** option is a Selection. If `'point'`\n * (the default), the selection predicate is an equality check for the slider\n * value. If `'interval'`, the predicate checks an interval from the minimum\n * to the current slider value.\n * @param {number} [options.min] The minimum slider value.\n * @param {number} [options.max] The maximum slider value.\n * @param {number} [options.step] The slider step, the amount to increment\n * between consecutive values.\n * @param {number} [options.value] The initial slider value.\n * @param {string} [options.from] The name of a database table to use as a data\n * source for this widget. Used in conjunction with the *column* option.\n * The minimum and maximum values of the column determine the slider range.\n * @param {string} [options.column] The name of a database column whose values\n * determine the slider range. Used in conjunction with the *from* option.\n * The minimum and maximum values of the column determine the slider range.\n * @param {string} [options.label] A text label for this input.\n * @param {number} [options.width] The width of the slider in screen pixels.\n */\n constructor({\n element,\n filterBy,\n as,\n min: min5,\n max: max4,\n step,\n from: from2,\n column: column3,\n label: label2 = column3,\n value = as?.value,\n select: select2 = \"point\",\n field: field3 = column3,\n width: width2\n } = {}) {\n super(filterBy);\n this.id = \"slider_\" + ++_id2;\n this.from = from2;\n this.column = column3 || \"value\";\n this.selection = as;\n this.selectionType = select2;\n this.field = field3;\n this.min = min5;\n this.max = max4;\n this.step = step;\n this.element = element || document.createElement(\"div\");\n this.element.setAttribute(\"class\", \"input\");\n Object.defineProperty(this.element, \"value\", { value: this });\n if (label2) {\n const desc2 = document.createElement(\"label\");\n desc2.setAttribute(\"for\", this.id);\n desc2.innerText = label2;\n this.element.appendChild(desc2);\n }\n this.slider = document.createElement(\"input\");\n this.slider.setAttribute(\"id\", this.id);\n this.slider.setAttribute(\"type\", \"range\");\n if (width2 != null) this.slider.style.width = `${+width2}px`;\n if (min5 != null) this.slider.setAttribute(\"min\", `${min5}`);\n if (max4 != null) this.slider.setAttribute(\"max\", `${max4}`);\n if (step != null) this.slider.setAttribute(\"step\", `${step}`);\n this.element.appendChild(this.slider);\n this.curval = document.createElement(\"label\");\n this.curval.setAttribute(\"for\", this.id);\n this.curval.setAttribute(\"class\", \"value\");\n this.element.appendChild(this.curval);\n if (value != null) {\n this.slider.setAttribute(\"value\", `${value}`);\n if (this.selection?.value === void 0) this.publish(value);\n }\n this.curval.innerText = this.slider.value;\n this.slider.addEventListener(\"input\", () => {\n const { value: value2 } = this.slider;\n this.curval.innerText = value2;\n if (this.selection) this.publish(+value2);\n });\n if (this.selection && !isSelection(this.selection)) {\n this.selection.addEventListener(\"value\", (value2) => {\n if (value2 !== +this.slider.value) {\n this.slider.value = value2;\n this.curval.innerText = value2;\n }\n });\n }\n }\n query(filter3 = []) {\n const { from: from2, column: column3 } = this;\n if (!from2 || this.min != null && this.max != null) return null;\n return Query.select({ min: min(column3), max: max(column3) }).from(from2).where(filter3);\n }\n queryResult(data) {\n const { min: min5, max: max4 } = Array.from(data)[0];\n if (this.min == null) {\n this.min = min5;\n this.slider.setAttribute(\"min\", `${min5}`);\n }\n if (this.max == null) {\n this.max = max4;\n this.slider.setAttribute(\"max\", `${max4}`);\n }\n if (this.step == null) {\n this.step = (max4 - min5) / 500;\n this.slider.setAttribute(\"step\", `${this.step}`);\n }\n return this;\n }\n publish(value) {\n const { field: field3, selectionType, selection: selection2 } = this;\n if (isSelection(selection2)) {\n if (selectionType === \"interval\") {\n const domain = [this.min ?? 0, value];\n selection2.update(clauseInterval(field3, domain, {\n source: this,\n bin: \"ceil\",\n scale: { type: \"identity\", domain },\n pixelSize: this.step\n }));\n } else {\n selection2.update(clausePoint(field3, value, { source: this }));\n }\n } else if (isParam(this.selection)) {\n selection2.update(value);\n }\n }\n};\n\n// ../inputs/src/util/format.js\nvar formatLocaleAuto = localize((locale3) => {\n const formatNumber3 = formatLocaleNumber(locale3);\n return (value) => value == null ? \"\" : typeof value === \"number\" ? formatNumber3(value) : value instanceof Date ? formatDate(value) : `${value}`;\n});\nvar formatLocaleNumber = localize((locale3) => {\n return (value) => value === 0 ? \"0\" : value.toLocaleString(locale3);\n});\nvar formatAuto2 = formatLocaleAuto();\nvar formatNumber2 = formatLocaleNumber();\nfunction formatDate(date3) {\n return format2(date3, \"Invalid Date\");\n}\nfunction localize(f) {\n let key = null;\n let value;\n return (locale3 = \"en\") => locale3 === key ? value : value = f(key = locale3);\n}\n\n// ../inputs/src/Table.js\nvar _id3 = -1;\nvar Table2 = class extends MosaicClient {\n /**\n * Create a new Table instance.\n * @param {object} options Options object\n */\n constructor({\n element,\n filterBy,\n from: from2,\n columns = [\"*\"],\n align: align3 = {},\n format: format3,\n width: width2,\n maxWidth,\n height: height2 = 500,\n rowBatch = 100,\n as\n } = {}) {\n super(filterBy);\n this.id = `table-${++_id3}`;\n this.from = from2;\n this.columns = columns;\n this.format = format3;\n this.align = align3;\n this.widths = typeof width2 === \"object\" ? width2 : {};\n this.offset = 0;\n this.limit = +rowBatch;\n this.pending = false;\n this.selection = as;\n this.currentRow = -1;\n this.sortHeader = null;\n this.sortColumn = null;\n this.sortDesc = false;\n this.element = element || document.createElement(\"div\");\n this.element.setAttribute(\"id\", this.id);\n Object.defineProperty(this.element, \"value\", { value: this });\n if (typeof width2 === \"number\") this.element.style.width = `${width2}px`;\n if (maxWidth) this.element.style.maxWidth = `${maxWidth}px`;\n this.element.style.maxHeight = `${height2}px`;\n this.element.style.overflow = \"auto\";\n let prevScrollTop = -1;\n this.element.addEventListener(\"scroll\", (evt) => {\n const { pending, loaded } = this;\n const { scrollHeight, scrollTop, clientHeight } = evt.target;\n const back = scrollTop < prevScrollTop;\n prevScrollTop = scrollTop;\n if (back || pending || loaded) return;\n if (scrollHeight - scrollTop < 2 * clientHeight) {\n this.pending = true;\n this.requestData(this.offset + this.limit);\n }\n });\n this.tbl = document.createElement(\"table\");\n this.element.appendChild(this.tbl);\n this.head = document.createElement(\"thead\");\n this.tbl.appendChild(this.head);\n this.body = document.createElement(\"tbody\");\n this.tbl.appendChild(this.body);\n if (this.selection) {\n this.body.addEventListener(\"pointerover\", (evt) => {\n const row = resolveRow(evt.target);\n if (row > -1 && row !== this.currentRow) {\n this.currentRow = row;\n this.selection.update(this.clause([row]));\n }\n });\n this.body.addEventListener(\"pointerleave\", () => {\n this.currentRow = -1;\n this.selection.update(this.clause());\n });\n }\n this.style = document.createElement(\"style\");\n this.element.appendChild(this.style);\n }\n clause(rows = []) {\n const { data, limit, schema } = this;\n const fields = schema.map((s2) => s2.column);\n const values2 = rows.map((row) => {\n const { columns } = data[~~(row / limit)];\n return fields.map((f) => columns[f][row % limit]);\n });\n return clausePoints(fields, values2, { source: this });\n }\n requestData(offset2 = 0) {\n this.offset = offset2;\n const query = this.query(this.filterBy?.predicate(this));\n this.requestQuery(query);\n coordinator().prefetch(query.clone().offset(offset2 + this.limit));\n }\n fields() {\n return this.columns.map((name2) => column(this.from, name2));\n }\n fieldInfo(info) {\n this.schema = info;\n const thead = this.head;\n thead.innerHTML = \"\";\n const tr = document.createElement(\"tr\");\n for (const { column: column3 } of info) {\n const th = document.createElement(\"th\");\n th.addEventListener(\"click\", (evt) => this.sort(evt, column3));\n th.appendChild(document.createElement(\"span\"));\n th.appendChild(document.createTextNode(column3));\n tr.appendChild(th);\n }\n thead.appendChild(tr);\n this.formats = formatof(this.format, info);\n this.style.innerText = tableCSS(\n this.id,\n alignof(this.align, info),\n widthof(this.widths, info)\n );\n return this;\n }\n query(filter3 = []) {\n const { from: from2, limit, offset: offset2, schema, sortColumn, sortDesc } = this;\n return Query.from(from2).select(schema.map((s2) => s2.column)).where(filter3).orderby(sortColumn ? sortDesc ? desc(sortColumn) : sortColumn : []).limit(limit).offset(offset2);\n }\n queryResult(data) {\n if (!this.pending) {\n this.loaded = false;\n this.data = [];\n this.body.replaceChildren();\n this.offset = 0;\n }\n this.data.push(toDataColumns(data));\n return this;\n }\n update() {\n const { body, formats, data, schema, limit } = this;\n const nf = schema.length;\n const n = data.length - 1;\n const rowCount = limit * n;\n const { numRows, columns } = data[n];\n const cols = schema.map((s2) => columns[s2.column]);\n for (let i = 0; i < numRows; ++i) {\n const tr = document.createElement(\"tr\");\n Object.assign(tr, { __row__: rowCount + i });\n for (let j = 0; j < nf; ++j) {\n const value = cols[j][i];\n const td = document.createElement(\"td\");\n td.innerText = value == null ? \"\" : formats[j](value);\n tr.appendChild(td);\n }\n body.appendChild(tr);\n }\n if (numRows < limit) {\n this.loaded = true;\n }\n this.pending = false;\n return this;\n }\n sort(event, column3) {\n if (column3 === this.sortColumn) {\n this.sortDesc = !this.sortDesc;\n } else {\n this.sortColumn = column3;\n this.sortDesc = false;\n }\n const th = event.currentTarget;\n const currentHeader = this.sortHeader;\n if (currentHeader === th && event.metaKey) {\n currentHeader.firstChild.textContent = \"\";\n this.sortHeader = null;\n this.sortColumn = null;\n } else {\n if (currentHeader) currentHeader.firstChild.textContent = \"\";\n this.sortHeader = th;\n th.firstChild.textContent = this.sortDesc ? \"\\u25BE\" : \"\\u25B4\";\n }\n this.requestData();\n }\n};\nfunction resolveRow(element) {\n const p = element.parentElement;\n return Object.hasOwn(p, \"__row__\") ? +p.__row__ : -1;\n}\nfunction formatof(base = {}, schema, locale3) {\n return schema.map(({ column: column3, type: type2 }) => {\n if (column3 in base) {\n return base[column3];\n } else {\n switch (type2) {\n case \"number\":\n return formatLocaleNumber(locale3);\n case \"date\":\n return formatDate;\n default:\n return formatLocaleAuto(locale3);\n }\n }\n });\n}\nfunction alignof(base = {}, schema) {\n return schema.map(({ column: column3, type: type2 }) => {\n if (column3 in base) {\n return base[column3];\n } else if (type2 === \"number\") {\n return \"right\";\n } else {\n return \"left\";\n }\n });\n}\nfunction widthof(base = {}, schema) {\n return schema.map(({ column: column3 }) => base[column3]);\n}\nfunction tableCSS(id2, aligns, widths) {\n const styles2 = [];\n aligns.forEach((a2, i) => {\n const w = +widths[i];\n if (a2 !== \"left\" || w) {\n const align3 = a2 !== \"left\" ? `text-align:${a2};` : \"\";\n const width2 = w ? `width:${w}px;max-width:${w}px;` : \"\";\n styles2.push(`#${id2} tr>:nth-child(${i + 1}) {${align3}${width2}}`);\n }\n });\n return styles2.join(\" \");\n}\n\n// ../vgplot/src/connect.js\nfunction connect(ctx, ...clients) {\n const coord = ctx?.context?.coordinator ?? coordinator();\n for (const client of clients) {\n coord.connect(client);\n }\n}\n\n// ../vgplot/src/inputs.js\nfunction input2(ctx, InputClass, options) {\n const input3 = new InputClass(options);\n connect(ctx, input3);\n return input3.element;\n}\nfunction menu2(options) {\n return input2(this, Menu, options);\n}\nfunction search2(options) {\n return input2(this, Search, options);\n}\nfunction slider2(options) {\n return input2(this, Slider, options);\n}\nfunction table2(options) {\n return input2(this, Table2, options);\n}\n\n// ../vgplot/src/layout/concat.js\nfunction concat2({ direction = \"vertical\", wrap: wrap3 = false }, children2) {\n const div = document.createElement(\"div\");\n div.style.display = \"flex\";\n div.style.flexDirection = direction === \"vertical\" ? \"column\" : \"row\";\n div.style.flexWrap = !wrap3 ? \"nowrap\" : wrap3 === true ? \"wrap\" : wrap3;\n div.style.justifyContent = \"flex-start\";\n div.style.alignItems = \"flex-start\";\n children2.forEach((child) => div.appendChild(child));\n Object.assign(div, { value: { element: div } });\n return div;\n}\nfunction vconcat(...plots) {\n return concat2({ direction: \"vertical\" }, plots.flat());\n}\nfunction hconcat(...plots) {\n return concat2({ direction: \"horizontal\" }, plots.flat());\n}\n\n// ../vgplot/src/layout/space.js\nfunction space({ dim = \"width\", size = 10 }) {\n const span = document.createElement(\"span\");\n span.style.display = \"inline-block\";\n span.style[dim] = Number.isNaN(+size) ? size : `${size}px`;\n return Object.assign(span, { value: { element: span } });\n}\nfunction vspace(size) {\n return space({ dim: \"height\", size });\n}\nfunction hspace(size) {\n return space({ dim: \"width\", size });\n}\n\n// ../vgplot/src/plot/attributes.js\nvar attributes_exports = {};\n__export(attributes_exports, {\n align: () => align2,\n aspectRatio: () => aspectRatio,\n axis: () => axis2,\n colorBase: () => colorBase,\n colorClamp: () => colorClamp,\n colorConstant: () => colorConstant2,\n colorDomain: () => colorDomain,\n colorExponent: () => colorExponent,\n colorInterpolate: () => colorInterpolate,\n colorLabel: () => colorLabel,\n colorN: () => colorN,\n colorNice: () => colorNice,\n colorPercent: () => colorPercent,\n colorPivot: () => colorPivot,\n colorRange: () => colorRange,\n colorReverse: () => colorReverse,\n colorScale: () => colorScale2,\n colorScheme: () => colorScheme2,\n colorSymmetric: () => colorSymmetric,\n colorTickFormat: () => colorTickFormat,\n colorZero: () => colorZero,\n facetGrid: () => facetGrid,\n facetLabel: () => facetLabel,\n facetMargin: () => facetMargin,\n facetMarginBottom: () => facetMarginBottom,\n facetMarginLeft: () => facetMarginLeft,\n facetMarginRight: () => facetMarginRight,\n facetMarginTop: () => facetMarginTop,\n fxAlign: () => fxAlign,\n fxAriaDescription: () => fxAriaDescription,\n fxAriaLabel: () => fxAriaLabel,\n fxAxis: () => fxAxis,\n fxDomain: () => fxDomain,\n fxFontVariant: () => fxFontVariant,\n fxGrid: () => fxGrid,\n fxInset: () => fxInset,\n fxInsetLeft: () => fxInsetLeft,\n fxInsetRight: () => fxInsetRight,\n fxLabel: () => fxLabel,\n fxLabelAnchor: () => fxLabelAnchor,\n fxLabelOffset: () => fxLabelOffset,\n fxLine: () => fxLine,\n fxPadding: () => fxPadding,\n fxPaddingInner: () => fxPaddingInner,\n fxPaddingOuter: () => fxPaddingOuter,\n fxRange: () => fxRange,\n fxReverse: () => fxReverse,\n fxRound: () => fxRound,\n fxTickFormat: () => fxTickFormat,\n fxTickPadding: () => fxTickPadding,\n fxTickRotate: () => fxTickRotate,\n fxTickSize: () => fxTickSize,\n fxTickSpacing: () => fxTickSpacing,\n fxTicks: () => fxTicks,\n fyAlign: () => fyAlign,\n fyAriaDescription: () => fyAriaDescription,\n fyAriaLabel: () => fyAriaLabel,\n fyAxis: () => fyAxis,\n fyDomain: () => fyDomain,\n fyFontVariant: () => fyFontVariant,\n fyGrid: () => fyGrid,\n fyInset: () => fyInset,\n fyInsetBottom: () => fyInsetBottom,\n fyInsetTop: () => fyInsetTop,\n fyLabel: () => fyLabel,\n fyLabelAnchor: () => fyLabelAnchor,\n fyLabelOffset: () => fyLabelOffset,\n fyLine: () => fyLine,\n fyPadding: () => fyPadding,\n fyPaddingInner: () => fyPaddingInner,\n fyPaddingOuter: () => fyPaddingOuter,\n fyRange: () => fyRange,\n fyReverse: () => fyReverse,\n fyRound: () => fyRound,\n fyTickFormat: () => fyTickFormat,\n fyTickPadding: () => fyTickPadding,\n fyTickRotate: () => fyTickRotate,\n fyTickSize: () => fyTickSize,\n fyTickSpacing: () => fyTickSpacing,\n fyTicks: () => fyTicks,\n grid: () => grid,\n height: () => height,\n inset: () => inset,\n label: () => label,\n lengthBase: () => lengthBase,\n lengthClamp: () => lengthClamp,\n lengthConstant: () => lengthConstant,\n lengthDomain: () => lengthDomain,\n lengthExponent: () => lengthExponent,\n lengthNice: () => lengthNice,\n lengthPercent: () => lengthPercent,\n lengthRange: () => lengthRange,\n lengthScale: () => lengthScale,\n lengthZero: () => lengthZero,\n margin: () => margin,\n marginBottom: () => marginBottom,\n marginLeft: () => marginLeft,\n marginRight: () => marginRight,\n marginTop: () => marginTop,\n margins: () => margins,\n name: () => name,\n opacityBase: () => opacityBase,\n opacityClamp: () => opacityClamp,\n opacityConstant: () => opacityConstant,\n opacityDomain: () => opacityDomain,\n opacityExponent: () => opacityExponent,\n opacityLabel: () => opacityLabel,\n opacityNice: () => opacityNice,\n opacityPercent: () => opacityPercent,\n opacityRange: () => opacityRange,\n opacityReverse: () => opacityReverse,\n opacityScale: () => opacityScale,\n opacityTickFormat: () => opacityTickFormat,\n opacityZero: () => opacityZero,\n padding: () => padding,\n projectionClip: () => projectionClip,\n projectionDomain: () => projectionDomain,\n projectionInset: () => projectionInset,\n projectionInsetBottom: () => projectionInsetBottom,\n projectionInsetLeft: () => projectionInsetLeft,\n projectionInsetRight: () => projectionInsetRight,\n projectionInsetTop: () => projectionInsetTop,\n projectionParallels: () => projectionParallels,\n projectionPrecision: () => projectionPrecision,\n projectionRotate: () => projectionRotate,\n projectionType: () => projectionType,\n rBase: () => rBase,\n rClamp: () => rClamp,\n rConstant: () => rConstant,\n rDomain: () => rDomain,\n rExponent: () => rExponent,\n rLabel: () => rLabel,\n rNice: () => rNice,\n rPercent: () => rPercent,\n rRange: () => rRange,\n rScale: () => rScale,\n rZero: () => rZero,\n style: () => style,\n symbolDomain: () => symbolDomain,\n symbolRange: () => symbolRange,\n symbolScale: () => symbolScale,\n width: () => width,\n xAlign: () => xAlign,\n xAriaDescription: () => xAriaDescription,\n xAriaLabel: () => xAriaLabel,\n xAxis: () => xAxis,\n xBase: () => xBase,\n xClamp: () => xClamp,\n xConstant: () => xConstant,\n xDomain: () => xDomain,\n xExponent: () => xExponent,\n xFontVariant: () => xFontVariant,\n xGrid: () => xGrid,\n xInset: () => xInset,\n xInsetLeft: () => xInsetLeft,\n xInsetRight: () => xInsetRight,\n xLabel: () => xLabel,\n xLabelAnchor: () => xLabelAnchor,\n xLabelArrow: () => xLabelArrow,\n xLabelOffset: () => xLabelOffset,\n xLine: () => xLine,\n xNice: () => xNice,\n xPadding: () => xPadding,\n xPaddingInner: () => xPaddingInner,\n xPaddingOuter: () => xPaddingOuter,\n xPercent: () => xPercent,\n xRange: () => xRange,\n xReverse: () => xReverse,\n xRound: () => xRound,\n xScale: () => xScale,\n xTickFormat: () => xTickFormat,\n xTickPadding: () => xTickPadding,\n xTickRotate: () => xTickRotate,\n xTickSize: () => xTickSize,\n xTickSpacing: () => xTickSpacing,\n xTicks: () => xTicks,\n xZero: () => xZero,\n xyDomain: () => xyDomain,\n yAlign: () => yAlign,\n yAriaDescription: () => yAriaDescription,\n yAriaLabel: () => yAriaLabel,\n yAxis: () => yAxis,\n yBase: () => yBase,\n yClamp: () => yClamp,\n yConstant: () => yConstant,\n yDomain: () => yDomain,\n yExponent: () => yExponent,\n yFontVariant: () => yFontVariant,\n yGrid: () => yGrid,\n yInset: () => yInset,\n yInsetBottom: () => yInsetBottom,\n yInsetTop: () => yInsetTop,\n yLabel: () => yLabel,\n yLabelAnchor: () => yLabelAnchor,\n yLabelArrow: () => yLabelArrow,\n yLabelOffset: () => yLabelOffset,\n yLine: () => yLine,\n yNice: () => yNice,\n yPadding: () => yPadding,\n yPaddingInner: () => yPaddingInner,\n yPaddingOuter: () => yPaddingOuter,\n yPercent: () => yPercent,\n yRange: () => yRange,\n yReverse: () => yReverse,\n yRound: () => yRound,\n yScale: () => yScale,\n yTickFormat: () => yTickFormat,\n yTickPadding: () => yTickPadding,\n yTickRotate: () => yTickRotate,\n yTickSize: () => yTickSize,\n yTickSpacing: () => yTickSpacing,\n yTicks: () => yTicks,\n yZero: () => yZero\n});\n\n// ../vgplot/src/plot/named-plots.js\nvar NamedPlots = class extends Map {\n request(name2, callback) {\n if (this.has(name2)) {\n callback(this.get(name2));\n } else {\n const waiting = this.waiting || (this.waiting = /* @__PURE__ */ new Map());\n const list2 = waiting.get(name2) || [];\n waiting.set(name2, list2.concat(callback));\n }\n }\n set(name2, plot3) {\n if (this.has(name2)) {\n console.warn(`Overwriting named plot \"${name2}\".`);\n }\n const { waiting } = this;\n if (waiting?.has(name2)) {\n waiting.get(name2).forEach((fn) => fn(plot3));\n waiting.delete(name2);\n }\n return super.set(name2, plot3);\n }\n clear() {\n this.waiting?.clear();\n return super.clear();\n }\n};\nvar namedPlots = new NamedPlots();\nfunction requestNamedPlot(ctx, name2, callback) {\n const map5 = ctx?.context?.namedPlots ?? namedPlots;\n map5.request(name2, callback);\n}\nfunction setNamedPlot(ctx, name2, plot3) {\n const map5 = ctx?.context?.namedPlots ?? namedPlots;\n map5.set(name2, plot3);\n}\n\n// ../vgplot/src/plot/attributes.js\nfunction name(name2) {\n return (plot3) => setNamedPlot(this, name2, plot3);\n}\nfunction setAttribute(plot3, name2, value) {\n if (isParam(value)) {\n value.addEventListener(\"value\", (value2) => {\n plot3.setAttribute(name2, value2);\n plot3.update();\n });\n if (value.value !== void 0) {\n plot3.setAttribute(name2, value.value);\n }\n } else {\n plot3.setAttribute(name2, value);\n }\n}\nfunction attribute(name2, value) {\n return (plot3) => {\n setAttribute(plot3, name2, value);\n };\n}\nfunction attributes(values2) {\n return (plot3) => {\n for (const [name2, value] of Object.entries(values2)) {\n setAttribute(plot3, name2, value);\n }\n };\n}\nfunction margins(object) {\n const { top: top2, bottom: bottom2, left: left2, right: right2 } = object;\n const attr = {};\n if (top2 !== void 0) attr.marginTop = top2;\n if (bottom2 !== void 0) attr.marginBottom = bottom2;\n if (left2 !== void 0) attr.marginLeft = left2;\n if (right2 !== void 0) attr.marginRight = right2;\n return attributes(attr);\n}\nfunction margin(value) {\n return attributes({\n marginTop: value,\n marginBottom: value,\n marginLeft: value,\n marginRight: value\n });\n}\nfunction xyDomain(value) {\n return attributes({ xDomain: value, yDomain: value });\n}\nvar attrf = (name2) => (value) => attribute(name2, value);\nvar style = attrf(\"style\");\nvar width = attrf(\"width\");\nvar height = attrf(\"height\");\nvar marginLeft = attrf(\"marginLeft\");\nvar marginRight = attrf(\"marginRight\");\nvar marginTop = attrf(\"marginTop\");\nvar marginBottom = attrf(\"marginBottom\");\nvar align2 = attrf(\"align\");\nvar aspectRatio = attrf(\"aspectRatio\");\nvar axis2 = attrf(\"axis\");\nvar inset = attrf(\"inset\");\nvar grid = attrf(\"grid\");\nvar label = attrf(\"label\");\nvar padding = attrf(\"padding\");\nvar xScale = attrf(\"xScale\");\nvar xDomain = attrf(\"xDomain\");\nvar xRange = attrf(\"xRange\");\nvar xNice = attrf(\"xNice\");\nvar xInset = attrf(\"xInset\");\nvar xInsetLeft = attrf(\"xInsetLeft\");\nvar xInsetRight = attrf(\"xInsetRight\");\nvar xClamp = attrf(\"xClamp\");\nvar xRound = attrf(\"xRound\");\nvar xAlign = attrf(\"xAlign\");\nvar xPadding = attrf(\"xPadding\");\nvar xPaddingInner = attrf(\"xPaddingInner\");\nvar xPaddingOuter = attrf(\"xPaddingOuter\");\nvar xAxis = attrf(\"xAxis\");\nvar xTicks = attrf(\"xTicks\");\nvar xTickSize = attrf(\"xTickSize\");\nvar xTickSpacing = attrf(\"xTickSpacing\");\nvar xTickPadding = attrf(\"xTickPadding\");\nvar xTickFormat = attrf(\"xTickFormat\");\nvar xTickRotate = attrf(\"xTickRotate\");\nvar xGrid = attrf(\"xGrid\");\nvar xLine = attrf(\"xLine\");\nvar xLabel = attrf(\"xLabel\");\nvar xLabelAnchor = attrf(\"xLabelAnchor\");\nvar xLabelArrow = attrf(\"xLabelArrow\");\nvar xLabelOffset = attrf(\"xLabelOffset\");\nvar xFontVariant = attrf(\"xFontVariant\");\nvar xAriaLabel = attrf(\"xAriaLabel\");\nvar xAriaDescription = attrf(\"xAriaDescription\");\nvar xPercent = attrf(\"xPercent\");\nvar xReverse = attrf(\"xReverse\");\nvar xZero = attrf(\"xZero\");\nvar xBase = attrf(\"xBase\");\nvar xExponent = attrf(\"xExponent\");\nvar xConstant = attrf(\"xConstant\");\nvar yScale = attrf(\"yScale\");\nvar yDomain = attrf(\"yDomain\");\nvar yRange = attrf(\"yRange\");\nvar yNice = attrf(\"yNice\");\nvar yInset = attrf(\"yInset\");\nvar yInsetTop = attrf(\"yInsetTop\");\nvar yInsetBottom = attrf(\"yInsetBottom\");\nvar yClamp = attrf(\"yClamp\");\nvar yRound = attrf(\"yRound\");\nvar yAlign = attrf(\"yAlign\");\nvar yPadding = attrf(\"yPadding\");\nvar yPaddingInner = attrf(\"yPaddingInner\");\nvar yPaddingOuter = attrf(\"yPaddingOuter\");\nvar yAxis = attrf(\"yAxis\");\nvar yTicks = attrf(\"yTicks\");\nvar yTickSize = attrf(\"yTickSize\");\nvar yTickSpacing = attrf(\"yTickSpacing\");\nvar yTickPadding = attrf(\"yTickPadding\");\nvar yTickFormat = attrf(\"yTickFormat\");\nvar yTickRotate = attrf(\"yTickRotate\");\nvar yGrid = attrf(\"yGrid\");\nvar yLine = attrf(\"yLine\");\nvar yLabel = attrf(\"yLabel\");\nvar yLabelAnchor = attrf(\"yLabelAnchor\");\nvar yLabelArrow = attrf(\"yLabelArrow\");\nvar yLabelOffset = attrf(\"yLabelOffset\");\nvar yFontVariant = attrf(\"yFontVariant\");\nvar yAriaLabel = attrf(\"yAriaLabel\");\nvar yAriaDescription = attrf(\"yAriaDescription\");\nvar yPercent = attrf(\"yPercent\");\nvar yReverse = attrf(\"yReverse\");\nvar yZero = attrf(\"yZero\");\nvar yBase = attrf(\"yBase\");\nvar yExponent = attrf(\"yExponent\");\nvar yConstant = attrf(\"yConstant\");\nvar facetMargin = attrf(\"facetMargin\");\nvar facetMarginTop = attrf(\"facetMarginTop\");\nvar facetMarginBottom = attrf(\"facetMarginBottom\");\nvar facetMarginLeft = attrf(\"facetMarginLeft\");\nvar facetMarginRight = attrf(\"facetMarginRight\");\nvar facetGrid = attrf(\"facetGrid\");\nvar facetLabel = attrf(\"facetLabel\");\nvar fxDomain = attrf(\"fxDomain\");\nvar fxRange = attrf(\"fxRange\");\nvar fxInset = attrf(\"fxInset\");\nvar fxInsetLeft = attrf(\"fxInsetLeft\");\nvar fxInsetRight = attrf(\"fxInsetRight\");\nvar fxRound = attrf(\"fxRound\");\nvar fxAlign = attrf(\"fxAlign\");\nvar fxPadding = attrf(\"fxPadding\");\nvar fxPaddingInner = attrf(\"fxPaddingInner\");\nvar fxPaddingOuter = attrf(\"fxPaddingOuter\");\nvar fxAxis = attrf(\"fxAxis\");\nvar fxTicks = attrf(\"fxTicks\");\nvar fxTickSize = attrf(\"fxTickSize\");\nvar fxTickSpacing = attrf(\"fxTickSpacing\");\nvar fxTickPadding = attrf(\"fxTickPadding\");\nvar fxTickFormat = attrf(\"fxTickFormat\");\nvar fxTickRotate = attrf(\"fxTickRotate\");\nvar fxGrid = attrf(\"fxGrid\");\nvar fxLine = attrf(\"fxLine\");\nvar fxLabel = attrf(\"fxLabel\");\nvar fxLabelAnchor = attrf(\"fxLabelAnchor\");\nvar fxLabelOffset = attrf(\"fxLabelOffset\");\nvar fxFontVariant = attrf(\"fxFontVariant\");\nvar fxAriaLabel = attrf(\"fxAriaLabel\");\nvar fxAriaDescription = attrf(\"fxAriaDescription\");\nvar fxReverse = attrf(\"fxReverse\");\nvar fyDomain = attrf(\"fyDomain\");\nvar fyRange = attrf(\"fyRange\");\nvar fyInset = attrf(\"fyInset\");\nvar fyInsetTop = attrf(\"fyInsetTop\");\nvar fyInsetBottom = attrf(\"fyInsetBottom\");\nvar fyRound = attrf(\"fyRound\");\nvar fyAlign = attrf(\"fyAlign\");\nvar fyPadding = attrf(\"fyPadding\");\nvar fyPaddingInner = attrf(\"fyPaddingInner\");\nvar fyPaddingOuter = attrf(\"fyPaddingOuter\");\nvar fyAxis = attrf(\"fyAxis\");\nvar fyTicks = attrf(\"fyTicks\");\nvar fyTickSize = attrf(\"fyTickSize\");\nvar fyTickSpacing = attrf(\"fyTickSpacing\");\nvar fyTickPadding = attrf(\"fyTickPadding\");\nvar fyTickFormat = attrf(\"fyTickFormat\");\nvar fyTickRotate = attrf(\"fyTickRotate\");\nvar fyGrid = attrf(\"fyGrid\");\nvar fyLine = attrf(\"fyLine\");\nvar fyLabel = attrf(\"fyLabel\");\nvar fyLabelAnchor = attrf(\"fyLabelAnchor\");\nvar fyLabelOffset = attrf(\"fyLabelOffset\");\nvar fyFontVariant = attrf(\"fyFontVariant\");\nvar fyAriaLabel = attrf(\"fyAriaLabel\");\nvar fyAriaDescription = attrf(\"fyAriaDescription\");\nvar fyReverse = attrf(\"fyReverse\");\nvar colorScale2 = attrf(\"colorScale\");\nvar colorDomain = attrf(\"colorDomain\");\nvar colorRange = attrf(\"colorRange\");\nvar colorClamp = attrf(\"colorClamp\");\nvar colorN = attrf(\"colorN\");\nvar colorNice = attrf(\"colorNice\");\nvar colorScheme2 = attrf(\"colorScheme\");\nvar colorInterpolate = attrf(\"colorInterpolate\");\nvar colorPivot = attrf(\"colorPivot\");\nvar colorSymmetric = attrf(\"colorSymmetric\");\nvar colorLabel = attrf(\"colorLabel\");\nvar colorPercent = attrf(\"colorPercent\");\nvar colorReverse = attrf(\"colorReverse\");\nvar colorZero = attrf(\"colorZero\");\nvar colorTickFormat = attrf(\"colorTickFormat\");\nvar colorBase = attrf(\"colorBase\");\nvar colorExponent = attrf(\"colorExponent\");\nvar colorConstant2 = attrf(\"colorConstant\");\nvar opacityScale = attrf(\"opacityScale\");\nvar opacityDomain = attrf(\"opacityDomain\");\nvar opacityRange = attrf(\"opacityRange\");\nvar opacityClamp = attrf(\"opacityClamp\");\nvar opacityNice = attrf(\"opacityNice\");\nvar opacityLabel = attrf(\"opacityLabel\");\nvar opacityPercent = attrf(\"opacityPercent\");\nvar opacityReverse = attrf(\"opacityReverse\");\nvar opacityZero = attrf(\"opacityZero\");\nvar opacityTickFormat = attrf(\"opacityTickFormat\");\nvar opacityBase = attrf(\"opacityBase\");\nvar opacityExponent = attrf(\"opacityExponent\");\nvar opacityConstant = attrf(\"opacityConstant\");\nvar symbolScale = attrf(\"symbolScale\");\nvar symbolDomain = attrf(\"symbolDomain\");\nvar symbolRange = attrf(\"symbolRange\");\nvar rScale = attrf(\"rScale\");\nvar rDomain = attrf(\"rDomain\");\nvar rRange = attrf(\"rRange\");\nvar rClamp = attrf(\"rClamp\");\nvar rNice = attrf(\"rNice\");\nvar rLabel = attrf(\"rLabel\");\nvar rPercent = attrf(\"rPercent\");\nvar rZero = attrf(\"rZero\");\nvar rBase = attrf(\"rBase\");\nvar rExponent = attrf(\"rExponent\");\nvar rConstant = attrf(\"rConstant\");\nvar lengthScale = attrf(\"lengthScale\");\nvar lengthDomain = attrf(\"lengthDomain\");\nvar lengthRange = attrf(\"lengthRange\");\nvar lengthClamp = attrf(\"lengthClamp\");\nvar lengthNice = attrf(\"lengthNice\");\nvar lengthPercent = attrf(\"lengthPercent\");\nvar lengthZero = attrf(\"lengthZero\");\nvar lengthBase = attrf(\"lengthBase\");\nvar lengthExponent = attrf(\"lengthExponent\");\nvar lengthConstant = attrf(\"lengthConstant\");\nvar projectionType = attrf(\"projectionType\");\nvar projectionParallels = attrf(\"projectionParallels\");\nvar projectionPrecision = attrf(\"projectionPrecision\");\nvar projectionRotate = attrf(\"projectionRotate\");\nvar projectionDomain = attrf(\"projectionDomain\");\nvar projectionInset = attrf(\"projectionInset\");\nvar projectionInsetLeft = attrf(\"projectionInsetLeft\");\nvar projectionInsetRight = attrf(\"projectionInsetRight\");\nvar projectionInsetTop = attrf(\"projectionInsetTop\");\nvar projectionInsetBottom = attrf(\"projectionInsetBottom\");\nvar projectionClip = attrf(\"projectionClip\");\n\n// ../vgplot/src/plot/data.js\nfunction from(table3, options) {\n return { table: table3, options };\n}\n\n// ../vgplot/src/plot/marks.js\nvar marks_exports = {};\n__export(marks_exports, {\n area: () => area2,\n areaX: () => areaX2,\n areaY: () => areaY2,\n arrow: () => arrow2,\n axisFx: () => axisFx2,\n axisFy: () => axisFy2,\n axisX: () => axisX2,\n axisY: () => axisY2,\n barX: () => barX2,\n barY: () => barY2,\n cell: () => cell2,\n cellX: () => cellX2,\n cellY: () => cellY2,\n circle: () => circle2,\n contour: () => contour2,\n delaunayLink: () => delaunayLink2,\n delaunayMesh: () => delaunayMesh2,\n denseLine: () => denseLine,\n density: () => density2,\n densityX: () => densityX,\n densityY: () => densityY,\n dot: () => dot2,\n dotX: () => dotX2,\n dotY: () => dotY2,\n errorbarX: () => errorbarX,\n errorbarY: () => errorbarY,\n frame: () => frame3,\n geo: () => geo2,\n graticule: () => graticule3,\n gridFx: () => gridFx2,\n gridFy: () => gridFy2,\n gridX: () => gridX2,\n gridY: () => gridY2,\n heatmap: () => heatmap,\n hexagon: () => hexagon2,\n hexbin: () => hexbin2,\n hexgrid: () => hexgrid2,\n hull: () => hull2,\n image: () => image2,\n line: () => line2,\n lineX: () => lineX2,\n lineY: () => lineY2,\n link: () => link3,\n raster: () => raster2,\n rasterTile: () => rasterTile,\n rect: () => rect2,\n rectX: () => rectX2,\n rectY: () => rectY2,\n regressionY: () => regressionY,\n ruleX: () => ruleX2,\n ruleY: () => ruleY2,\n sphere: () => sphere2,\n spike: () => spike2,\n text: () => text2,\n textX: () => textX2,\n textY: () => textY2,\n tickX: () => tickX2,\n tickY: () => tickY2,\n vector: () => vector2,\n vectorX: () => vectorX2,\n vectorY: () => vectorY2,\n voronoi: () => voronoi2,\n voronoiMesh: () => voronoiMesh2\n});\nvar decorators = /* @__PURE__ */ new Set([\n \"frame\",\n \"axisX\",\n \"axisY\",\n \"axisFx\",\n \"axisFy\",\n \"gridX\",\n \"gridY\",\n \"gridFx\",\n \"gridFy\",\n \"hexgrid\",\n \"graticule\",\n \"sphere\"\n]);\nfunction mark(type2, data, channels = {}) {\n if (arguments.length === 2 && !Array.isArray(data)) {\n channels = data;\n data = decorators.has(type2) ? null : [{}];\n }\n const MarkClass = type2.startsWith(\"area\") || type2.startsWith(\"line\") ? ConnectedMark : Mark2;\n return explicitType(MarkClass, type2, data, channels);\n}\nfunction explicitType(MarkClass, type2, data, channels) {\n return (plot3) => {\n plot3.addMark(new MarkClass(type2, data, channels));\n };\n}\nfunction implicitType(MarkClass, data, channels) {\n return (plot3) => {\n plot3.addMark(new MarkClass(data, channels));\n };\n}\nvar area2 = (...args) => mark(\"area\", ...args);\nvar areaX2 = (...args) => mark(\"areaX\", ...args);\nvar areaY2 = (...args) => mark(\"areaY\", ...args);\nvar line2 = (...args) => mark(\"line\", ...args);\nvar lineX2 = (...args) => mark(\"lineX\", ...args);\nvar lineY2 = (...args) => mark(\"lineY\", ...args);\nvar barX2 = (...args) => mark(\"barX\", ...args);\nvar barY2 = (...args) => mark(\"barY\", ...args);\nvar cell2 = (...args) => mark(\"cell\", ...args);\nvar cellX2 = (...args) => mark(\"cellX\", ...args);\nvar cellY2 = (...args) => mark(\"cellY\", ...args);\nvar rect2 = (...args) => mark(\"rect\", ...args);\nvar rectX2 = (...args) => mark(\"rectX\", ...args);\nvar rectY2 = (...args) => mark(\"rectY\", ...args);\nvar dot2 = (...args) => mark(\"dot\", ...args);\nvar dotX2 = (...args) => mark(\"dotX\", ...args);\nvar dotY2 = (...args) => mark(\"dotY\", ...args);\nvar circle2 = (...args) => mark(\"circle\", ...args);\nvar hexagon2 = (...args) => mark(\"hexagon\", ...args);\nvar text2 = (...args) => mark(\"text\", ...args);\nvar textX2 = (...args) => mark(\"textX\", ...args);\nvar textY2 = (...args) => mark(\"textY\", ...args);\nvar ruleX2 = (...args) => mark(\"ruleX\", ...args);\nvar ruleY2 = (...args) => mark(\"ruleY\", ...args);\nvar tickX2 = (...args) => mark(\"tickX\", ...args);\nvar tickY2 = (...args) => mark(\"tickY\", ...args);\nvar vector2 = (...args) => mark(\"vector\", ...args);\nvar vectorX2 = (...args) => mark(\"vectoX\", ...args);\nvar vectorY2 = (...args) => mark(\"vectorY\", ...args);\nvar spike2 = (...args) => mark(\"spike\", ...args);\nvar image2 = (...args) => mark(\"image\", ...args);\nvar densityX = (...args) => explicitType(Density1DMark, \"areaX\", ...args);\nvar densityY = (...args) => explicitType(Density1DMark, \"areaY\", ...args);\nvar density2 = (...args) => implicitType(Density2DMark, ...args);\nvar denseLine = (...args) => implicitType(DenseLineMark, ...args);\nvar contour2 = (...args) => implicitType(ContourMark, ...args);\nvar heatmap = (...args) => implicitType(HeatmapMark, ...args);\nvar raster2 = (...args) => implicitType(RasterMark, ...args);\nvar rasterTile = (...args) => implicitType(RasterTileMark, ...args);\nvar hexbin2 = (...args) => implicitType(HexbinMark, ...args);\nvar hexgrid2 = (...args) => mark(\"hexgrid\", ...args);\nvar regressionY = (...args) => implicitType(RegressionMark, ...args);\nvar errorbarX = (...args) => explicitType(ErrorBarMark, \"ruleY\", ...args);\nvar errorbarY = (...args) => implicitType(ErrorBarMark, \"ruleX\", ...args);\nvar voronoi2 = (...args) => mark(\"voronoi\", ...args);\nvar voronoiMesh2 = (...args) => mark(\"voronoiMesh\", ...args);\nvar delaunayLink2 = (...args) => mark(\"delaunayLink\", ...args);\nvar delaunayMesh2 = (...args) => mark(\"delaunayMesh\", ...args);\nvar hull2 = (...args) => mark(\"hull\", ...args);\nvar arrow2 = (...args) => mark(\"arrow\", ...args);\nvar link3 = (...args) => mark(\"link\", ...args);\nvar frame3 = (...args) => mark(\"frame\", ...args);\nvar axisX2 = (...args) => mark(\"axisX\", ...args);\nvar axisY2 = (...args) => mark(\"axisY\", ...args);\nvar axisFx2 = (...args) => mark(\"axisFx\", ...args);\nvar axisFy2 = (...args) => mark(\"axisFy\", ...args);\nvar gridX2 = (...args) => mark(\"gridX\", ...args);\nvar gridY2 = (...args) => mark(\"gridY\", ...args);\nvar gridFx2 = (...args) => mark(\"gridFx\", ...args);\nvar gridFy2 = (...args) => mark(\"gridFy\", ...args);\nvar geo2 = (...args) => implicitType(GeoMark, ...args);\nvar sphere2 = (...args) => mark(\"sphere\", ...args);\nvar graticule3 = (...args) => mark(\"graticule\", ...args);\n\n// ../vgplot/src/plot/interactors.js\nvar interactors_exports = {};\n__export(interactors_exports, {\n highlight: () => highlight,\n intervalX: () => intervalX,\n intervalXY: () => intervalXY,\n intervalY: () => intervalY,\n nearest: () => nearest,\n nearestX: () => nearestX,\n nearestY: () => nearestY,\n pan: () => pan,\n panX: () => panX,\n panY: () => panY,\n panZoom: () => panZoom,\n panZoomX: () => panZoomX,\n panZoomY: () => panZoomY,\n toggle: () => toggle,\n toggleColor: () => toggleColor,\n toggleX: () => toggleX,\n toggleY: () => toggleY,\n toggleZ: () => toggleZ\n});\nfunction interactor(InteractorClass, options) {\n return (plot3) => {\n const mark2 = plot3.marks[plot3.marks.length - 1];\n plot3.addInteractor(new InteractorClass(mark2, options));\n };\n}\nfunction highlight({ by, ...channels }) {\n return interactor(Highlight, { selection: by, channels });\n}\nfunction toggle({ as, ...rest }) {\n return interactor(Toggle, { ...rest, selection: as });\n}\nfunction toggleX(options) {\n return toggle({ ...options, channels: [\"x\"] });\n}\nfunction toggleY(options) {\n return toggle({ ...options, channels: [\"y\"] });\n}\nfunction toggleZ(options) {\n return toggle({ ...options, channels: [\"z\"] });\n}\nfunction toggleColor(options) {\n return toggle({ ...options, channels: [\"color\"] });\n}\nfunction nearest({ as, ...rest }) {\n return interactor(Nearest, { ...rest, selection: as, pointer: \"xy\" });\n}\nfunction nearestX({ as, ...rest }) {\n return interactor(Nearest, { ...rest, selection: as, pointer: \"x\" });\n}\nfunction nearestY({ as, ...rest }) {\n return interactor(Nearest, { ...rest, selection: as, pointer: \"y\" });\n}\nfunction intervalX({ as, ...rest }) {\n return interactor(Interval1D, { ...rest, selection: as, channel: \"x\" });\n}\nfunction intervalY({ as, ...rest }) {\n return interactor(Interval1D, { ...rest, selection: as, channel: \"y\" });\n}\nfunction intervalXY({ as, ...rest }) {\n return interactor(Interval2D, { ...rest, selection: as });\n}\nfunction zoom(options) {\n return interactor(PanZoom, options);\n}\nfunction pan(options = {}) {\n return zoom({ ...options, zoom: false });\n}\nfunction panX(options = {}) {\n return zoom({ ...options, zoom: false, pany: false });\n}\nfunction panY(options = {}) {\n return zoom({ ...options, zoom: false, panx: false });\n}\nfunction panZoom(options = {}) {\n return zoom(options);\n}\nfunction panZoomX(options = {}) {\n return zoom({ ...options, pany: false });\n}\nfunction panZoomY(options = {}) {\n return zoom({ ...options, panx: false });\n}\n\n// ../vgplot/src/plot/legends.js\nvar legends_exports = {};\n__export(legends_exports, {\n colorLegend: () => colorLegend,\n opacityLegend: () => opacityLegend,\n symbolLegend: () => symbolLegend\n});\nfunction legend2(channel, options = {}) {\n if (options.for) {\n const { for: maybePlot, ...rest } = options;\n const legend3 = new Legend(channel, rest);\n const type2 = typeof maybePlot;\n const add2 = (plot3) => plot3.addLegend(legend3, false);\n if (type2 === \"string\") {\n requestNamedPlot(this, maybePlot, add2);\n } else if (maybePlot.value) {\n add2(maybePlot.value);\n }\n return legend3.element;\n } else {\n return (plot3) => plot3.addLegend(new Legend(channel, options));\n }\n}\nfunction colorLegend(options) {\n return legend2.call(this, \"color\", options);\n}\nfunction opacityLegend(options) {\n return legend2.call(this, \"opacity\", options);\n}\nfunction symbolLegend(options) {\n return legend2.call(this, \"symbol\", options);\n}\n\n// ../vgplot/src/plot/plot.js\nfunction plot2(...directives) {\n const p = new Plot();\n directives.flat().forEach((dir) => dir(p));\n connect(this, ...p.marks);\n p.update();\n return p.element;\n}\n\n// ../vgplot/src/context.js\nfunction createAPIContext({\n coordinator: coordinator2 = coordinator(),\n namedPlots: namedPlots2 = new NamedPlots(),\n extensions = null,\n ...options\n} = {}) {\n return {\n ...api_exports,\n ...extensions,\n context: {\n coordinator: coordinator2,\n namedPlots: namedPlots2,\n ...options\n }\n };\n}\n\n// ../spec/src/constants.js\nvar SPEC = \"spec\";\nvar LITERAL = \"literal\";\nvar OPTIONS = \"options\";\nvar SELECTION = \"selection\";\nvar PARAMREF = \"paramref\";\nvar PARAM = \"param\";\nvar INCLUDE = \"include\";\nvar SELECT = \"select\";\nvar VALUE = \"value\";\nvar CROSSFILTER = \"crossfilter\";\nvar INTERSECT = \"intersect\";\nvar UNION = \"union\";\nvar SINGLE = \"single\";\nvar DATA = \"data\";\nvar EXPRESSION = \"expression\";\nvar SQL = \"sql\";\nvar AGG = \"agg\";\nvar INPUT = \"input\";\nvar HCONCAT = \"hconcat\";\nvar VCONCAT = \"vconcat\";\nvar HSPACE = \"hspace\";\nvar VSPACE = \"vspace\";\nvar MARK = \"mark\";\nvar FROM = \"from\";\nvar PLOT = \"plot\";\nvar LEGEND = \"legend\";\nvar ATTRIBUTE = \"attribute\";\nvar TRANSFORM = \"transform\";\nvar INTERACTOR = \"interactor\";\nvar FIXED = \"Fixed\";\n\n// ../spec/src/ast/ASTNode.js\nvar ASTNode = class {\n constructor(type2, children2 = null) {\n this.type = type2;\n this.children = children2;\n }\n /**\n * Instantiate this AST node to use in a live web application.\n * @param {import('../ast-to-dom.js').InstantiateContext} ctx The instantiation context.\n * @returns {*} The instantiated value of this node.\n */\n instantiate(ctx) {\n throw Error(\"instantiate not implemented\");\n }\n /**\n * Generate ESM code for this AST node.\n * @param {import('../ast-to-esm.js').CodegenContext} ctx The code generator context.\n * @returns {string|void} The generated ESM code for the node.\n */\n codegen(ctx) {\n return Error(\"codegen not implemented\");\n }\n /**\n * @returns {*} This AST node in JSON specification format.\n */\n toJSON() {\n return Error(\"toJSON not implemented\");\n }\n};\n\n// ../spec/src/ast/SpecNode.js\nvar SpecNode = class extends ASTNode {\n constructor(root2, meta, config, data, params, plotDefaults) {\n super(SPEC, [root2]);\n this.root = root2;\n this.meta = meta;\n this.config = config;\n this.data = data;\n this.params = params;\n this.plotDefaults = plotDefaults;\n }\n toJSON() {\n const { root: root2, meta, config, plotDefaults } = this;\n const dataDefs = new Map(Object.entries(this.data));\n const paramDefs = new Map(Object.entries(this.params));\n const spec = {};\n if (meta) spec.meta = { ...meta };\n if (config) spec.config = { ...config };\n if (dataDefs?.size) {\n const data = spec.data = {};\n for (const [name2, node] of dataDefs) {\n data[name2] = node.toJSON();\n }\n }\n if (paramDefs?.size) {\n const params = spec.params = {};\n for (const [name2, node] of paramDefs) {\n params[name2] = node.toJSON();\n }\n }\n if (plotDefaults?.length) {\n const defaults22 = spec.plotDefaults = {};\n for (const node of plotDefaults) {\n Object.assign(defaults22, node.toJSON());\n }\n }\n return Object.assign(spec, root2.toJSON());\n }\n};\n\n// ../spec/src/util.js\nfunction paramRef(value) {\n const type2 = typeof value;\n return type2 === \"object\" ? value?.param : type2 === \"string\" ? paramStr(value) : null;\n}\nfunction paramStr(value) {\n return value?.[0] === \"$\" ? value.slice(1) : null;\n}\nfunction toParamRef(name2) {\n return `$${name2}`;\n}\nfunction toArray(value) {\n return [value].flat();\n}\nfunction isArray3(value) {\n return Array.isArray(value);\n}\nfunction isObject3(value) {\n return value !== null && typeof value === \"object\" && !isArray3(value);\n}\nfunction isString(value) {\n return typeof value === \"string\";\n}\nfunction error(message, data) {\n throw Object.assign(Error(message), { data });\n}\nvar re3 = /^(?:[-+]\\d{2})?\\d{4}(?:-\\d{2}(?:-\\d{2})?)?(?:T\\d{2}:\\d{2}(?::\\d{2}(?:\\.\\d{3})?)?(?:Z|[-+]\\d{2}:?\\d{2})?)?$/;\nfunction isoparse(string2, fallback) {\n if (!re3.test(string2 += \"\")) return fallback;\n return new Date(string2);\n}\n\n// ../spec/src/ast/OptionsNode.js\nfunction parseOptions(spec, ctx) {\n const options = {};\n for (const key in spec) {\n options[key] = ctx.maybeSelection(spec[key]);\n }\n return new OptionsNode(options);\n}\nvar OptionsNode = class _OptionsNode extends ASTNode {\n constructor(options) {\n super(OPTIONS);\n this.options = options;\n }\n filter(predicate) {\n const opt = Object.fromEntries(\n Object.entries(this.options).filter(([key, value]) => predicate(key, value))\n );\n return new _OptionsNode(opt);\n }\n instantiate(ctx) {\n const { options } = this;\n const opt = {};\n for (const key in options) {\n opt[key] = options[key].instantiate(ctx);\n }\n return opt;\n }\n codegen(ctx) {\n const { options } = this;\n const opt = [];\n for (const key in options) {\n opt.push(`${key}: ${options[key].codegen(ctx)}`);\n }\n return opt.length ? `{${ctx.maybeLineWrap(opt)}}` : \"\";\n }\n toJSON() {\n const { options } = this;\n const opt = {};\n for (const key in options) {\n opt[key] = options[key].toJSON();\n }\n return opt;\n }\n};\n\n// ../spec/src/ast/DataNode.js\nvar TABLE_DATA = \"table\";\nvar PARQUET_DATA = \"parquet\";\nvar CSV_DATA = \"csv\";\nvar JSON_DATA = \"json\";\nvar SPATIAL_DATA = \"spatial\";\nvar dataFormats = /* @__PURE__ */ new Map([\n [TABLE_DATA, parseTableData],\n [PARQUET_DATA, parseParquetData],\n [CSV_DATA, parseCSVData],\n [JSON_DATA, parseJSONData],\n [SPATIAL_DATA, parseSpatialData]\n]);\nfunction parseData(name2, spec, ctx) {\n const def = resolveDataSpec(spec);\n if (dataFormats.has(def.type)) {\n const parse2 = dataFormats.get(def.type);\n return parse2(name2, def, ctx);\n } else {\n ctx.error(`Unrecognized data format type.`, spec);\n }\n}\nfunction resolveDataSpec(spec) {\n if (isArray3(spec)) spec = { type: \"json\", data: spec };\n if (isString(spec)) spec = { type: \"table\", query: spec };\n return { ...spec, type: inferType2(spec) };\n}\nfunction inferType2(spec) {\n return spec.type || fileExtension(spec.file) || \"table\";\n}\nfunction fileExtension(file) {\n const idx = file?.lastIndexOf(\".\");\n return idx > 0 ? file.slice(idx + 1) : null;\n}\nfunction parseTableData(name2, spec, ctx) {\n const { query, type: type2, ...options } = spec;\n return new TableDataNode(name2, query, parseOptions(options, ctx));\n}\nfunction parseParquetData(name2, spec, ctx) {\n const { file, type: type2, ...options } = spec;\n return new ParquetDataNode(name2, file, parseOptions(options, ctx));\n}\nfunction parseCSVData(name2, spec, ctx) {\n const { file, type: type2, ...options } = spec;\n return new CSVDataNode(name2, file, parseOptions(options, ctx));\n}\nfunction parseJSONData(name2, spec, ctx) {\n const { data, file, type: type2, ...options } = spec;\n const opt = parseOptions(options, ctx);\n return data ? new LiteralJSONDataNode(name2, data, opt) : new JSONDataNode(name2, file, opt);\n}\nfunction parseSpatialData(name2, spec, ctx) {\n const { file, type: type2, ...options } = spec;\n return new SpatialDataNode(name2, file, parseOptions(options, ctx));\n}\nfunction resolveFileURL(file, baseURL) {\n return baseURL ? new URL(file, baseURL).toString() : file;\n}\nfunction codegenOptions(options, ctx) {\n const code = options?.codegen(ctx);\n return code ? `, ${code}` : \"\";\n}\nvar DataNode = class extends ASTNode {\n constructor(name2, format3) {\n super(DATA);\n this.name = name2;\n this.format = format3;\n }\n};\nvar QueryDataNode = class extends DataNode {\n constructor(name2, format3) {\n super(name2, format3);\n }\n /**\n * Instantiate a table creation query.\n * @param {import('../ast-to-dom.js').InstantiateContext} ctx The instantiation context.\n * @returns {string|void} The instantiated query.\n */\n instantiateQuery(ctx) {\n ctx.error(\"instantiateQuery not implemented\");\n }\n /**\n * Code generate a table creation query.\n * @param {import('../ast-to-esm.js').CodegenContext} ctx The code generator context.\n * @returns {string|void} The generated query code.\n */\n codegenQuery(ctx) {\n ctx.error(\"codegenQuery not implemented\");\n }\n /**\n * Instantiate this AST node to use in a live web application.\n * @param {import('../ast-to-dom.js').InstantiateContext} ctx The instantiation context.\n * @returns {*} The instantiated value of this node.\n */\n instantiate(ctx) {\n const query = this.instantiateQuery(ctx);\n if (query) return query;\n }\n /**\n * Generate ESM code for this AST node.\n * @param {import('../ast-to-esm.js').CodegenContext} ctx The code generator context.\n * @returns {string|void} The generated ESM code for the node.\n */\n codegen(ctx) {\n const query = this.codegenQuery(ctx);\n if (query) return query;\n }\n};\nvar TableDataNode = class extends QueryDataNode {\n constructor(name2, query, options) {\n super(name2, TABLE_DATA);\n this.query = query?.trim();\n this.options = options;\n }\n /**\n * Instantiate a table creation query.\n * @param {import('../ast-to-dom.js').InstantiateContext} ctx The instantiation context.\n * @returns {string|void} The instantiated query.\n */\n instantiateQuery(ctx) {\n const { name: name2, query, options } = this;\n if (query) {\n return ctx.api.create(name2, query, options.instantiate(ctx));\n }\n }\n /**\n * Code generate a table creation query.\n * @param {import('../ast-to-esm.js').CodegenContext} ctx The code generator context.\n * @returns {string|void} The generated query code.\n */\n codegenQuery(ctx) {\n const { name: name2, query, options } = this;\n if (query) {\n return `\\`${create(name2, query, options.instantiate(ctx))}\\``;\n }\n }\n toJSON() {\n const { format: format3, query, options } = this;\n return { type: format3, query, ...options.toJSON() };\n }\n};\nvar FileDataNode = class extends QueryDataNode {\n constructor(name2, format3, method, file, options) {\n super(name2, format3);\n this.file = file;\n this.method = method;\n this.options = options;\n }\n /**\n * Instantiate a table creation query.\n * @param {import('../ast-to-dom.js').InstantiateContext} ctx The instantiation context.\n * @returns {string|void} The instantiated query.\n */\n instantiateQuery(ctx) {\n const { name: name2, method, file, options } = this;\n const url = resolveFileURL(file, ctx.baseURL);\n const opt = options?.instantiate(ctx);\n return ctx.api[method](name2, url, opt);\n }\n /**\n * Code generate a table creation query.\n * @param {import('../ast-to-esm.js').CodegenContext} ctx The code generator context.\n * @returns {string|void} The generated query code.\n */\n codegenQuery(ctx) {\n const { name: name2, method, file, options } = this;\n const url = resolveFileURL(file, ctx.baseURL);\n const opt = codegenOptions(options, ctx);\n return `${ctx.ns()}${method}(\"${name2}\", \"${url}\"${opt})`;\n }\n toJSON() {\n const { format: format3, file, options } = this;\n return { type: format3, file, ...options.toJSON() };\n }\n};\nvar SpatialDataNode = class extends FileDataNode {\n constructor(name2, file, options) {\n super(name2, SPATIAL_DATA, \"loadSpatial\", file, options);\n }\n};\nvar ParquetDataNode = class extends FileDataNode {\n constructor(name2, file, options) {\n super(name2, PARQUET_DATA, \"loadParquet\", file, options);\n }\n};\nvar CSVDataNode = class extends FileDataNode {\n constructor(name2, file, options) {\n super(name2, CSV_DATA, \"loadCSV\", file, options);\n }\n};\nvar JSONDataNode = class extends FileDataNode {\n constructor(name2, file, options) {\n super(name2, JSON_DATA, \"loadJSON\", file, options);\n }\n};\nvar LiteralJSONDataNode = class extends QueryDataNode {\n constructor(name2, data, options) {\n super(name2, JSON_DATA);\n this.data = data;\n this.options = options;\n }\n /**\n * Instantiate a table creation query.\n * @param {import('../ast-to-dom.js').InstantiateContext} ctx The instantiation context.\n * @returns {string|void} The instantiated query.\n */\n instantiateQuery(ctx) {\n const { name: name2, data, options } = this;\n return ctx.api.loadObjects(name2, data, options.instantiate(ctx));\n }\n /**\n * Code generate a table creation query.\n * @param {import('../ast-to-esm.js').CodegenContext} ctx The code generator context.\n * @returns {string|void} The generated query code.\n */\n codegenQuery(ctx) {\n const { name: name2, data, options } = this;\n const opt = options ? \",\" + options.codegen(ctx) : \"\";\n const d = \"[\\n \" + data.map((d2) => JSON.stringify(d2)).join(\",\\n \") + \"\\n ]\";\n return `${ctx.ns()}loadObjects(\"${name2}\", ${d}${opt})`;\n }\n toJSON() {\n const { format: format3, data, options } = this;\n return { type: format3, data, ...options.toJSON() };\n }\n};\n\n// ../spec/src/config/extensions.js\nfunction resolveExtensions(ast) {\n const spec = ast.config?.extensions;\n const exts = new Set(spec ? toArray(spec) : []);\n for (const def of Object.values(ast.data)) {\n if (def.format === SPATIAL_DATA) {\n exts.add(\"spatial\");\n }\n }\n return exts;\n}\n\n// ../spec/src/ast-to-dom.js\nasync function astToDOM(ast, options) {\n const { data, params, plotDefaults } = ast;\n const ctx = new InstantiateContext({ plotDefaults, ...options });\n const queries = [];\n const exts = resolveExtensions(ast);\n queries.push(...Array.from(exts).map((name2) => loadExtension(name2)));\n for (const node of Object.values(data)) {\n const query = node.instantiate(ctx);\n if (query) queries.push(query);\n }\n if (queries.length > 0) {\n await ctx.coordinator.exec(queries);\n }\n for (const [name2, node] of Object.entries(params)) {\n if (!ctx.activeParams.has(name2)) {\n const param = node.instantiate(ctx);\n ctx.activeParams.set(name2, param);\n }\n }\n return {\n element: ast.root.instantiate(ctx),\n params: ctx.activeParams\n };\n}\nvar InstantiateContext = class {\n constructor({\n api = createAPIContext(),\n plotDefaults = [],\n params = /* @__PURE__ */ new Map(),\n baseURL = null\n } = {}) {\n this.api = api;\n this.plotDefaults = plotDefaults;\n this.activeParams = params;\n this.baseURL = baseURL;\n this.coordinator = api.context.coordinator;\n }\n error(message, data) {\n error(message, data);\n }\n};\n\n// ../spec/src/ast/LiteralNode.js\nvar LiteralNode = class extends ASTNode {\n constructor(value) {\n super(LITERAL);\n this.value = value;\n }\n instantiate() {\n return this.value;\n }\n codegen(ctx) {\n return ctx.stringify(this.value);\n }\n toJSON() {\n return this.value;\n }\n};\n\n// ../spec/src/ast/SelectionNode.js\nfunction parseSelection(spec, ctx) {\n const { select: select2, include, ...options } = spec;\n const opt = parseOptions(options, ctx);\n if (include) {\n opt.options.include = new IncludeNode(\n toArray(include).map((ref) => ctx.selectionRef(paramRef(ref)))\n );\n }\n return new SelectionNode(select2, opt);\n}\nvar SelectionNode = class extends ASTNode {\n /**\n * Create a Selection AST node.\n * @param {string} select The selection type.\n * @param {OptionsNode} options Selection options.\n */\n constructor(select2 = INTERSECT, options = new OptionsNode({})) {\n super(SELECTION);\n this.select = select2;\n this.options = options;\n }\n instantiate(ctx) {\n const { select: select2, options } = this;\n return ctx.api.Selection[select2](options.instantiate(ctx));\n }\n codegen(ctx) {\n const { select: select2, options } = this;\n return `${ctx.ns()}Selection.${select2}(${options.codegen(ctx)})`;\n }\n toJSON() {\n const { select: select2, options } = this;\n return { select: select2, ...options.toJSON() };\n }\n};\nvar IncludeNode = class extends ASTNode {\n constructor(refs) {\n super(INCLUDE);\n this.refs = refs;\n }\n instantiate(ctx) {\n return this.refs.map((ref) => ref.instantiate(ctx));\n }\n codegen(ctx) {\n return `[${this.refs.map((ref) => ref.codegen(ctx)).join(\", \")}]`;\n }\n toJSON() {\n return this.refs.map((ref) => ref.toJSON());\n }\n};\n\n// ../spec/src/ast/ParamNode.js\nvar paramTypes = /* @__PURE__ */ new Set([VALUE, SINGLE, CROSSFILTER, INTERSECT, UNION]);\nfunction parseParam(spec, ctx) {\n const param = isObject3(spec) ? spec : { value: spec };\n const { select: select2 = VALUE, value, date: date3 } = param;\n if (!paramTypes.has(select2)) {\n ctx.error(`Unrecognized param type: ${select2}`, param);\n }\n if (select2 !== VALUE) {\n return parseSelection(spec, ctx);\n } else if (isArray3(value)) {\n return new ParamNode(value.map((v2) => ctx.maybeParam(v2)));\n } else {\n return new ParamNode(value, date3);\n }\n}\nvar ParamNode = class extends ASTNode {\n constructor(value, date3) {\n super(PARAM);\n this.value = value;\n this.date = date3;\n }\n instantiate(ctx) {\n const { date: date3, value } = this;\n const { Param: Param2 } = ctx.api;\n return isArray3(value) ? Param2.array(value.map((v2) => v2.instantiate(ctx))) : Param2.value(isoparse(date3, value));\n }\n codegen(ctx) {\n const { value, date: date3 } = this;\n const prefix2 = `${ctx.ns()}Param.`;\n return isArray3(value) ? `${prefix2}array([${value.map((v2) => v2.codegen(ctx)).join(\", \")}])` : date3 ? `${prefix2}value(new Date(${JSON.stringify(date3)}))` : `${prefix2}value(${JSON.stringify(value)})`;\n }\n toJSON() {\n const { date: date3, value } = this;\n return isArray3(value) ? value.map((v2) => v2.toJSON()) : date3 ? { date: date3 } : value;\n }\n};\n\n// ../spec/src/ast/ParamRefNode.js\nvar ParamRefNode = class extends ASTNode {\n constructor(name2) {\n super(PARAMREF);\n this.name = name2;\n }\n instantiate(ctx) {\n return ctx.activeParams?.get(this.name);\n }\n codegen(ctx) {\n return toParamRef(this.name);\n }\n toJSON() {\n return toParamRef(this.name);\n }\n};\n\n// ../spec/src/ast/PlotAttributeNode.js\nfunction parseAttribute(key, value, ctx) {\n if (!ctx.plot?.attributes?.has(key)) {\n ctx.error(`Unrecognized attribute: ${key}`);\n }\n return new PlotAttributeNode(\n key,\n value === FIXED ? new PlotFixedNode() : ctx.maybeParam(value)\n );\n}\nvar PlotAttributeNode = class extends ASTNode {\n constructor(name2, value) {\n super(ATTRIBUTE);\n this.name = name2;\n this.value = value;\n }\n instantiate(ctx) {\n const { name: name2, value } = this;\n return ctx.api[name2](value.instantiate(ctx));\n }\n codegen(ctx) {\n const { name: name2, value } = this;\n return `${ctx.tab()}${ctx.ns()}${name2}(${value.codegen(ctx)})`;\n }\n toJSON() {\n const { name: name2, value } = this;\n return { [name2]: value.toJSON() };\n }\n};\nvar PlotFixedNode = class extends ASTNode {\n constructor() {\n super(LITERAL);\n this.value = FIXED;\n }\n instantiate(ctx) {\n return ctx.api[FIXED];\n }\n codegen(ctx) {\n return `${ctx.ns()}${FIXED}`;\n }\n toJSON() {\n return this.value;\n }\n};\n\n// ../spec/src/ast/HConcatNode.js\nfunction parseHConcat(spec, ctx) {\n const children2 = spec[HCONCAT].map((s2) => ctx.parseComponent(s2));\n return new HConcatNode(children2);\n}\nvar HConcatNode = class extends ASTNode {\n constructor(children2) {\n super(HCONCAT, children2);\n }\n instantiate(ctx) {\n return ctx.api[HCONCAT](this.children.map((c4) => c4.instantiate(ctx)));\n }\n codegen(ctx) {\n ctx.indent();\n const items = this.children.map((c4) => c4.codegen(ctx));\n ctx.undent();\n return `${ctx.tab()}${ctx.ns()}${this.type}(\n${items.join(\",\\n\")}\n${ctx.tab()})`;\n }\n toJSON() {\n return { [this.type]: this.children.map((c4) => c4.toJSON()) };\n }\n};\n\n// ../spec/src/ast/HSpaceNode.js\nfunction parseHSpace(spec) {\n return new HSpaceNode(spec[HSPACE]);\n}\nvar HSpaceNode = class extends ASTNode {\n constructor(value) {\n super(HSPACE);\n this.value = value;\n }\n instantiate(ctx) {\n return ctx.api[HSPACE](this.value);\n }\n codegen(ctx) {\n return `${ctx.tab()}${ctx.ns()}${this.type}(${ctx.stringify(this.value)})`;\n }\n toJSON() {\n return { [this.type]: this.value };\n }\n};\n\n// ../spec/src/ast/InputNode.js\nfunction parseInput(spec, ctx) {\n const { [INPUT]: name2, ...options } = spec;\n if (!ctx.inputs?.has(name2)) {\n ctx.error(`Unrecognized input type: ${name2}`, spec);\n }\n return new InputNode(name2, parseOptions(options, ctx));\n}\nvar InputNode = class extends ASTNode {\n constructor(name2, options) {\n super(INPUT);\n this.name = name2;\n this.options = options;\n }\n instantiate(ctx) {\n return ctx.api[this.name](this.options.instantiate(ctx));\n }\n codegen(ctx) {\n const opt = this.options.codegen(ctx);\n return `${ctx.tab()}${ctx.ns()}${this.name}(${opt})`;\n }\n toJSON() {\n const { type: type2, name: name2, options } = this;\n return { [type2]: name2, ...options.toJSON() };\n }\n};\n\n// ../spec/src/ast/PlotLegendNode.js\nfunction parseLegend(spec, ctx) {\n const { [LEGEND]: name2, ...options } = spec;\n const key = `${name2}Legend`;\n if (!ctx.plot?.legends?.has(key)) {\n ctx.error(`Unrecognized legend type: ${name2}`, spec);\n }\n return new PlotLegendNode(key, name2, parseOptions(options, ctx));\n}\nvar PlotLegendNode = class extends ASTNode {\n constructor(key, name2, options) {\n super(LEGEND);\n this.key = key;\n this.name = name2;\n this.options = options;\n }\n instantiate(ctx) {\n return ctx.api[this.key](this.options.instantiate(ctx));\n }\n codegen(ctx) {\n const opt = this.options.codegen(ctx);\n return `${ctx.tab()}${ctx.ns()}${this.key}(${opt})`;\n }\n toJSON() {\n const { type: type2, name: name2, options } = this;\n return { [type2]: name2, ...options.toJSON() };\n }\n};\n\n// ../spec/src/ast/PlotInteractorNode.js\nfunction parseInteractor(spec, ctx) {\n const { [SELECT]: name2, ...options } = spec;\n if (!ctx.plot?.interactors?.has(name2)) {\n ctx.error(`Unrecognized interactor type: ${name2}`, spec);\n }\n return new PlotInteractorNode(name2, parseOptions(options, ctx));\n}\nvar PlotInteractorNode = class extends ASTNode {\n constructor(name2, options) {\n super(INTERACTOR);\n this.name = name2;\n this.options = options;\n }\n instantiate(ctx) {\n return ctx.api[this.name](this.options.instantiate(ctx));\n }\n codegen(ctx) {\n const opt = this.options.codegen(ctx);\n return `${ctx.tab()}${ctx.ns()}${this.name}(${opt})`;\n }\n toJSON() {\n const { name: name2, options } = this;\n return { [SELECT]: name2, ...options.toJSON() };\n }\n};\n\n// ../spec/src/ast/ExpressionNode.js\nfunction parseExpression(spec, ctx) {\n const { label: label2 } = spec;\n const key = spec[SQL] ? SQL : spec[AGG] ? AGG : ctx.error(\"Unrecognized expression type\", spec);\n const expr = spec[key];\n const tokens = expr.split(/(\\\\'|\\\\\"|\"(?:\\\\\"|[^\"])*\"|'(?:\\\\'|[^'])*'|\\$\\w+)/g);\n const spans = [\"\"];\n const params = [];\n for (let i = 0, k2 = 0; i < tokens.length; ++i) {\n const tok = tokens[i];\n if (tok.startsWith(\"$\")) {\n params[k2] = ctx.maybeParam(tok);\n spans[++k2] = \"\";\n } else {\n spans[k2] += tok;\n }\n }\n return new ExpressionNode(expr, spans, params, label2, key === AGG);\n}\nvar ExpressionNode = class extends ASTNode {\n constructor(value, spans, params, label2, aggregate) {\n super(EXPRESSION);\n this.value = value;\n this.spans = spans;\n this.params = params;\n this.label = label2;\n this.aggregate = aggregate;\n }\n instantiate(ctx) {\n const { spans, params, label: label2, aggregate } = this;\n const tag = ctx.api[aggregate ? AGG : SQL];\n const args = params.map((e) => e.instantiate(ctx));\n return tag(spans, ...args).annotate({ label: label2 });\n }\n codegen(ctx) {\n const { spans, params, label: label2, aggregate } = this;\n const method = aggregate ? AGG : SQL;\n let str = \"\";\n const n = params.length;\n for (let i = 0; i < n; ++i) {\n str += spans[i] + \"${\" + params[i].codegen(ctx) + \"}\";\n }\n str += spans[n];\n return `${ctx.ns()}${method}\\`${str}\\`` + (label2 ? `.annotate({ label: ${JSON.stringify(label2)} })` : \"\");\n }\n toJSON() {\n const key = this.aggregate ? AGG : SQL;\n return { [key]: this.value };\n }\n};\n\n// ../spec/src/ast/PlotFromNode.js\nfunction parseMarkData(spec, ctx) {\n if (!spec) {\n return null;\n }\n if (isArray3(spec)) {\n return new LiteralNode(spec);\n }\n const { from: table3, ...options } = spec;\n return new PlotFromNode(table3, parseOptions(options, ctx));\n}\nvar PlotFromNode = class extends ASTNode {\n constructor(table3, options) {\n super(FROM);\n this.table = table3;\n this.options = options;\n }\n instantiate(ctx) {\n const { table: table3, options } = this;\n return ctx.api[FROM](table3, options.instantiate(ctx));\n }\n codegen(ctx) {\n const { type: type2, table: table3, options } = this;\n const opt = options.codegen(ctx);\n return `${ctx.ns()}${type2}(\"${table3}\"${opt ? \", \" + opt : \"\"})`;\n }\n toJSON() {\n const { type: type2, table: table3, options } = this;\n return { [type2]: table3, ...options.toJSON() };\n }\n};\n\n// ../spec/src/ast/TransformNode.js\nfunction toArray2(value) {\n return value == null ? [] : [value].flat();\n}\nfunction parseTransform(spec, ctx) {\n let name2;\n for (const key in spec) {\n if (ctx.transforms.has(key)) {\n name2 = key;\n }\n }\n if (!name2) {\n return;\n }\n if (name2 === \"bin\") {\n const { bin: bin3, ...options } = spec;\n const [arg] = toArray2(bin3);\n return new BinTransformNode(name2, arg, parseOptions(options, ctx));\n } else {\n const args = name2 === \"count\" && !spec[name2] ? [] : toArray2(spec[name2]);\n const options = {\n distinct: spec.distinct,\n orderby: toArray2(spec.orderby).map((v2) => ctx.maybeParam(v2)),\n partitionby: toArray2(spec.partitionby).map((v2) => ctx.maybeParam(v2)),\n rows: spec.rows ? ctx.maybeParam(spec.rows) : null,\n range: spec.range ? ctx.maybeParam(spec.range) : null\n };\n return new TransformNode(name2, args, options);\n }\n}\nvar TransformNode = class extends ASTNode {\n constructor(name2, args, options) {\n super(TRANSFORM);\n this.name = name2;\n this.args = args;\n this.options = options;\n }\n instantiate(ctx) {\n const { name: name2, args, options } = this;\n const { distinct: distinct2, orderby, partitionby, rows, range: range3 } = options;\n let expr = ctx.api[name2](...args);\n if (distinct2) {\n expr = expr.distinct();\n }\n if (orderby.length) {\n expr = expr.orderby(orderby.map((v2) => v2.instantiate(ctx)));\n }\n if (partitionby.length) {\n expr = expr.partitionby(partitionby.map((v2) => v2.instantiate(ctx)));\n }\n if (rows != null) {\n expr = expr.rows(rows.instantiate(ctx));\n } else if (range3 != null) {\n expr = expr.range(range3.instantiate(ctx));\n }\n return expr;\n }\n codegen(ctx) {\n const { name: name2, args, options } = this;\n const { distinct: distinct2, orderby, partitionby, rows, range: range3 } = options;\n let str = `${ctx.ns()}${name2}(` + args.map((v2) => JSON.stringify(v2)).join(\", \") + \")\";\n if (distinct2) {\n str += \".distinct()\";\n }\n if (orderby.length) {\n const p = orderby.map((v2) => v2.codegen(ctx));\n str += `.orderby(${p.join(\", \")})`;\n }\n if (partitionby.length) {\n const p = partitionby.map((v2) => v2.codegen(ctx));\n str += `.partitionby(${p.join(\", \")})`;\n }\n if (rows) {\n str += `.rows(${rows.codegen(ctx)})`;\n } else if (range3) {\n str += `.range(${range3.codegen(ctx)})`;\n }\n return str;\n }\n toJSON() {\n const { name: name2, args, options } = this;\n const { distinct: distinct2, orderby, partitionby, rows, range: range3 } = options;\n const json = { [name2]: simplify(args) };\n if (distinct2) {\n json.distinct = true;\n }\n if (orderby.length) {\n json.orderby = simplify(orderby.map((v2) => v2.toJSON()));\n }\n if (partitionby.length) {\n json.partitionby = simplify(partitionby.map((v2) => v2.toJSON()));\n }\n if (rows) {\n json.rows = rows.toJSON();\n } else if (range3) {\n json.range = range3.toJSON();\n }\n return json;\n }\n};\nvar BinTransformNode = class extends ASTNode {\n constructor(name2, arg, options) {\n super(TRANSFORM);\n this.name = name2;\n this.arg = arg;\n this.options = options;\n }\n instantiate(ctx) {\n const { name: name2, arg, options } = this;\n return ctx.api[name2](arg, options.instantiate(ctx));\n }\n codegen(ctx) {\n const { name: name2, arg, options } = this;\n const opt = options.codegen(ctx);\n return `${ctx.ns()}${name2}(` + JSON.stringify(arg) + (opt ? `, ${opt}` : \"\") + \")\";\n }\n toJSON() {\n const { name: name2, arg, options } = this;\n return { [name2]: arg, ...options.toJSON() };\n }\n};\nfunction simplify(array4) {\n return array4.length === 0 ? \"\" : array4.length === 1 ? array4[0] : array4;\n}\n\n// ../spec/src/ast/PlotMarkNode.js\nfunction maybeTransform(value, ctx) {\n if (isObject3(value)) {\n return value[SQL] || value[AGG] ? parseExpression(value, ctx) : parseTransform(value, ctx);\n }\n}\nfunction parseMark(spec, ctx) {\n const { mark: mark2, data, ...options } = spec;\n if (!ctx.plot?.marks?.has(mark2)) {\n ctx.error(`Unrecognized mark type: ${mark2}`, spec);\n }\n const input3 = parseMarkData(data, ctx);\n const opt = {};\n for (const key in options) {\n const value = options[key];\n opt[key] = maybeTransform(value, ctx) || ctx.maybeParam(value);\n }\n return new PlotMarkNode(mark2, input3, new OptionsNode(opt));\n}\nvar PlotMarkNode = class extends ASTNode {\n constructor(name2, data, options) {\n super(MARK);\n this.name = name2;\n this.data = data;\n this.options = options;\n }\n instantiate(ctx) {\n const { name: name2, data, options } = this;\n const opt = options.instantiate(ctx);\n return data ? ctx.api[name2](data.instantiate(ctx), opt) : ctx.api[name2](opt);\n }\n codegen(ctx) {\n const { name: name2, data, options } = this;\n const d = data ? data.codegen(ctx) : \"\";\n const o = options.codegen(ctx);\n let arg;\n if (d && o) {\n ctx.indent();\n const opt = options.codegen(ctx);\n arg = `\n${ctx.tab()}${d},\n${ctx.tab()}${opt}\n`;\n ctx.undent();\n arg += ctx.tab();\n } else {\n arg = `${d}${o}`;\n }\n return `${ctx.tab()}${ctx.ns()}${name2}(${arg})`;\n }\n toJSON() {\n const { type: type2, name: name2, data, options } = this;\n return {\n [type2]: name2,\n ...data ? { data: data.toJSON() } : {},\n ...options.toJSON()\n };\n }\n};\n\n// ../spec/src/ast/PlotNode.js\nfunction parseTopLevelMark(spec, ctx) {\n return parsePlot({ plot: [spec] }, ctx);\n}\nfunction parsePlot(spec, ctx) {\n const { [PLOT]: entries, ...attrs } = spec;\n const attributes2 = Object.entries(attrs).map(([key, value]) => parseAttribute(key, value, ctx));\n const children2 = entries.map((spec2) => {\n return isString(spec2.mark) ? parseMark(spec2, ctx) : isString(spec2.legend) ? parseLegend(spec2, ctx) : isString(spec2.select) ? parseInteractor(spec2, ctx) : ctx.error(`Invalid plot entry.`, spec2);\n });\n return new PlotNode(children2, attributes2);\n}\nvar PlotNode = class extends ASTNode {\n constructor(children2, attributes2) {\n super(PLOT, children2);\n this.attributes = attributes2;\n }\n instantiate(ctx) {\n const attrs = [\n ...ctx.plotDefaults || [],\n ...this.attributes || []\n ];\n return ctx.api[PLOT](\n this.children.map((c4) => c4.instantiate(ctx)),\n attrs.map((a2) => a2.instantiate(ctx))\n );\n }\n codegen(ctx) {\n const { type: type2, children: children2, attributes: attributes2 } = this;\n ctx.indent();\n const entries = [\n ...children2.map((c4) => c4.codegen(ctx)),\n ...ctx.plotDefaults?.length ? [`${ctx.tab()}...defaultAttributes`] : [],\n ...attributes2.map((a2) => a2.codegen(ctx))\n ].join(\",\\n\");\n ctx.undent();\n return `${ctx.tab()}${ctx.ns()}${type2}(\n${entries}\n${ctx.tab()})`;\n }\n toJSON() {\n const { type: type2, children: children2, attributes: attributes2 } = this;\n const plot3 = { [type2]: children2.map((c4) => c4.toJSON()) };\n for (const a2 of attributes2) {\n Object.assign(plot3, a2.toJSON());\n }\n return plot3;\n }\n};\n\n// ../spec/src/ast/VConcatNode.js\nfunction parseVConcat(spec, ctx) {\n const children2 = spec[VCONCAT].map((s2) => ctx.parseComponent(s2));\n return new VConcatNode(children2);\n}\nvar VConcatNode = class extends ASTNode {\n constructor(children2) {\n super(VCONCAT, children2);\n }\n instantiate(ctx) {\n return ctx.api[VCONCAT](this.children.map((c4) => c4.instantiate(ctx)));\n }\n codegen(ctx) {\n ctx.indent();\n const items = this.children.map((c4) => c4.codegen(ctx));\n ctx.undent();\n return `${ctx.tab()}${ctx.ns()}${this.type}(\n${items.join(\",\\n\")}\n${ctx.tab()})`;\n }\n toJSON() {\n return { [this.type]: this.children.map((c4) => c4.toJSON()) };\n }\n};\n\n// ../spec/src/ast/VSpaceNode.js\nfunction parseVSpace(spec) {\n return new VSpaceNode(spec[VSPACE]);\n}\nvar VSpaceNode = class extends ASTNode {\n constructor(value) {\n super(VSPACE);\n this.value = value;\n }\n instantiate(ctx) {\n return ctx.api[VSPACE](this.value);\n }\n codegen(ctx) {\n return `${ctx.tab()}${ctx.ns()}${this.type}(${ctx.stringify(this.value)})`;\n }\n toJSON() {\n return { [this.type]: this.value };\n }\n};\n\n// ../spec/src/config/components.js\nfunction componentMap(overrides = []) {\n return new Map([\n [PLOT, parsePlot],\n [MARK, parseTopLevelMark],\n [LEGEND, parseLegend],\n [INPUT, parseInput],\n [HCONCAT, parseHConcat],\n [VCONCAT, parseVConcat],\n [HSPACE, parseHSpace],\n [VSPACE, parseVSpace],\n ...overrides\n ]);\n}\n\n// ../spec/src/config/inputs.js\nfunction inputNames(overrides = []) {\n return /* @__PURE__ */ new Set([\n \"menu\",\n \"search\",\n \"slider\",\n \"table\",\n ...overrides\n ]);\n}\n\n// ../spec/src/config/plots.js\nfunction plotNames({\n attributes: attributes2 = plotAttributeNames(),\n interactors = plotInteractorNames(),\n legends = plotLegendNames(),\n marks: marks2 = plotMarkNames()\n} = {}) {\n return { attributes: attributes2, interactors, legends, marks: marks2 };\n}\nfunction plotAttributeNames(overrides = []) {\n return /* @__PURE__ */ new Set([\n ...Object.keys(attributes_exports),\n ...overrides\n ]);\n}\nfunction plotInteractorNames(overrides = []) {\n return /* @__PURE__ */ new Set([\n ...Object.keys(interactors_exports),\n ...overrides\n ]);\n}\nfunction plotLegendNames(overrides = []) {\n return /* @__PURE__ */ new Set([\n ...Object.keys(legends_exports),\n ...overrides\n ]);\n}\nfunction plotMarkNames(overrides = []) {\n return /* @__PURE__ */ new Set([\n ...Object.keys(marks_exports),\n ...overrides\n ]);\n}\n\n// ../spec/src/config/transforms.js\nfunction transformNames(overrides = []) {\n return /* @__PURE__ */ new Set([\n \"argmin\",\n \"argmax\",\n \"avg\",\n \"bin\",\n \"centroid\",\n \"centroidX\",\n \"centroidY\",\n \"count\",\n \"covariance\",\n \"covarPop\",\n \"dateMonth\",\n \"dateMonthDay\",\n \"dateDay\",\n \"first\",\n \"geojson\",\n \"last\",\n \"max\",\n \"median\",\n \"min\",\n \"mode\",\n \"product\",\n \"quantile\",\n \"stddev\",\n \"stddevPop\",\n \"sum\",\n \"variance\",\n \"varPop\",\n \"row_number\",\n \"rank\",\n \"dense_rank\",\n \"percent_rank\",\n \"cume_dist\",\n \"ntile\",\n \"lag\",\n \"lead\",\n \"first_value\",\n \"last_value\",\n \"nth_value\",\n ...overrides\n ]);\n}\n\n// ../spec/src/parse-spec.js\nfunction parseSpec(spec, options) {\n return new ParseContext(options).parse(spec);\n}\nvar ParseContext = class {\n /**\n * Create a new parser context.\n * @param {object} [options]\n * @param {Map} [options.components] Map of component names to parse functions.\n * @param {Set} [options.transforms] The names of allowed transform functions.\n * @param {Set} [options.inputs] The names of supported input widgets.\n * @param {PlotNames} [options.plot] The names of supported plot elements.\n * @param {any[]} [options.params] An array of [name, node] pairs of pre-parsed\n * Param or Selection AST nodes.\n * @param {any[]} [options.datasets] An array of [name, node] pairs of pre-parsed\n * dataset definition AST nodes.\n */\n constructor({\n components = componentMap(),\n transforms = transformNames(),\n inputs = inputNames(),\n plot: plot3 = plotNames(),\n params = [],\n datasets = []\n } = {}) {\n this.components = components;\n this.transforms = transforms;\n this.inputs = inputs;\n this.plot = plot3;\n this.params = new Map(params);\n this.datasets = new Map(datasets);\n }\n parse(spec) {\n const {\n meta,\n config,\n data = {},\n params,\n plotDefaults = {},\n ...root2\n } = spec;\n for (const name2 in data) {\n this.datasets.set(name2, parseData(name2, data[name2], this));\n }\n this.plotDefaults = Object.entries(plotDefaults).map(([key, value]) => parseAttribute(key, value, this));\n for (const name2 in params) {\n this.params.set(name2, parseParam(params[name2], this));\n }\n return new SpecNode(\n this.parseComponent(root2),\n meta ? { ...meta } : void 0,\n config ? { ...config } : void 0,\n Object.fromEntries(this.datasets),\n Object.fromEntries(this.params),\n this.plotDefaults\n );\n }\n parseComponent(spec) {\n for (const [key, parse2] of this.components) {\n const value = spec[key];\n if (value != null) {\n return parse2(spec, this);\n }\n }\n this.error(`Invalid specification.`, spec);\n }\n /**\n * Test if a value is a param reference, if so, generates a parameter\n * definition as needed and returns a new ParamRefNode. Otherwise,\n * returns a LiteralNode for the given value.\n * @param {*} value The value to test.\n * @returns {ParamRefNode|LiteralNode} An AST node for the input value.\n */\n maybeParam(value) {\n const name2 = paramRef(value);\n return name2 ? this.paramRef(name2) : new LiteralNode(value);\n }\n /**\n * Test if a value is a param reference, if so, generates a selection\n * definition as needed and returns a new ParamRefNode. Otherwise,\n * returns a LiteralNode for the given value.\n * @param {*} value The value to test.\n * @returns {ParamRefNode|LiteralNode} An AST node for the input value.\n */\n maybeSelection(value) {\n const name2 = paramRef(value);\n return name2 ? this.selectionRef(name2) : new LiteralNode(value);\n }\n /**\n * Create a parameter reference. Generates a parameter definition if needed\n * and returns a new ParamRefNode.\n * @param {string} name The parameter name.\n * @param {() => ParamNode | SelectionNode} [makeNode] A Param or Selection AST\n * node constructor.\n * @returns {ParamRefNode|null} A node referring to the param or selection.\n */\n paramRef(name2, makeNode = () => new ParamNode()) {\n const { params } = this;\n if (!name2) return null;\n let p = params.get(name2);\n if (!p) {\n p = makeNode();\n params.set(name2, p);\n }\n return new ParamRefNode(name2);\n }\n /**\n * Create a selection reference. Generates a selection definition if needed\n * and returns a new ParamRefNode. Returns null if a non-selection parameter\n * with the same name already exists and *strict* is true.\n * @param {string} name The selection name.\n * @param {boolean} [strict=false] Indicates if this method may return param\n * references (false, default) or only selection references (true).\n * @returns {ParamRefNode|null} A node referring to the param or selection.\n */\n selectionRef(name2, strict = false) {\n const p = this.params.get(name2);\n if (strict && p && !(p instanceof SelectionNode)) {\n return null;\n }\n return this.paramRef(name2, () => new SelectionNode());\n }\n error(message, data) {\n error(message, data);\n }\n};\n\n// ../../node_modules/uuid/dist/esm-browser/stringify.js\nvar byteToHex = [];\nfor (i = 0; i < 256; ++i) {\n byteToHex.push((i + 256).toString(16).slice(1));\n}\nvar i;\nfunction unsafeStringify(arr, offset2 = 0) {\n return (byteToHex[arr[offset2 + 0]] + byteToHex[arr[offset2 + 1]] + byteToHex[arr[offset2 + 2]] + byteToHex[arr[offset2 + 3]] + \"-\" + byteToHex[arr[offset2 + 4]] + byteToHex[arr[offset2 + 5]] + \"-\" + byteToHex[arr[offset2 + 6]] + byteToHex[arr[offset2 + 7]] + \"-\" + byteToHex[arr[offset2 + 8]] + byteToHex[arr[offset2 + 9]] + \"-\" + byteToHex[arr[offset2 + 10]] + byteToHex[arr[offset2 + 11]] + byteToHex[arr[offset2 + 12]] + byteToHex[arr[offset2 + 13]] + byteToHex[arr[offset2 + 14]] + byteToHex[arr[offset2 + 15]]).toLowerCase();\n}\n\n// ../../node_modules/uuid/dist/esm-browser/rng.js\nvar getRandomValues;\nvar rnds8 = new Uint8Array(16);\nfunction rng() {\n if (!getRandomValues) {\n getRandomValues = typeof crypto !== \"undefined\" && crypto.getRandomValues && crypto.getRandomValues.bind(crypto);\n if (!getRandomValues) {\n throw new Error(\"crypto.getRandomValues() not supported. See https://github.com/uuidjs/uuid#getrandomvalues-not-supported\");\n }\n }\n return getRandomValues(rnds8);\n}\n\n// ../../node_modules/uuid/dist/esm-browser/native.js\nvar randomUUID = typeof crypto !== \"undefined\" && crypto.randomUUID && crypto.randomUUID.bind(crypto);\nvar native_default = {\n randomUUID\n};\n\n// ../../node_modules/uuid/dist/esm-browser/v4.js\nfunction v4(options, buf2, offset2) {\n if (native_default.randomUUID && !buf2 && !options) {\n return native_default.randomUUID();\n }\n options = options || {};\n var rnds = options.random || (options.rng || rng)();\n rnds[6] = rnds[6] & 15 | 64;\n rnds[8] = rnds[8] & 63 | 128;\n if (buf2) {\n offset2 = offset2 || 0;\n for (var i = 0; i < 16; ++i) {\n buf2[offset2 + i] = rnds[i];\n }\n return buf2;\n }\n return unsafeStringify(rnds);\n}\nvar v4_default = v4;\n\n// src/index.js\nvar src_default = {\n /** @type {import('anywidget/types').Initialize} */\n initialize(view) {\n view.model.set(\"data_cube_schema\", coordinator().dataCubeIndexer.schema);\n },\n /** @type {import('anywidget/types').Render} */\n render(view) {\n view.el.classList.add(\"mosaic-widget\");\n const getSpec = () => view.model.get(\"spec\");\n const getDataCubeSchema = () => view.model.get(\"data_cube_schema\");\n const logger = coordinator().logger();\n const openQueries = /* @__PURE__ */ new Map();\n function send(query, resolve, reject) {\n const uuid = v4_default();\n openQueries.set(uuid, {\n query,\n startTime: performance.now(),\n resolve,\n reject\n });\n view.model.send({ ...query, uuid });\n }\n const connector = {\n query(query) {\n return new Promise((resolve, reject) => send(query, resolve, reject));\n }\n };\n function reset() {\n coordinator().clear();\n }\n async function updateSpec() {\n const spec = getSpec();\n reset();\n logger.log(\"Setting spec:\", spec);\n const dom = await instantiateSpec(spec);\n view.el.replaceChildren(dom.element);\n const params = {};\n for (const [name2, param] of dom.params) {\n params[name2] = {\n value: param.value,\n ...isSelection(param) ? { predicate: String(param.predicate()) } : {}\n };\n param.addEventListener(\"value\", (value) => {\n params[name2] = {\n value,\n ...isSelection(param) ? { predicate: String(param.predicate()) } : {}\n };\n view.model.set(\"params\", params);\n view.model.save_changes();\n });\n }\n view.model.set(\"params\", params);\n view.model.save_changes();\n }\n view.model.on(\"change:spec\", () => updateSpec());\n function configureCoordinator() {\n coordinator().dataCubeIndexer.schema = getDataCubeSchema();\n }\n view.model.on(\"change:data_cube_schema\", () => configureCoordinator());\n view.model.on(\"msg:custom\", (msg, buffers) => {\n logger.group(`query ${msg.uuid}`);\n logger.log(\"received message\", msg, buffers);\n const query = openQueries.get(msg.uuid);\n openQueries.delete(msg.uuid);\n logger.log(query.query.sql, (performance.now() - query.startTime).toFixed(1));\n if (msg.error) {\n query.reject(msg.error);\n logger.error(msg.error);\n } else {\n switch (msg.type) {\n case \"arrow\": {\n const table3 = decodeIPC2(buffers[0].buffer);\n logger.log(\"table\", table3);\n query.resolve(table3);\n break;\n }\n case \"json\": {\n logger.log(\"json\", msg.result);\n query.resolve(msg.result);\n break;\n }\n default: {\n query.resolve({});\n break;\n }\n }\n }\n logger.groupEnd(\"query\");\n });\n coordinator().databaseConnector(connector);\n configureCoordinator();\n updateSpec();\n return () => {\n reset();\n };\n }\n};\nfunction instantiateSpec(spec) {\n return astToDOM(parseSpec(spec));\n}\nexport {\n src_default as default\n};\n", + "_model_module": "anywidget", + "_model_module_version": "~0.9.*", + "_model_name": "AnyModel", + "_view_count": null, + "_view_module": "anywidget", + "_view_module_version": "~0.9.*", + "_view_name": "AnyView", + "data_cube_schema": "mosaic", + "layout": "IPY_MODEL_a5b987df120a4739848e2e8bd96a2fef", + "params": { + "domain": {}, + "colors": {}, + "click": { + "predicate": "" + } + }, + "spec": { + "colorDomain": "$domain", + "colorRange": "$colors", + "plot": [ + { + "data": { + "filterBy": "$click", + "from": "weather" + }, + "fill": "weather", + "mark": "dot", + "r": "precipitation", + "x": { + "dateMonthDay": "date" + }, + "y": "temp_max" + } + ], + "rDomain": "Fixed", + "rRange": [ + 2, + 10 + ], + "width": 800, + "xTickFormat": "%b", + "xyDomain": "Fixed" + } + } + }, + "a5b987df120a4739848e2e8bd96a2fef": { + "model_module": "@jupyter-widgets/base", + "model_name": "LayoutModel", + "model_module_version": "1.2.0", + "state": { + "_model_module": "@jupyter-widgets/base", + "_model_module_version": "1.2.0", + "_model_name": "LayoutModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "LayoutView", + "align_content": null, + "align_items": null, + "align_self": null, + "border": null, + "bottom": null, + "display": null, + "flex": null, + "flex_flow": null, + "grid_area": null, + "grid_auto_columns": null, + "grid_auto_flow": null, + "grid_auto_rows": null, + "grid_column": null, + "grid_gap": null, + "grid_row": null, + "grid_template_areas": null, + "grid_template_columns": null, + "grid_template_rows": null, + "height": null, + "justify_content": null, + "justify_items": null, + "left": null, + "margin": null, + "max_height": null, + "max_width": null, + "min_height": null, + "min_width": null, + "object_fit": null, + "object_position": null, + "order": null, + "overflow": null, + "overflow_x": null, + "overflow_y": null, + "padding": null, + "right": null, + "top": null, + "visibility": null, + "width": null + } + }, + "b91226e5c1b24aa0a602d1aab529936a": { + "model_module": "anywidget", + "model_name": "AnyModel", + "model_module_version": "~0.9.*", + "state": { + "_anywidget_id": "mosaic_widget.MosaicWidget", + "_css": "/* src/style.css */\n.mosaic-widget .input {\n margin-right: 1em;\n}\n.mosaic-widget .input > * {\n vertical-align: middle;\n}\n.mosaic-widget table {\n position: relative;\n table-layout: fixed;\n border-collapse: separate;\n border-spacing: 0;\n font-variant-numeric: tabular-nums;\n box-sizing: border-box;\n max-width: initial;\n min-height: 33px;\n margin: 0;\n width: 100%;\n font-size: 13px;\n line-height: 15.6px;\n}\n.mosaic-widget thead tr th {\n position: sticky;\n top: 0;\n background: #fff;\n cursor: ns-resize;\n border-bottom: solid 1px #ccc;\n}\n.mosaic-widget tbody tr:hover {\n background: #eef;\n}\n.mosaic-widget th {\n color: #111;\n text-align: left;\n vertical-align: bottom;\n}\n.mosaic-widget td,\nth {\n white-space: nowrap;\n text-overflow: ellipsis;\n overflow: hidden;\n padding: 3px 6.5px 3px 0;\n}\n.mosaic-widget tbody tr:first-child td {\n padding-top: 4px;\n}\n.mosaic-widget td,\ntr:not(:last-child) th {\n border-bottom: solid 1px #eee;\n}\n.mosaic-widget td {\n color: #444;\n vertical-align: top;\n}\n", + "_dom_classes": [], + "_esm": "var __create = Object.create;\nvar __defProp = Object.defineProperty;\nvar __getOwnPropDesc = Object.getOwnPropertyDescriptor;\nvar __getOwnPropNames = Object.getOwnPropertyNames;\nvar __getProtoOf = Object.getPrototypeOf;\nvar __hasOwnProp = Object.prototype.hasOwnProperty;\nvar __commonJS = (cb, mod) => function __require() {\n return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;\n};\nvar __export = (target, all2) => {\n for (var name2 in all2)\n __defProp(target, name2, { get: all2[name2], enumerable: true });\n};\nvar __copyProps = (to, from2, except, desc2) => {\n if (from2 && typeof from2 === \"object\" || typeof from2 === \"function\") {\n for (let key of __getOwnPropNames(from2))\n if (!__hasOwnProp.call(to, key) && key !== except)\n __defProp(to, key, { get: () => from2[key], enumerable: !(desc2 = __getOwnPropDesc(from2, key)) || desc2.enumerable });\n }\n return to;\n};\nvar __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(\n // If the importer is in node compatibility mode or this is not an ESM\n // file that has been converted to a CommonJS file using a Babel-\n // compatible transform (i.e. \"__esModule\" has not been set), then set\n // \"default\" to the CommonJS \"module.exports\" for node compatibility.\n isNodeMode || !mod || !mod.__esModule ? __defProp(target, \"default\", { value: mod, enumerable: true }) : target,\n mod\n));\n\n// ../../node_modules/binary-search-bounds/search-bounds.js\nvar require_search_bounds = __commonJS({\n \"../../node_modules/binary-search-bounds/search-bounds.js\"(exports, module) {\n \"use strict\";\n function ge(a2, y3, c4, l, h) {\n var i = h + 1;\n while (l <= h) {\n var m = l + h >>> 1, x3 = a2[m];\n var p = c4 !== void 0 ? c4(x3, y3) : x3 - y3;\n if (p >= 0) {\n i = m;\n h = m - 1;\n } else {\n l = m + 1;\n }\n }\n return i;\n }\n function gt2(a2, y3, c4, l, h) {\n var i = h + 1;\n while (l <= h) {\n var m = l + h >>> 1, x3 = a2[m];\n var p = c4 !== void 0 ? c4(x3, y3) : x3 - y3;\n if (p > 0) {\n i = m;\n h = m - 1;\n } else {\n l = m + 1;\n }\n }\n return i;\n }\n function lt2(a2, y3, c4, l, h) {\n var i = l - 1;\n while (l <= h) {\n var m = l + h >>> 1, x3 = a2[m];\n var p = c4 !== void 0 ? c4(x3, y3) : x3 - y3;\n if (p < 0) {\n i = m;\n l = m + 1;\n } else {\n h = m - 1;\n }\n }\n return i;\n }\n function le(a2, y3, c4, l, h) {\n var i = l - 1;\n while (l <= h) {\n var m = l + h >>> 1, x3 = a2[m];\n var p = c4 !== void 0 ? c4(x3, y3) : x3 - y3;\n if (p <= 0) {\n i = m;\n l = m + 1;\n } else {\n h = m - 1;\n }\n }\n return i;\n }\n function eq2(a2, y3, c4, l, h) {\n while (l <= h) {\n var m = l + h >>> 1, x3 = a2[m];\n var p = c4 !== void 0 ? c4(x3, y3) : x3 - y3;\n if (p === 0) {\n return m;\n }\n if (p <= 0) {\n l = m + 1;\n } else {\n h = m - 1;\n }\n }\n return -1;\n }\n function norm(a2, y3, c4, l, h, f) {\n if (typeof c4 === \"function\") {\n return f(a2, y3, c4, l === void 0 ? 0 : l | 0, h === void 0 ? a2.length - 1 : h | 0);\n }\n return f(a2, y3, void 0, c4 === void 0 ? 0 : c4 | 0, l === void 0 ? a2.length - 1 : l | 0);\n }\n module.exports = {\n ge: function(a2, y3, c4, l, h) {\n return norm(a2, y3, c4, l, h, ge);\n },\n gt: function(a2, y3, c4, l, h) {\n return norm(a2, y3, c4, l, h, gt2);\n },\n lt: function(a2, y3, c4, l, h) {\n return norm(a2, y3, c4, l, h, lt2);\n },\n le: function(a2, y3, c4, l, h) {\n return norm(a2, y3, c4, l, h, le);\n },\n eq: function(a2, y3, c4, l, h) {\n return norm(a2, y3, c4, l, h, eq2);\n }\n };\n }\n});\n\n// ../../node_modules/interval-tree-1d/interval-tree.js\nvar require_interval_tree = __commonJS({\n \"../../node_modules/interval-tree-1d/interval-tree.js\"(exports, module) {\n \"use strict\";\n var bounds = require_search_bounds();\n var NOT_FOUND = 0;\n var SUCCESS = 1;\n var EMPTY = 2;\n module.exports = createWrapper;\n function IntervalTreeNode(mid2, left2, right2, leftPoints, rightPoints) {\n this.mid = mid2;\n this.left = left2;\n this.right = right2;\n this.leftPoints = leftPoints;\n this.rightPoints = rightPoints;\n this.count = (left2 ? left2.count : 0) + (right2 ? right2.count : 0) + leftPoints.length;\n }\n var proto = IntervalTreeNode.prototype;\n function copy4(a2, b) {\n a2.mid = b.mid;\n a2.left = b.left;\n a2.right = b.right;\n a2.leftPoints = b.leftPoints;\n a2.rightPoints = b.rightPoints;\n a2.count = b.count;\n }\n function rebuild(node, intervals2) {\n var ntree = createIntervalTree(intervals2);\n node.mid = ntree.mid;\n node.left = ntree.left;\n node.right = ntree.right;\n node.leftPoints = ntree.leftPoints;\n node.rightPoints = ntree.rightPoints;\n node.count = ntree.count;\n }\n function rebuildWithInterval(node, interval3) {\n var intervals2 = node.intervals([]);\n intervals2.push(interval3);\n rebuild(node, intervals2);\n }\n function rebuildWithoutInterval(node, interval3) {\n var intervals2 = node.intervals([]);\n var idx = intervals2.indexOf(interval3);\n if (idx < 0) {\n return NOT_FOUND;\n }\n intervals2.splice(idx, 1);\n rebuild(node, intervals2);\n return SUCCESS;\n }\n proto.intervals = function(result) {\n result.push.apply(result, this.leftPoints);\n if (this.left) {\n this.left.intervals(result);\n }\n if (this.right) {\n this.right.intervals(result);\n }\n return result;\n };\n proto.insert = function(interval3) {\n var weight = this.count - this.leftPoints.length;\n this.count += 1;\n if (interval3[1] < this.mid) {\n if (this.left) {\n if (4 * (this.left.count + 1) > 3 * (weight + 1)) {\n rebuildWithInterval(this, interval3);\n } else {\n this.left.insert(interval3);\n }\n } else {\n this.left = createIntervalTree([interval3]);\n }\n } else if (interval3[0] > this.mid) {\n if (this.right) {\n if (4 * (this.right.count + 1) > 3 * (weight + 1)) {\n rebuildWithInterval(this, interval3);\n } else {\n this.right.insert(interval3);\n }\n } else {\n this.right = createIntervalTree([interval3]);\n }\n } else {\n var l = bounds.ge(this.leftPoints, interval3, compareBegin);\n var r = bounds.ge(this.rightPoints, interval3, compareEnd);\n this.leftPoints.splice(l, 0, interval3);\n this.rightPoints.splice(r, 0, interval3);\n }\n };\n proto.remove = function(interval3) {\n var weight = this.count - this.leftPoints;\n if (interval3[1] < this.mid) {\n if (!this.left) {\n return NOT_FOUND;\n }\n var rw = this.right ? this.right.count : 0;\n if (4 * rw > 3 * (weight - 1)) {\n return rebuildWithoutInterval(this, interval3);\n }\n var r = this.left.remove(interval3);\n if (r === EMPTY) {\n this.left = null;\n this.count -= 1;\n return SUCCESS;\n } else if (r === SUCCESS) {\n this.count -= 1;\n }\n return r;\n } else if (interval3[0] > this.mid) {\n if (!this.right) {\n return NOT_FOUND;\n }\n var lw = this.left ? this.left.count : 0;\n if (4 * lw > 3 * (weight - 1)) {\n return rebuildWithoutInterval(this, interval3);\n }\n var r = this.right.remove(interval3);\n if (r === EMPTY) {\n this.right = null;\n this.count -= 1;\n return SUCCESS;\n } else if (r === SUCCESS) {\n this.count -= 1;\n }\n return r;\n } else {\n if (this.count === 1) {\n if (this.leftPoints[0] === interval3) {\n return EMPTY;\n } else {\n return NOT_FOUND;\n }\n }\n if (this.leftPoints.length === 1 && this.leftPoints[0] === interval3) {\n if (this.left && this.right) {\n var p = this;\n var n = this.left;\n while (n.right) {\n p = n;\n n = n.right;\n }\n if (p === this) {\n n.right = this.right;\n } else {\n var l = this.left;\n var r = this.right;\n p.count -= n.count;\n p.right = n.left;\n n.left = l;\n n.right = r;\n }\n copy4(this, n);\n this.count = (this.left ? this.left.count : 0) + (this.right ? this.right.count : 0) + this.leftPoints.length;\n } else if (this.left) {\n copy4(this, this.left);\n } else {\n copy4(this, this.right);\n }\n return SUCCESS;\n }\n for (var l = bounds.ge(this.leftPoints, interval3, compareBegin); l < this.leftPoints.length; ++l) {\n if (this.leftPoints[l][0] !== interval3[0]) {\n break;\n }\n if (this.leftPoints[l] === interval3) {\n this.count -= 1;\n this.leftPoints.splice(l, 1);\n for (var r = bounds.ge(this.rightPoints, interval3, compareEnd); r < this.rightPoints.length; ++r) {\n if (this.rightPoints[r][1] !== interval3[1]) {\n break;\n } else if (this.rightPoints[r] === interval3) {\n this.rightPoints.splice(r, 1);\n return SUCCESS;\n }\n }\n }\n }\n return NOT_FOUND;\n }\n };\n function reportLeftRange(arr, hi, cb) {\n for (var i = 0; i < arr.length && arr[i][0] <= hi; ++i) {\n var r = cb(arr[i]);\n if (r) {\n return r;\n }\n }\n }\n function reportRightRange(arr, lo, cb) {\n for (var i = arr.length - 1; i >= 0 && arr[i][1] >= lo; --i) {\n var r = cb(arr[i]);\n if (r) {\n return r;\n }\n }\n }\n function reportRange(arr, cb) {\n for (var i = 0; i < arr.length; ++i) {\n var r = cb(arr[i]);\n if (r) {\n return r;\n }\n }\n }\n proto.queryPoint = function(x3, cb) {\n if (x3 < this.mid) {\n if (this.left) {\n var r = this.left.queryPoint(x3, cb);\n if (r) {\n return r;\n }\n }\n return reportLeftRange(this.leftPoints, x3, cb);\n } else if (x3 > this.mid) {\n if (this.right) {\n var r = this.right.queryPoint(x3, cb);\n if (r) {\n return r;\n }\n }\n return reportRightRange(this.rightPoints, x3, cb);\n } else {\n return reportRange(this.leftPoints, cb);\n }\n };\n proto.queryInterval = function(lo, hi, cb) {\n if (lo < this.mid && this.left) {\n var r = this.left.queryInterval(lo, hi, cb);\n if (r) {\n return r;\n }\n }\n if (hi > this.mid && this.right) {\n var r = this.right.queryInterval(lo, hi, cb);\n if (r) {\n return r;\n }\n }\n if (hi < this.mid) {\n return reportLeftRange(this.leftPoints, hi, cb);\n } else if (lo > this.mid) {\n return reportRightRange(this.rightPoints, lo, cb);\n } else {\n return reportRange(this.leftPoints, cb);\n }\n };\n function compareNumbers(a2, b) {\n return a2 - b;\n }\n function compareBegin(a2, b) {\n var d = a2[0] - b[0];\n if (d) {\n return d;\n }\n return a2[1] - b[1];\n }\n function compareEnd(a2, b) {\n var d = a2[1] - b[1];\n if (d) {\n return d;\n }\n return a2[0] - b[0];\n }\n function createIntervalTree(intervals2) {\n if (intervals2.length === 0) {\n return null;\n }\n var pts = [];\n for (var i = 0; i < intervals2.length; ++i) {\n pts.push(intervals2[i][0], intervals2[i][1]);\n }\n pts.sort(compareNumbers);\n var mid2 = pts[pts.length >> 1];\n var leftIntervals = [];\n var rightIntervals = [];\n var centerIntervals = [];\n for (var i = 0; i < intervals2.length; ++i) {\n var s2 = intervals2[i];\n if (s2[1] < mid2) {\n leftIntervals.push(s2);\n } else if (mid2 < s2[0]) {\n rightIntervals.push(s2);\n } else {\n centerIntervals.push(s2);\n }\n }\n var leftPoints = centerIntervals;\n var rightPoints = centerIntervals.slice();\n leftPoints.sort(compareBegin);\n rightPoints.sort(compareEnd);\n return new IntervalTreeNode(\n mid2,\n createIntervalTree(leftIntervals),\n createIntervalTree(rightIntervals),\n leftPoints,\n rightPoints\n );\n }\n function IntervalTree2(root2) {\n this.root = root2;\n }\n var tproto = IntervalTree2.prototype;\n tproto.insert = function(interval3) {\n if (this.root) {\n this.root.insert(interval3);\n } else {\n this.root = new IntervalTreeNode(interval3[0], null, null, [interval3], [interval3]);\n }\n };\n tproto.remove = function(interval3) {\n if (this.root) {\n var r = this.root.remove(interval3);\n if (r === EMPTY) {\n this.root = null;\n }\n return r !== NOT_FOUND;\n }\n return false;\n };\n tproto.queryPoint = function(p, cb) {\n if (this.root) {\n return this.root.queryPoint(p, cb);\n }\n };\n tproto.queryInterval = function(lo, hi, cb) {\n if (lo <= hi && this.root) {\n return this.root.queryInterval(lo, hi, cb);\n }\n };\n Object.defineProperty(tproto, \"count\", {\n get: function() {\n if (this.root) {\n return this.root.count;\n }\n return 0;\n }\n });\n Object.defineProperty(tproto, \"intervals\", {\n get: function() {\n if (this.root) {\n return this.root.intervals([]);\n }\n return [];\n }\n });\n function createWrapper(intervals2) {\n if (!intervals2 || intervals2.length === 0) {\n return new IntervalTree2(null);\n }\n return new IntervalTree2(createIntervalTree(intervals2));\n }\n }\n});\n\n// ../core/src/util/throttle.js\nvar NIL = {};\nfunction throttle(callback, debounce = false) {\n let curr;\n let next;\n let pending = NIL;\n function invoke(event) {\n curr = callback(event).finally(() => {\n if (next) {\n const { value } = next;\n next = null;\n invoke(value);\n } else {\n curr = null;\n }\n });\n }\n function enqueue(event) {\n next = { event };\n }\n function process(event) {\n curr ? enqueue(event) : invoke(event);\n }\n function delay(event) {\n if (pending !== event) {\n requestAnimationFrame(() => {\n const e = pending;\n pending = NIL;\n process(e);\n });\n }\n pending = event;\n }\n return debounce ? delay : process;\n}\n\n// ../core/src/MosaicClient.js\nvar MosaicClient = class {\n /**\n * Constructor.\n * @param {*} filterSelection An optional selection to interactively filter\n * this client's data. If provided, a coordinator will re-query and update\n * the client when the selection updates.\n */\n constructor(filterSelection) {\n this._filterBy = filterSelection;\n this._requestUpdate = throttle(() => this.requestQuery(), true);\n this._coordinator = null;\n }\n /**\n * Return this client's connected coordinator.\n */\n get coordinator() {\n return this._coordinator;\n }\n /**\n * Set this client's connected coordinator.\n */\n set coordinator(coordinator2) {\n this._coordinator = coordinator2;\n }\n /**\n * Return this client's filter selection.\n */\n get filterBy() {\n return this._filterBy;\n }\n /**\n * Return a boolean indicating if the client query can be indexed. Should\n * return true if changes to the filterBy selection does not change the\n * groupby domain of the client query.\n */\n get filterIndexable() {\n return true;\n }\n /**\n * Return an array of fields queried by this client.\n * @returns {object[]|null} The fields to retrieve info for.\n */\n fields() {\n return null;\n }\n /**\n * Called by the coordinator to set the field info for this client.\n * @param {*} info The field info result.\n * @returns {this}\n */\n fieldInfo(info) {\n return this;\n }\n /**\n * Return a query specifying the data needed by this client.\n * @param {*} [filter] The filtering criteria to apply in the query.\n * @returns {*} The client query\n */\n query(filter3) {\n return null;\n }\n /**\n * Called by the coordinator to inform the client that a query is pending.\n * @returns {this}\n */\n queryPending() {\n return this;\n }\n /**\n * Called by the coordinator to return a query result.\n * @param {*} data The query result.\n * @returns {this}\n */\n queryResult(data) {\n return this;\n }\n /**\n * Called by the coordinator to report a query execution error.\n * @param {*} error\n * @returns {this}\n */\n queryError(error2) {\n return this;\n }\n /**\n * Request the coordinator to execute a query for this client.\n * If an explicit query is not provided, the client query method will\n * be called, filtered by the current filterBy selection.\n * @returns {Promise}\n */\n requestQuery(query) {\n const q = query || this.query(this.filterBy?.predicate(this));\n return this._coordinator.requestQuery(this, q);\n }\n /**\n * Request that the coordinator perform a throttled update of this client\n * using the default query. Unlike requestQuery, for which every call will\n * result in an executed query, multiple calls to requestUpdate may be\n * consolidated into a single update.\n */\n requestUpdate() {\n this._requestUpdate();\n }\n /**\n * Reset this client, initiating new field info and query requests.\n * @returns {Promise}\n */\n initialize() {\n return this._coordinator.initializeClient(this);\n }\n /**\n * Requests a client update.\n * For example to (re-)render an interface component.\n *\n * @returns {this | Promise}\n */\n update() {\n return this;\n }\n};\n\n// ../../node_modules/@uwdata/flechette/src/constants.js\nvar MAGIC = Uint8Array.of(65, 82, 82, 79, 87, 49);\nvar Version = (\n /** @type {const} */\n {\n /** 0.1.0 (October 2016). */\n V1: 0,\n /** 0.2.0 (February 2017). Non-backwards compatible with V1. */\n V2: 1,\n /** 0.3.0 -> 0.7.1 (May - December 2017). Non-backwards compatible with V2. */\n V3: 2,\n /** >= 0.8.0 (December 2017). Non-backwards compatible with V3. */\n V4: 3,\n /**\n * >= 1.0.0 (July 2020). Backwards compatible with V4 (V5 readers can read V4\n * metadata and IPC messages). Implementations are recommended to provide a\n * V4 compatibility mode with V5 format changes disabled.\n *\n * Incompatible changes between V4 and V5:\n * - Union buffer layout has changed.\n * In V5, Unions don't have a validity bitmap buffer.\n */\n V5: 4\n }\n);\nvar MessageHeader = (\n /** @type {const} */\n {\n NONE: 0,\n /**\n * A Schema describes the columns in a record batch.\n */\n Schema: 1,\n /**\n * For sending dictionary encoding information. Any Field can be\n * dictionary-encoded, but in this case none of its children may be\n * dictionary-encoded.\n * There is one vector / column per dictionary, but that vector / column\n * may be spread across multiple dictionary batches by using the isDelta\n * flag.\n */\n DictionaryBatch: 2,\n /**\n * A data header describing the shared memory layout of a \"record\" or \"row\"\n * batch. Some systems call this a \"row batch\" internally and others a \"record\n * batch\".\n */\n RecordBatch: 3,\n /**\n * EXPERIMENTAL: Metadata for n-dimensional arrays, aka \"tensors\" or\n * \"ndarrays\". Arrow implementations in general are not required to implement\n * this type.\n *\n * Not currently supported by Flechette.\n */\n Tensor: 4,\n /**\n * EXPERIMENTAL: Metadata for n-dimensional sparse arrays, aka \"sparse\n * tensors\". Arrow implementations in general are not required to implement\n * this type.\n *\n * Not currently supported by Flechette.\n */\n SparseTensor: 5\n }\n);\nvar Type = (\n /** @type {const} */\n {\n /**\n * Dictionary types compress data by using a set of integer indices to\n * lookup potentially repeated vales in a separate dictionary of values.\n *\n * This type entry is provided for API convenience, it does not occur\n * in actual Arrow IPC binary data.\n */\n Dictionary: -1,\n /** No data type. Included for flatbuffer compatibility. */\n NONE: 0,\n /** Null values only. */\n Null: 1,\n /** Integers, either signed or unsigned, with 8, 16, 32, or 64 bit widths. */\n Int: 2,\n /** Floating point numbers with 16, 32, or 64 bit precision. */\n Float: 3,\n /** Opaque binary data. */\n Binary: 4,\n /** Unicode with UTF-8 encoding. */\n Utf8: 5,\n /** Booleans represented as 8 bit bytes. */\n Bool: 6,\n /**\n * Exact decimal value represented as an integer value in two's complement.\n * Currently only 128-bit (16-byte) and 256-bit (32-byte) integers are used.\n * The representation uses the endianness indicated in the schema.\n */\n Decimal: 7,\n /**\n * Date is either a 32-bit or 64-bit signed integer type representing an\n * elapsed time since UNIX epoch (1970-01-01), stored in either of two units:\n * - Milliseconds (64 bits) indicating UNIX time elapsed since the epoch (no\n * leap seconds), where the values are evenly divisible by 86400000\n * - Days (32 bits) since the UNIX epoch\n */\n Date: 8,\n /**\n * Time is either a 32-bit or 64-bit signed integer type representing an\n * elapsed time since midnight, stored in either of four units: seconds,\n * milliseconds, microseconds or nanoseconds.\n *\n * The integer `bitWidth` depends on the `unit` and must be one of the following:\n * - SECOND and MILLISECOND: 32 bits\n * - MICROSECOND and NANOSECOND: 64 bits\n *\n * The allowed values are between 0 (inclusive) and 86400 (=24*60*60) seconds\n * (exclusive), adjusted for the time unit (for example, up to 86400000\n * exclusive for the MILLISECOND unit).\n * This definition doesn't allow for leap seconds. Time values from\n * measurements with leap seconds will need to be corrected when ingesting\n * into Arrow (for example by replacing the value 86400 with 86399).\n */\n Time: 9,\n /**\n * Timestamp is a 64-bit signed integer representing an elapsed time since a\n * fixed epoch, stored in either of four units: seconds, milliseconds,\n * microseconds or nanoseconds, and is optionally annotated with a timezone.\n *\n * Timestamp values do not include any leap seconds (in other words, all\n * days are considered 86400 seconds long).\n *\n * The timezone is an optional string for the name of a timezone, one of:\n *\n * - As used in the Olson timezone database (the \"tz database\" or\n * \"tzdata\"), such as \"America/New_York\".\n * - An absolute timezone offset of the form \"+XX:XX\" or \"-XX:XX\",\n * such as \"+07:30\".\n *\n * Whether a timezone string is present indicates different semantics about\n * the data.\n */\n Timestamp: 10,\n /**\n * A \"calendar\" interval which models types that don't necessarily\n * have a precise duration without the context of a base timestamp (e.g.\n * days can differ in length during day light savings time transitions).\n * All integers in the units below are stored in the endianness indicated\n * by the schema.\n *\n * - YEAR_MONTH - Indicates the number of elapsed whole months, stored as\n * 4-byte signed integers.\n * - DAY_TIME - Indicates the number of elapsed days and milliseconds (no\n * leap seconds), stored as 2 contiguous 32-bit signed integers (8-bytes\n * in total). Support of this IntervalUnit is not required for full arrow\n * compatibility.\n * - MONTH_DAY_NANO - A triple of the number of elapsed months, days, and\n * nanoseconds. The values are stored contiguously in 16-byte blocks.\n * Months and days are encoded as 32-bit signed integers and nanoseconds\n * is encoded as a 64-bit signed integer. Nanoseconds does not allow for\n * leap seconds. Each field is independent (e.g. there is no constraint\n * that nanoseconds have the same sign as days or that the quantity of\n * nanoseconds represents less than a day's worth of time).\n */\n Interval: 11,\n /**\n * List (vector) data supporting variably-sized lists.\n * A list has a single child data type for list entries.\n */\n List: 12,\n /**\n * A struct consisting of multiple named child data types.\n */\n Struct: 13,\n /**\n * A union is a complex type with parallel child data types. By default ids\n * in the type vector refer to the offsets in the children. Optionally\n * typeIds provides an indirection between the child offset and the type id.\n * For each child `typeIds[offset]` is the id used in the type vector.\n */\n Union: 14,\n /**\n * Binary data where each entry has the same fixed size.\n */\n FixedSizeBinary: 15,\n /**\n * List (vector) data where every list has the same fixed size.\n * A list has a single child data type for list entries.\n */\n FixedSizeList: 16,\n /**\n * A Map is a logical nested type that is represented as\n * List>\n *\n * In this layout, the keys and values are each respectively contiguous. We do\n * not constrain the key and value types, so the application is responsible\n * for ensuring that the keys are hashable and unique. Whether the keys are sorted\n * may be set in the metadata for this field.\n *\n * In a field with Map type, the field has a child Struct field, which then\n * has two children: key type and the second the value type. The names of the\n * child fields may be respectively \"entries\", \"key\", and \"value\", but this is\n * not enforced.\n *\n * Map\n * ```text\n * - child[0] entries: Struct\n * - child[0] key: K\n * - child[1] value: V\n * ```\n * Neither the \"entries\" field nor the \"key\" field may be nullable.\n *\n * The metadata is structured so that Arrow systems without special handling\n * for Map can make Map an alias for List. The \"layout\" attribute for the Map\n * field must have the same contents as a List.\n */\n Map: 17,\n /**\n * An absolute length of time unrelated to any calendar artifacts. For the\n * purposes of Arrow implementations, adding this value to a Timestamp\n * (\"t1\") naively (i.e. simply summing the two numbers) is acceptable even\n * though in some cases the resulting Timestamp (t2) would not account for\n * leap-seconds during the elapsed time between \"t1\" and \"t2\". Similarly,\n * representing the difference between two Unix timestamp is acceptable, but\n * would yield a value that is possibly a few seconds off from the true\n * elapsed time.\n *\n * The resolution defaults to millisecond, but can be any of the other\n * supported TimeUnit values as with Timestamp and Time types. This type is\n * always represented as an 8-byte integer.\n */\n Duration: 18,\n /**\n * Same as Binary, but with 64-bit offsets, allowing representation of\n * extremely large data values.\n */\n LargeBinary: 19,\n /**\n * Same as Utf8, but with 64-bit offsets, allowing representation of\n * extremely large data values.\n */\n LargeUtf8: 20,\n /**\n * Same as List, but with 64-bit offsets, allowing representation of\n * extremely large data values.\n */\n LargeList: 21,\n /**\n * Contains two child arrays, run_ends and values. The run_ends child array\n * must be a 16/32/64-bit integer array which encodes the indices at which\n * the run with the value in each corresponding index in the values child\n * array ends. Like list/struct types, the value array can be of any type.\n */\n RunEndEncoded: 22,\n /**\n * Logically the same as Binary, but the internal representation uses a view\n * struct that contains the string length and either the string's entire data\n * inline (for small strings) or an inlined prefix, an index of another buffer,\n * and an offset pointing to a slice in that buffer (for non-small strings).\n *\n * Since it uses a variable number of data buffers, each Field with this type\n * must have a corresponding entry in `variadicBufferCounts`.\n */\n BinaryView: 23,\n /**\n * Logically the same as Utf8, but the internal representation uses a view\n * struct that contains the string length and either the string's entire data\n * inline (for small strings) or an inlined prefix, an index of another buffer,\n * and an offset pointing to a slice in that buffer (for non-small strings).\n *\n * Since it uses a variable number of data buffers, each Field with this type\n * must have a corresponding entry in `variadicBufferCounts`.\n */\n Utf8View: 24,\n /**\n * Represents the same logical types that List can, but contains offsets and\n * sizes allowing for writes in any order and sharing of child values among\n * list values.\n */\n ListView: 25,\n /**\n * Same as ListView, but with 64-bit offsets and sizes, allowing to represent\n * extremely large data values.\n */\n LargeListView: 26\n }\n);\nvar Precision = (\n /** @type {const} */\n {\n /** 16-bit floating point number. */\n HALF: 0,\n /** 32-bit floating point number. */\n SINGLE: 1,\n /** 64-bit floating point number. */\n DOUBLE: 2\n }\n);\nvar DateUnit = (\n /** @type {const} */\n {\n /* Days (as 32 bit int) since the UNIX epoch. */\n DAY: 0,\n /**\n * Milliseconds (as 64 bit int) indicating UNIX time elapsed since the epoch\n * (no leap seconds), with values evenly divisible by 86400000.\n */\n MILLISECOND: 1\n }\n);\nvar TimeUnit = (\n /** @type {const} */\n {\n /** Seconds. */\n SECOND: 0,\n /** Milliseconds. */\n MILLISECOND: 1,\n /** Microseconds. */\n MICROSECOND: 2,\n /** Nanoseconds. */\n NANOSECOND: 3\n }\n);\nvar IntervalUnit = (\n /** @type {const} */\n {\n /**\n * Indicates the number of elapsed whole months, stored as 4-byte signed\n * integers.\n */\n YEAR_MONTH: 0,\n /**\n * Indicates the number of elapsed days and milliseconds (no leap seconds),\n * stored as 2 contiguous 32-bit signed integers (8-bytes in total). Support\n * of this IntervalUnit is not required for full arrow compatibility.\n */\n DAY_TIME: 1,\n /**\n * A triple of the number of elapsed months, days, and nanoseconds.\n * The values are stored contiguously in 16-byte blocks. Months and days are\n * encoded as 32-bit signed integers and nanoseconds is encoded as a 64-bit\n * signed integer. Nanoseconds does not allow for leap seconds. Each field is\n * independent (e.g. there is no constraint that nanoseconds have the same\n * sign as days or that the quantity of nanoseconds represents less than a\n * day's worth of time).\n */\n MONTH_DAY_NANO: 2\n }\n);\nvar UnionMode = (\n /** @type {const} */\n {\n /** Sparse union layout with full arrays for each sub-type. */\n Sparse: 0,\n /** Dense union layout with offsets into value arrays. */\n Dense: 1\n }\n);\n\n// ../../node_modules/@uwdata/flechette/src/util/arrays.js\nvar uint8Array = Uint8Array;\nvar uint16Array = Uint16Array;\nvar uint32Array = Uint32Array;\nvar uint64Array = BigUint64Array;\nvar int8Array = Int8Array;\nvar int16Array = Int16Array;\nvar int32Array = Int32Array;\nvar int64Array = BigInt64Array;\nvar float32Array = Float32Array;\nvar float64Array = Float64Array;\nfunction intArrayType(bitWidth, signed) {\n const i = Math.log2(bitWidth) - 3;\n return (signed ? [int8Array, int16Array, int32Array, int64Array] : [uint8Array, uint16Array, uint32Array, uint64Array])[i];\n}\nvar TypedArray = Object.getPrototypeOf(Int8Array);\nfunction bisect(offsets, index2) {\n let a2 = 0;\n let b = offsets.length;\n if (b <= 2147483648) {\n do {\n const mid2 = a2 + b >>> 1;\n if (offsets[mid2] <= index2) a2 = mid2 + 1;\n else b = mid2;\n } while (a2 < b);\n } else {\n do {\n const mid2 = Math.trunc((a2 + b) / 2);\n if (offsets[mid2] <= index2) a2 = mid2 + 1;\n else b = mid2;\n } while (a2 < b);\n }\n return a2;\n}\n\n// ../../node_modules/@uwdata/flechette/src/util/objects.js\nfunction check(value, test, message) {\n if (test(value)) return value;\n throw new Error(message(value));\n}\nfunction checkOneOf(value, set3, message) {\n set3 = Array.isArray(set3) ? set3 : Object.values(set3);\n return check(\n value,\n (value2) => set3.includes(value2),\n message ?? (() => `${value} must be one of ${set3}`)\n );\n}\nfunction keyFor(object, value) {\n for (const [key, val] of Object.entries(object)) {\n if (val === value) return key;\n }\n return \"\";\n}\n\n// ../../node_modules/@uwdata/flechette/src/data-types.js\nvar invalidDataType = (typeId) => `Unsupported data type: \"${keyFor(Type, typeId)}\" (id ${typeId})`;\nvar field = (name2, type2, nullable = true, metadata = null) => ({\n name: name2,\n type: type2,\n nullable,\n metadata\n});\nfunction isField(value) {\n return Object.hasOwn(value, \"name\") && isDataType(value.type);\n}\nfunction isDataType(value) {\n return typeof value?.typeId === \"number\";\n}\nfunction asField(value, defaultName = \"\", defaultNullable = true) {\n return isField(value) ? value : field(\n defaultName,\n check(value, isDataType, () => `Data type expected.`),\n defaultNullable\n );\n}\nvar dictionary = (type2, indexType, ordered = false, id2 = -1) => ({\n typeId: Type.Dictionary,\n id: id2,\n dictionary: type2,\n indices: indexType || int32(),\n ordered\n});\nvar int = (bitWidth = 32, signed = true) => ({\n typeId: Type.Int,\n bitWidth: checkOneOf(bitWidth, [8, 16, 32, 64]),\n signed,\n values: intArrayType(bitWidth, signed)\n});\nvar int32 = () => int(32);\nvar float = (precision = 2) => ({\n typeId: Type.Float,\n precision: checkOneOf(precision, Precision),\n values: [uint16Array, float32Array, float64Array][precision]\n});\nvar binary = () => ({\n typeId: Type.Binary,\n offsets: int32Array\n});\nvar utf8 = () => ({\n typeId: Type.Utf8,\n offsets: int32Array\n});\nvar decimal = (precision, scale3, bitWidth = 128) => ({\n typeId: Type.Decimal,\n precision,\n scale: scale3,\n bitWidth: checkOneOf(bitWidth, [128, 256]),\n values: uint64Array\n});\nvar date = (unit3) => ({\n typeId: Type.Date,\n unit: checkOneOf(unit3, DateUnit),\n values: unit3 === DateUnit.DAY ? int32Array : int64Array\n});\nvar time = (unit3 = TimeUnit.MILLISECOND, bitWidth = 32) => ({\n typeId: Type.Time,\n unit: checkOneOf(unit3, TimeUnit),\n bitWidth: checkOneOf(bitWidth, [32, 64]),\n values: bitWidth === 32 ? int32Array : int64Array\n});\nvar timestamp = (unit3 = TimeUnit.MILLISECOND, timezone = null) => ({\n typeId: Type.Timestamp,\n unit: checkOneOf(unit3, TimeUnit),\n timezone,\n values: int64Array\n});\nvar interval = (unit3 = IntervalUnit.MONTH_DAY_NANO) => ({\n typeId: Type.Interval,\n unit: checkOneOf(unit3, IntervalUnit),\n values: unit3 === IntervalUnit.MONTH_DAY_NANO ? void 0 : int32Array\n});\nvar list = (child) => ({\n typeId: Type.List,\n children: [asField(child)],\n offsets: int32Array\n});\nvar struct = (children2) => ({\n typeId: Type.Struct,\n children: Array.isArray(children2) && isField(children2[0]) ? (\n /** @type {import('./types.js').Field[]} */\n children2\n ) : Object.entries(children2).map(([name2, type2]) => field(name2, type2))\n});\nvar union = (mode3, children2, typeIds, typeIdForValue) => {\n typeIds ??= children2.map((v2, i) => i);\n return {\n typeId: Type.Union,\n mode: checkOneOf(mode3, UnionMode),\n typeIds,\n typeMap: typeIds.reduce((m, id2, i) => (m[id2] = i, m), {}),\n children: children2.map((v2, i) => asField(v2, `_${i}`)),\n typeIdForValue,\n offsets: int32Array\n };\n};\nvar fixedSizeBinary = (stride) => ({\n typeId: Type.FixedSizeBinary,\n stride\n});\nvar fixedSizeList = (child, stride) => ({\n typeId: Type.FixedSizeList,\n stride,\n children: [asField(child)]\n});\nvar mapType = (keysSorted, child) => ({\n typeId: Type.Map,\n keysSorted,\n children: [child],\n offsets: int32Array\n});\nvar duration = (unit3 = TimeUnit.MILLISECOND) => ({\n typeId: Type.Duration,\n unit: checkOneOf(unit3, TimeUnit),\n values: int64Array\n});\nvar largeBinary = () => ({\n typeId: Type.LargeBinary,\n offsets: int64Array\n});\nvar largeUtf8 = () => ({\n typeId: Type.LargeUtf8,\n offsets: int64Array\n});\nvar largeList = (child) => ({\n typeId: Type.LargeList,\n children: [asField(child)],\n offsets: int64Array\n});\nvar runEndEncoded = (runsField, valuesField) => ({\n typeId: Type.RunEndEncoded,\n children: [\n check(\n asField(runsField, \"run_ends\"),\n (field3) => field3.type.typeId === Type.Int,\n () => \"Run-ends must have an integer type.\"\n ),\n asField(valuesField, \"values\")\n ]\n});\nvar listView = (child) => ({\n typeId: Type.ListView,\n children: [asField(child, \"value\")],\n offsets: int32Array\n});\nvar largeListView = (child) => ({\n typeId: Type.LargeListView,\n children: [asField(child, \"value\")],\n offsets: int64Array\n});\n\n// ../../node_modules/@uwdata/flechette/src/util/numbers.js\nvar f64 = new float64Array(2);\nvar buf = f64.buffer;\nvar i64 = new int64Array(buf);\nvar u32 = new uint32Array(buf);\nvar i32 = new int32Array(buf);\nvar u8 = new uint8Array(buf);\nfunction toNumber(value) {\n if (value > Number.MAX_SAFE_INTEGER || value < Number.MIN_SAFE_INTEGER) {\n throw Error(`BigInt exceeds integer number representation: ${value}`);\n }\n return Number(value);\n}\nfunction divide(num, div) {\n return Number(num / div) + Number(num % div) / Number(div);\n}\nvar asUint64 = (v2) => BigInt.asUintN(64, v2);\nfunction fromDecimal128(buf2, offset2) {\n const i = offset2 << 1;\n let x3;\n if (BigInt.asIntN(64, buf2[i + 1]) < 0) {\n x3 = asUint64(~buf2[i]) | asUint64(~buf2[i + 1]) << 64n;\n x3 = -(x3 + 1n);\n } else {\n x3 = buf2[i] | buf2[i + 1] << 64n;\n }\n return x3;\n}\nfunction fromDecimal256(buf2, offset2) {\n const i = offset2 << 2;\n let x3;\n if (BigInt.asIntN(64, buf2[i + 3]) < 0) {\n x3 = asUint64(~buf2[i]) | asUint64(~buf2[i + 1]) << 64n | asUint64(~buf2[i + 2]) << 128n | asUint64(~buf2[i + 3]) << 192n;\n x3 = -(x3 + 1n);\n } else {\n x3 = buf2[i] | buf2[i + 1] << 64n | buf2[i + 2] << 128n | buf2[i + 3] << 192n;\n }\n return x3;\n}\n\n// ../../node_modules/@uwdata/flechette/src/util/strings.js\nvar textDecoder = new TextDecoder(\"utf-8\");\nvar textEncoder = new TextEncoder();\nfunction decodeUtf8(buf2) {\n return textDecoder.decode(buf2);\n}\n\n// ../../node_modules/@uwdata/flechette/src/util/read.js\nvar SIZEOF_INT = 4;\nfunction decodeBit(bitmap2, index2) {\n return (bitmap2[index2 >> 3] & 1 << index2 % 8) !== 0;\n}\nfunction readObject(buf2, index2) {\n const pos = index2 + readInt32(buf2, index2);\n const vtable = pos - readInt32(buf2, pos);\n const size = readInt16(buf2, vtable);\n return (index3, read, fallback = null) => {\n if (index3 < size) {\n const off = readInt16(buf2, vtable + index3);\n if (off) return read(buf2, pos + off);\n }\n return fallback;\n };\n}\nfunction readOffset(buf2, offset2) {\n return offset2;\n}\nfunction readBoolean(buf2, offset2) {\n return !!readInt8(buf2, offset2);\n}\nfunction readInt8(buf2, offset2) {\n return readUint8(buf2, offset2) << 24 >> 24;\n}\nfunction readUint8(buf2, offset2) {\n return buf2[offset2];\n}\nfunction readInt16(buf2, offset2) {\n return readUint16(buf2, offset2) << 16 >> 16;\n}\nfunction readUint16(buf2, offset2) {\n return buf2[offset2] | buf2[offset2 + 1] << 8;\n}\nfunction readInt32(buf2, offset2) {\n return buf2[offset2] | buf2[offset2 + 1] << 8 | buf2[offset2 + 2] << 16 | buf2[offset2 + 3] << 24;\n}\nfunction readUint32(buf2, offset2) {\n return readInt32(buf2, offset2) >>> 0;\n}\nfunction readInt64(buf2, offset2) {\n return toNumber(BigInt.asIntN(\n 64,\n BigInt(readUint32(buf2, offset2)) + (BigInt(readUint32(buf2, offset2 + SIZEOF_INT)) << 32n)\n ));\n}\nfunction readString(buf2, index2) {\n let offset2 = index2 + readInt32(buf2, index2);\n const length4 = readInt32(buf2, offset2);\n offset2 += SIZEOF_INT;\n return decodeUtf8(buf2.subarray(offset2, offset2 + length4));\n}\nfunction readVector(buf2, offset2, stride, extract) {\n if (!offset2) return [];\n const base = offset2 + readInt32(buf2, offset2);\n return Array.from(\n { length: readInt32(buf2, base) },\n (_, i) => extract(buf2, base + SIZEOF_INT + i * stride)\n );\n}\n\n// ../../node_modules/@uwdata/flechette/src/util/struct.js\nvar RowIndex = Symbol(\"rowIndex\");\nfunction proxyFactory(names, batches) {\n class RowObject {\n /**\n * Create a new proxy row object representing a struct or table row.\n * @param {number} index The record batch row index.\n */\n constructor(index2) {\n this[RowIndex] = index2;\n }\n /**\n * Return a JSON-compatible object representation.\n */\n toJSON() {\n return structObject(names, batches, this[RowIndex]);\n }\n }\n ;\n const proto = RowObject.prototype;\n for (let i = 0; i < names.length; ++i) {\n if (Object.hasOwn(proto, names[i])) continue;\n const batch = batches[i];\n Object.defineProperty(proto, names[i], {\n get() {\n return batch.at(this[RowIndex]);\n },\n enumerable: true\n });\n }\n return (index2) => new RowObject(index2);\n}\nfunction objectFactory(names, batches) {\n return (index2) => structObject(names, batches, index2);\n}\nfunction structObject(names, batches, index2) {\n const obj = {};\n for (let i = 0; i < names.length; ++i) {\n obj[names[i]] = batches[i].at(index2);\n }\n return obj;\n}\n\n// ../../node_modules/@uwdata/flechette/src/batch.js\nfunction isDirectBatch(batch) {\n return batch instanceof DirectBatch;\n}\nvar Batch = class {\n /**\n * The array type to use when extracting data from the batch.\n * A null value indicates that the array type should match\n * the type of the batch's values array.\n * @type {ArrayConstructor | import('./types.js').TypedArrayConstructor | null}\n */\n static ArrayType = null;\n /**\n * Create a new column batch.\n * @param {object} options\n * @param {number} options.length The length of the batch\n * @param {number} options.nullCount The null value count\n * @param {import('./types.js').DataType} options.type The data type.\n * @param {Uint8Array} [options.validity] Validity bitmap buffer\n * @param {import('./types.js').TypedArray} [options.values] Values buffer\n * @param {import('./types.js').OffsetArray} [options.offsets] Offsets buffer\n * @param {import('./types.js').OffsetArray} [options.sizes] Sizes buffer\n * @param {Batch[]} [options.children] Children batches\n */\n constructor({\n length: length4,\n nullCount,\n type: type2,\n validity,\n values: values2,\n offsets,\n sizes,\n children: children2\n }) {\n this.length = length4;\n this.nullCount = nullCount;\n this.type = type2;\n this.validity = validity;\n this.values = values2;\n this.offsets = offsets;\n this.sizes = sizes;\n this.children = children2;\n if (!nullCount || !this.validity) {\n this.at = (index2) => this.value(index2);\n }\n }\n /**\n * Provide an informative object string tag.\n */\n get [Symbol.toStringTag]() {\n return \"Batch\";\n }\n /**\n * Return the value at the given index.\n * @param {number} index The value index.\n * @returns {T | null} The value.\n */\n at(index2) {\n return this.isValid(index2) ? this.value(index2) : null;\n }\n /**\n * Check if a value at the given index is valid (non-null).\n * @param {number} index The value index.\n * @returns {boolean} True if valid, false otherwise.\n */\n isValid(index2) {\n return decodeBit(this.validity, index2);\n }\n /**\n * Return the value at the given index. This method does not check the\n * validity bitmap and is intended primarily for internal use. In most\n * cases, callers should use the `at()` method instead.\n * @param {number} index The value index\n * @returns {T} The value, ignoring the validity bitmap.\n */\n value(index2) {\n return (\n /** @type {T} */\n this.values[index2]\n );\n }\n /**\n * Extract an array of values within the given index range. Unlike\n * Array.slice, all arguments are required and may not be negative indices.\n * @param {number} start The starting index, inclusive\n * @param {number} end The ending index, exclusive\n * @returns {import('./types.js').ValueArray} The slice of values\n */\n slice(start2, end) {\n const n = end - start2;\n const values2 = Array(n);\n for (let i = 0; i < n; ++i) {\n values2[i] = this.at(start2 + i);\n }\n return values2;\n }\n /**\n * Return an iterator over the values in this batch.\n * @returns {Iterator}\n */\n *[Symbol.iterator]() {\n for (let i = 0; i < this.length; ++i) {\n yield this.at(i);\n }\n }\n};\nvar DirectBatch = class extends Batch {\n /**\n * Create a new column batch with direct value array access.\n * @param {object} options\n * @param {number} options.length The length of the batch\n * @param {number} options.nullCount The null value count\n * @param {import('./types.js').DataType} options.type The data type.\n * @param {Uint8Array} [options.validity] Validity bitmap buffer\n * @param {import('./types.js').TypedArray} options.values Values buffer\n */\n constructor(options) {\n super(options);\n const { length: length4, values: values2 } = this;\n this.values = values2.subarray(0, length4);\n }\n /**\n * Extract an array of values within the given index range. Unlike\n * Array.slice, all arguments are required and may not be negative indices.\n * When feasible, a zero-copy subarray of a typed array is returned.\n * @param {number} start The starting index, inclusive\n * @param {number} end The ending index, exclusive\n * @returns {import('./types.js').ValueArray} The slice of values\n */\n slice(start2, end) {\n return this.nullCount ? super.slice(start2, end) : this.values.subarray(start2, end);\n }\n /**\n * Return an iterator over the values in this batch.\n * @returns {Iterator}\n */\n [Symbol.iterator]() {\n return this.nullCount ? super[Symbol.iterator]() : (\n /** @type {Iterator} */\n this.values[Symbol.iterator]()\n );\n }\n};\nvar NumberBatch = class extends Batch {\n static ArrayType = float64Array;\n};\nvar ArrayBatch = class extends Batch {\n static ArrayType = Array;\n};\nvar NullBatch = class extends ArrayBatch {\n /**\n * @param {number} index The value index\n * @returns {null}\n */\n value(index2) {\n return null;\n }\n};\nvar Int64Batch = class extends NumberBatch {\n /**\n * @param {number} index The value index\n */\n value(index2) {\n return toNumber(\n /** @type {bigint} */\n this.values[index2]\n );\n }\n};\nvar Float16Batch = class extends NumberBatch {\n /**\n * @param {number} index The value index\n */\n value(index2) {\n const v2 = (\n /** @type {number} */\n this.values[index2]\n );\n const expo = (v2 & 31744) >> 10;\n const sigf = (v2 & 1023) / 1024;\n const sign3 = (-1) ** ((v2 & 32768) >> 15);\n switch (expo) {\n case 31:\n return sign3 * (sigf ? Number.NaN : 1 / 0);\n case 0:\n return sign3 * (sigf ? 6103515625e-14 * sigf : 0);\n }\n return sign3 * 2 ** (expo - 15) * (1 + sigf);\n }\n};\nvar BoolBatch = class extends ArrayBatch {\n /**\n * @param {number} index The value index\n */\n value(index2) {\n return decodeBit(\n /** @type {Uint8Array} */\n this.values,\n index2\n );\n }\n};\nvar DecimalBatch = class extends Batch {\n constructor(options) {\n super(options);\n const { bitWidth, scale: scale3 } = (\n /** @type {import('./types.js').DecimalType} */\n this.type\n );\n this.decimal = bitWidth === 128 ? fromDecimal128 : fromDecimal256;\n this.scale = 10n ** BigInt(scale3);\n }\n};\nvar DecimalNumberBatch = class extends DecimalBatch {\n static ArrayType = float64Array;\n /**\n * @param {number} index The value index\n */\n value(index2) {\n return divide(\n this.decimal(\n /** @type {BigUint64Array} */\n this.values,\n index2\n ),\n this.scale\n );\n }\n};\nvar DecimalBigIntBatch = class extends DecimalBatch {\n static ArrayType = Array;\n /**\n * @param {number} index The value index\n */\n value(index2) {\n return this.decimal(\n /** @type {BigUint64Array} */\n this.values,\n index2\n );\n }\n};\nvar DateBatch = class extends ArrayBatch {\n /**\n * Create a new date batch.\n * @param {Batch} batch A batch of timestamp values.\n */\n constructor(batch) {\n super(batch);\n this.source = batch;\n }\n /**\n * @param {number} index The value index\n */\n value(index2) {\n return new Date(this.source.value(index2));\n }\n};\nvar DateDayBatch = class extends NumberBatch {\n /**\n * @param {number} index The value index\n * @returns {number}\n */\n value(index2) {\n return 864e5 * /** @type {number} */\n this.values[index2];\n }\n};\nvar DateDayMillisecondBatch = Int64Batch;\nvar TimestampSecondBatch = class extends Int64Batch {\n /**\n * @param {number} index The value index\n */\n value(index2) {\n return super.value(index2) * 1e3;\n }\n};\nvar TimestampMillisecondBatch = Int64Batch;\nvar TimestampMicrosecondBatch = class extends Int64Batch {\n /**\n * @param {number} index The value index\n */\n value(index2) {\n return divide(\n /** @type {bigint} */\n this.values[index2],\n 1000n\n );\n }\n};\nvar TimestampNanosecondBatch = class extends Int64Batch {\n /**\n * @param {number} index The value index\n */\n value(index2) {\n return divide(\n /** @type {bigint} */\n this.values[index2],\n 1000000n\n );\n }\n};\nvar IntervalDayTimeBatch = class extends ArrayBatch {\n /**\n * @param {number} index The value index\n * @returns {Int32Array}\n */\n value(index2) {\n const values2 = (\n /** @type {Int32Array} */\n this.values\n );\n return values2.subarray(index2 << 1, index2 + 1 << 1);\n }\n};\nvar IntervalMonthDayNanoBatch = class extends ArrayBatch {\n /**\n * @param {number} index The value index\n */\n value(index2) {\n const values2 = (\n /** @type {Uint8Array} */\n this.values\n );\n const base = index2 << 4;\n return Float64Array.of(\n readInt32(values2, base),\n readInt32(values2, base + 4),\n readInt64(values2, base + 8)\n );\n }\n};\nvar offset32 = ({ values: values2, offsets }, index2) => values2.subarray(offsets[index2], offsets[index2 + 1]);\nvar offset64 = ({ values: values2, offsets }, index2) => values2.subarray(toNumber(offsets[index2]), toNumber(offsets[index2 + 1]));\nvar BinaryBatch = class extends ArrayBatch {\n /**\n * @param {number} index\n * @returns {Uint8Array}\n */\n value(index2) {\n return offset32(this, index2);\n }\n};\nvar LargeBinaryBatch = class extends ArrayBatch {\n /**\n * @param {number} index\n * @returns {Uint8Array}\n */\n value(index2) {\n return offset64(this, index2);\n }\n};\nvar Utf8Batch = class extends ArrayBatch {\n /**\n * @param {number} index\n */\n value(index2) {\n return decodeUtf8(offset32(this, index2));\n }\n};\nvar LargeUtf8Batch = class extends ArrayBatch {\n /**\n * @param {number} index\n */\n value(index2) {\n return decodeUtf8(offset64(this, index2));\n }\n};\nvar ListBatch = class extends ArrayBatch {\n /**\n * @param {number} index\n * @returns {import('./types.js').ValueArray}\n */\n value(index2) {\n const offsets = (\n /** @type {Int32Array} */\n this.offsets\n );\n return this.children[0].slice(offsets[index2], offsets[index2 + 1]);\n }\n};\nvar LargeListBatch = class extends ArrayBatch {\n /**\n * @param {number} index\n * @returns {import('./types.js').ValueArray}\n */\n value(index2) {\n const offsets = (\n /** @type {BigInt64Array} */\n this.offsets\n );\n return this.children[0].slice(toNumber(offsets[index2]), toNumber(offsets[index2 + 1]));\n }\n};\nvar ListViewBatch = class extends ArrayBatch {\n /**\n * @param {number} index\n * @returns {import('./types.js').ValueArray}\n */\n value(index2) {\n const a2 = (\n /** @type {number} */\n this.offsets[index2]\n );\n const b = a2 + /** @type {number} */\n this.sizes[index2];\n return this.children[0].slice(a2, b);\n }\n};\nvar LargeListViewBatch = class extends ArrayBatch {\n /**\n * @param {number} index\n * @returns {import('./types.js').ValueArray}\n */\n value(index2) {\n const a2 = (\n /** @type {bigint} */\n this.offsets[index2]\n );\n const b = a2 + /** @type {bigint} */\n this.sizes[index2];\n return this.children[0].slice(toNumber(a2), toNumber(b));\n }\n};\nvar FixedBatch = class extends ArrayBatch {\n constructor(options) {\n super(options);\n this.stride = this.type.stride;\n }\n};\nvar FixedBinaryBatch = class extends FixedBatch {\n /**\n * @param {number} index\n * @returns {Uint8Array}\n */\n value(index2) {\n const { stride, values: values2 } = this;\n return (\n /** @type {Uint8Array} */\n values2.subarray(index2 * stride, (index2 + 1) * stride)\n );\n }\n};\nvar FixedListBatch = class extends FixedBatch {\n /**\n * @param {number} index\n * @returns {import('./types.js').ValueArray}\n */\n value(index2) {\n const { children: children2, stride } = this;\n return children2[0].slice(index2 * stride, (index2 + 1) * stride);\n }\n};\nfunction pairs({ children: children2, offsets }, index2) {\n const [keys, vals] = children2[0].children;\n const start2 = offsets[index2];\n const end = offsets[index2 + 1];\n const entries = [];\n for (let i = start2; i < end; ++i) {\n entries.push([keys.at(i), vals.at(i)]);\n }\n return entries;\n}\nvar MapEntryBatch = class extends ArrayBatch {\n /**\n * Return the value at the given index.\n * @param {number} index The value index.\n * @returns {[K, V][]} The map entries as an array of [key, value] arrays.\n */\n value(index2) {\n return (\n /** @type {[K, V][]} */\n pairs(this, index2)\n );\n }\n};\nvar MapBatch = class extends ArrayBatch {\n /**\n * Return the value at the given index.\n * @param {number} index The value index.\n * @returns {Map} The map value.\n */\n value(index2) {\n return new Map(\n /** @type {[K, V][]} */\n pairs(this, index2)\n );\n }\n};\nvar SparseUnionBatch = class extends ArrayBatch {\n /**\n * Create a new column batch.\n * @param {object} options\n * @param {number} options.length The length of the batch\n * @param {number} options.nullCount The null value count\n * @param {import('./types.js').DataType} options.type The data type.\n * @param {Uint8Array} [options.validity] Validity bitmap buffer\n * @param {Int32Array} [options.offsets] Offsets buffer\n * @param {Batch[]} options.children Children batches\n * @param {Int8Array} options.typeIds Union type ids buffer\n * @param {Record} options.map A typeId to children index map\n */\n constructor({ typeIds, ...options }) {\n super(options);\n this.typeIds = typeIds;\n this.typeMap = this.type.typeMap;\n }\n /**\n * @param {number} index The value index.\n */\n value(index2, offset2 = index2) {\n const { typeIds, children: children2, typeMap } = this;\n return children2[typeMap[typeIds[index2]]].at(offset2);\n }\n};\nvar DenseUnionBatch = class extends SparseUnionBatch {\n /**\n * @param {number} index The value index.\n */\n value(index2) {\n return super.value(\n index2,\n /** @type {number} */\n this.offsets[index2]\n );\n }\n};\nvar StructBatch = class extends ArrayBatch {\n constructor(options, factory = objectFactory) {\n super(options);\n this.names = this.type.children.map((child) => child.name);\n this.factory = factory(this.names, this.children);\n }\n /**\n * @param {number} index The value index.\n * @returns {Record}\n */\n value(index2) {\n return this.factory(index2);\n }\n};\nvar StructProxyBatch = class extends StructBatch {\n constructor(options) {\n super(options, proxyFactory);\n }\n};\nvar RunEndEncodedBatch = class extends ArrayBatch {\n /**\n * @param {number} index The value index.\n */\n value(index2) {\n const [{ values: runs }, vals] = this.children;\n return vals.at(\n bisect(\n /** @type {import('./types.js').IntegerArray} */\n runs,\n index2\n )\n );\n }\n};\nvar DictionaryBatch = class extends ArrayBatch {\n /**\n * Register the backing dictionary. Dictionaries are added\n * after batch creation as the complete dictionary may not\n * be finished across multiple record batches.\n * @param {import('./column.js').Column} dictionary\n * The dictionary of column values.\n */\n setDictionary(dictionary2) {\n this.dictionary = dictionary2;\n this.cache = dictionary2.cache();\n return this;\n }\n /**\n * @param {number} index The value index.\n */\n value(index2) {\n return this.cache[this.key(index2)];\n }\n /**\n * @param {number} index The value index.\n * @returns {number} The dictionary key\n */\n key(index2) {\n return (\n /** @type {number} */\n this.values[index2]\n );\n }\n};\nvar ViewBatch = class extends ArrayBatch {\n /**\n * Create a new view batch.\n * @param {object} options Batch options.\n * @param {number} options.length The length of the batch\n * @param {number} options.nullCount The null value count\n * @param {import('./types.js').DataType} options.type The data type.\n * @param {Uint8Array} [options.validity] Validity bitmap buffer\n * @param {Uint8Array} options.values Values buffer\n * @param {Uint8Array[]} options.data View data buffers\n */\n constructor({ data, ...options }) {\n super(options);\n this.data = data;\n }\n /**\n * Get the binary data at the provided index.\n * @param {number} index The value index.\n * @returns {Uint8Array}\n */\n view(index2) {\n const { values: values2, data } = this;\n const offset2 = index2 << 4;\n let start2 = offset2 + 4;\n let buf2 = (\n /** @type {Uint8Array} */\n values2\n );\n const length4 = readInt32(buf2, offset2);\n if (length4 > 12) {\n start2 = readInt32(buf2, offset2 + 12);\n buf2 = data[readInt32(buf2, offset2 + 8)];\n }\n return buf2.subarray(start2, start2 + length4);\n }\n};\nvar BinaryViewBatch = class extends ViewBatch {\n /**\n * @param {number} index The value index.\n */\n value(index2) {\n return this.view(index2);\n }\n};\nvar Utf8ViewBatch = class extends ViewBatch {\n /**\n * @param {number} index The value index.\n */\n value(index2) {\n return decodeUtf8(this.view(index2));\n }\n};\n\n// ../../node_modules/@uwdata/flechette/src/column.js\nfunction columnBuilder(type2) {\n let data = [];\n return {\n add(batch) {\n data.push(batch);\n return this;\n },\n clear: () => data = [],\n done: () => new Column(data, type2)\n };\n}\nvar Column = class {\n /**\n * Create a new column instance.\n * @param {import('./batch.js').Batch[]} data The value batches.\n * @param {import('./types.js').DataType} [type] The column data type.\n * If not specified, the type is extracted from the batches.\n */\n constructor(data, type2 = data[0]?.type) {\n this.type = type2;\n this.length = data.reduce((m, c4) => m + c4.length, 0);\n this.nullCount = data.reduce((m, c4) => m + c4.nullCount, 0);\n this.data = data;\n const n = data.length;\n const offsets = new Int32Array(n + 1);\n if (n === 1) {\n const [batch] = data;\n offsets[1] = batch.length;\n this.at = (index2) => batch.at(index2);\n } else {\n for (let i = 0, s2 = 0; i < n; ++i) {\n offsets[i + 1] = s2 += data[i].length;\n }\n }\n this.offsets = offsets;\n }\n /**\n * Provide an informative object string tag.\n */\n get [Symbol.toStringTag]() {\n return \"Column\";\n }\n /**\n * Return an iterator over the values in this column.\n * @returns {Iterator}\n */\n [Symbol.iterator]() {\n const data = this.data;\n return data.length === 1 ? data[0][Symbol.iterator]() : batchedIterator(data);\n }\n /**\n * Return the column value at the given index. If a column has multiple\n * batches, this method performs binary search over the batch lengths to\n * determine the batch from which to retrieve the value. The search makes\n * lookup less efficient than a standard array access. If making a full\n * scan of a column, consider extracting arrays via `toArray()` or using an\n * iterator (`for (const value of column) {...}`).\n * @param {number} index The row index.\n * @returns {T | null} The value.\n */\n at(index2) {\n const { data, offsets } = this;\n const i = bisect(offsets, index2) - 1;\n return data[i]?.at(index2 - offsets[i]);\n }\n /**\n * Return the column value at the given index. This method is the same as\n * `at()` and is provided for better compatibility with Apache Arrow JS.\n * @param {number} index The row index.\n * @returns {T | null} The value.\n */\n get(index2) {\n return this.at(index2);\n }\n /**\n * Extract column values into a single array instance. When possible,\n * a zero-copy subarray of the input Arrow data is returned.\n * @returns {import('./types.js').ValueArray}\n */\n toArray() {\n const { length: length4, nullCount, data } = this;\n const copy4 = !nullCount && isDirectBatch(data[0]);\n const n = data.length;\n if (copy4 && n === 1) {\n return data[0].values;\n }\n const ArrayType = !n || nullCount > 0 ? Array : data[0].constructor.ArrayType ?? data[0].values.constructor;\n const array4 = new ArrayType(length4);\n return copy4 ? copyArray(array4, data) : extractArray(array4, data);\n }\n /**\n * Return an array of cached column values.\n * Used internally to accelerate dictionary types.\n */\n cache() {\n return this._cache ?? (this._cache = this.toArray());\n }\n};\nfunction* batchedIterator(data) {\n for (let i = 0; i < data.length; ++i) {\n const iter = data[i][Symbol.iterator]();\n for (let next = iter.next(); !next.done; next = iter.next()) {\n yield next.value;\n }\n }\n}\nfunction copyArray(array4, data) {\n for (let i = 0, offset2 = 0; i < data.length; ++i) {\n const { values: values2 } = data[i];\n array4.set(values2, offset2);\n offset2 += values2.length;\n }\n return array4;\n}\nfunction extractArray(array4, data) {\n let index2 = -1;\n for (let i = 0; i < data.length; ++i) {\n const batch = data[i];\n for (let j = 0; j < batch.length; ++j) {\n array4[++index2] = batch.at(j);\n }\n }\n return array4;\n}\n\n// ../../node_modules/@uwdata/flechette/src/table.js\nvar Table = class _Table {\n /**\n * Create a new table with the given schema and columns (children).\n * @param {import('./types.js').Schema} schema The table schema.\n * @param {import('./column.js').Column[]} children The table columns.\n * @param {boolean} [useProxy=false] Flag indicating if row proxy\n * objects should be used to represent table rows (default `false`).\n */\n constructor(schema, children2, useProxy = false) {\n const names = schema.fields.map((f) => f.name);\n this.schema = schema;\n this.names = names;\n this.children = children2;\n this.factory = useProxy ? proxyFactory : objectFactory;\n const gen = [];\n this.getFactory = (b) => gen[b] ?? (gen[b] = this.factory(names, children2.map((c4) => c4.data[b])));\n }\n /**\n * Provide an informative object string tag.\n */\n get [Symbol.toStringTag]() {\n return \"Table\";\n }\n /**\n * The number of columns in this table.\n * @return {number} The number of columns.\n */\n get numCols() {\n return this.names.length;\n }\n /**\n * The number of rows in this table.\n * @return {number} The number of rows.\n */\n get numRows() {\n return this.children[0]?.length ?? 0;\n }\n /**\n * Return the child column at the given index position.\n * @param {number} index The column index.\n * @returns {import('./column.js').Column}\n */\n getChildAt(index2) {\n return this.children[index2];\n }\n /**\n * Return the first child column with the given name.\n * @param {string} name The column name.\n * @returns {import('./column.js').Column}\n */\n getChild(name2) {\n const i = this.names.findIndex((x3) => x3 === name2);\n return i > -1 ? this.children[i] : void 0;\n }\n /**\n * Construct a new table containing only columns at the specified indices.\n * The order of columns in the new table matches the order of input indices.\n * @param {number[]} indices The indices of columns to keep.\n * @param {string[]} [as] Optional new names for selected columns.\n * @returns {Table} A new table with columns at the specified indices.\n */\n selectAt(indices2, as = []) {\n const { children: children2, factory, schema } = this;\n const { fields } = schema;\n return new _Table(\n {\n ...schema,\n fields: indices2.map((i, j) => renameField(fields[i], as[j]))\n },\n indices2.map((i) => children2[i]),\n factory === proxyFactory\n );\n }\n /**\n * Construct a new table containing only columns with the specified names.\n * If columns have duplicate names, the first (with lowest index) is used.\n * The order of columns in the new table matches the order of input names.\n * @param {string[]} names Names of columns to keep.\n * @param {string[]} [as] Optional new names for selected columns.\n * @returns {Table} A new table with columns matching the specified names.\n */\n select(names, as) {\n const all2 = this.names;\n const indices2 = names.map((name2) => all2.indexOf(name2));\n return this.selectAt(indices2, as);\n }\n /**\n * Return an object mapping column names to extracted value arrays.\n * @returns {Record>}\n */\n toColumns() {\n const { children: children2, names } = this;\n const cols = {};\n names.forEach((name2, i) => cols[name2] = children2[i]?.toArray() ?? []);\n return cols;\n }\n /**\n * Return an array of objects representing the rows of this table.\n * @returns {Record[]}\n */\n toArray() {\n const { children: children2, getFactory, numRows } = this;\n const data = children2[0]?.data ?? [];\n const output = Array(numRows);\n for (let b = 0, row = -1; b < data.length; ++b) {\n const f = getFactory(b);\n for (let i = 0; i < data[b].length; ++i) {\n output[++row] = f(i);\n }\n }\n return output;\n }\n /**\n * Return an iterator over objects representing the rows of this table.\n * @returns {Generator, any, null>}\n */\n *[Symbol.iterator]() {\n const { children: children2, getFactory } = this;\n const data = children2[0]?.data ?? [];\n for (let b = 0; b < data.length; ++b) {\n const f = getFactory(b);\n for (let i = 0; i < data[b].length; ++i) {\n yield f(i);\n }\n }\n }\n /**\n * Return a row object for the given index.\n * @param {number} index The row index.\n * @returns {Record} The row object.\n */\n at(index2) {\n const { children: children2, getFactory, numRows } = this;\n if (index2 < 0 || index2 >= numRows) return null;\n const [{ offsets }] = children2;\n const b = bisect(offsets, index2) - 1;\n return getFactory(b)(index2 - offsets[b]);\n }\n /**\n * Return a row object for the given index. This method is the same as\n * `at()` and is provided for better compatibility with Apache Arrow JS.\n * @param {number} index The row index.\n * @returns {Record} The row object.\n */\n get(index2) {\n return this.at(index2);\n }\n};\nfunction renameField(field3, name2) {\n return name2 != null && name2 !== field3.name ? { ...field3, name: name2 } : field3;\n}\n\n// ../../node_modules/@uwdata/flechette/src/batch-type.js\nfunction batchType(type2, options = {}) {\n const { typeId, bitWidth, precision, unit: unit3 } = type2;\n const { useBigInt, useDate, useDecimalBigInt, useMap, useProxy } = options;\n switch (typeId) {\n case Type.Null:\n return NullBatch;\n case Type.Bool:\n return BoolBatch;\n case Type.Int:\n case Type.Time:\n case Type.Duration:\n return useBigInt || bitWidth < 64 ? DirectBatch : Int64Batch;\n case Type.Float:\n return precision ? DirectBatch : Float16Batch;\n case Type.Date:\n return wrap(\n unit3 === DateUnit.DAY ? DateDayBatch : DateDayMillisecondBatch,\n useDate && DateBatch\n );\n case Type.Timestamp:\n return wrap(\n unit3 === TimeUnit.SECOND ? TimestampSecondBatch : unit3 === TimeUnit.MILLISECOND ? TimestampMillisecondBatch : unit3 === TimeUnit.MICROSECOND ? TimestampMicrosecondBatch : TimestampNanosecondBatch,\n useDate && DateBatch\n );\n case Type.Decimal:\n return useDecimalBigInt ? DecimalBigIntBatch : DecimalNumberBatch;\n case Type.Interval:\n return unit3 === IntervalUnit.DAY_TIME ? IntervalDayTimeBatch : unit3 === IntervalUnit.YEAR_MONTH ? DirectBatch : IntervalMonthDayNanoBatch;\n case Type.FixedSizeBinary:\n return FixedBinaryBatch;\n case Type.Utf8:\n return Utf8Batch;\n case Type.LargeUtf8:\n return LargeUtf8Batch;\n case Type.Binary:\n return BinaryBatch;\n case Type.LargeBinary:\n return LargeBinaryBatch;\n case Type.BinaryView:\n return BinaryViewBatch;\n case Type.Utf8View:\n return Utf8ViewBatch;\n case Type.List:\n return ListBatch;\n case Type.LargeList:\n return LargeListBatch;\n case Type.Map:\n return useMap ? MapBatch : MapEntryBatch;\n case Type.ListView:\n return ListViewBatch;\n case Type.LargeListView:\n return LargeListViewBatch;\n case Type.FixedSizeList:\n return FixedListBatch;\n case Type.Struct:\n return useProxy ? StructProxyBatch : StructBatch;\n case Type.RunEndEncoded:\n return RunEndEncodedBatch;\n case Type.Dictionary:\n return DictionaryBatch;\n case Type.Union:\n return type2.mode ? DenseUnionBatch : SparseUnionBatch;\n }\n throw new Error(invalidDataType(typeId));\n}\nfunction wrap(BaseClass, WrapperClass) {\n return WrapperClass ? class WrapBatch extends WrapperClass {\n constructor(options) {\n super(new BaseClass(options));\n }\n } : BaseClass;\n}\n\n// ../../node_modules/@uwdata/flechette/src/decode/block.js\nfunction decodeBlock(buf2, index2) {\n return {\n offset: readInt64(buf2, index2),\n metadataLength: readInt32(buf2, index2 + 8),\n bodyLength: readInt64(buf2, index2 + 16)\n };\n}\nfunction decodeBlocks(buf2, index2) {\n return readVector(buf2, index2, 24, decodeBlock);\n}\n\n// ../../node_modules/@uwdata/flechette/src/decode/record-batch.js\nfunction decodeRecordBatch(buf2, index2, version) {\n const get3 = readObject(buf2, index2);\n if (get3(10, readOffset, 0)) {\n throw new Error(\"Record batch compression not implemented\");\n }\n const offset2 = version < Version.V4 ? 8 : 0;\n return {\n length: get3(4, readInt64, 0),\n nodes: readVector(buf2, get3(6, readOffset), 16, (buf3, pos) => ({\n length: readInt64(buf3, pos),\n nullCount: readInt64(buf3, pos + 8)\n })),\n regions: readVector(buf2, get3(8, readOffset), 16 + offset2, (buf3, pos) => ({\n offset: readInt64(buf3, pos + offset2),\n length: readInt64(buf3, pos + offset2 + 8)\n })),\n variadic: readVector(buf2, get3(12, readOffset), 8, readInt64)\n };\n}\n\n// ../../node_modules/@uwdata/flechette/src/decode/dictionary-batch.js\nfunction decodeDictionaryBatch(buf2, index2, version) {\n const get3 = readObject(buf2, index2);\n return {\n id: get3(4, readInt64, 0),\n data: get3(6, (buf3, off) => decodeRecordBatch(buf3, off, version)),\n /**\n * If isDelta is true the values in the dictionary are to be appended to a\n * dictionary with the indicated id. If isDelta is false this dictionary\n * should replace the existing dictionary.\n */\n isDelta: get3(8, readBoolean, false)\n };\n}\n\n// ../../node_modules/@uwdata/flechette/src/decode/data-type.js\nfunction decodeDataType(buf2, index2, typeId, children2) {\n checkOneOf(typeId, Type, invalidDataType);\n const get3 = readObject(buf2, index2);\n switch (typeId) {\n // types without flatbuffer objects\n case Type.Binary:\n return binary();\n case Type.Utf8:\n return utf8();\n case Type.LargeBinary:\n return largeBinary();\n case Type.LargeUtf8:\n return largeUtf8();\n case Type.List:\n return list(children2[0]);\n case Type.ListView:\n return listView(children2[0]);\n case Type.LargeList:\n return largeList(children2[0]);\n case Type.LargeListView:\n return largeListView(children2[0]);\n case Type.Struct:\n return struct(children2);\n case Type.RunEndEncoded:\n return runEndEncoded(children2[0], children2[1]);\n // types with flatbuffer objects\n case Type.Int:\n return int(\n // @ts-ignore\n get3(4, readInt32, 0),\n // bitwidth\n get3(6, readBoolean, false)\n // signed\n );\n case Type.Float:\n return float(\n // @ts-ignore\n get3(4, readInt16, Precision.HALF)\n // precision\n );\n case Type.Decimal:\n return decimal(\n get3(4, readInt32, 0),\n // precision\n get3(6, readInt32, 0),\n // scale\n // @ts-ignore\n get3(8, readInt32, 128)\n // bitwidth\n );\n case Type.Date:\n return date(\n // @ts-ignore\n get3(4, readInt16, DateUnit.MILLISECOND)\n // unit\n );\n case Type.Time:\n return time(\n // @ts-ignore\n get3(4, readInt16, TimeUnit.MILLISECOND),\n // unit\n get3(6, readInt32, 32)\n // bitWidth\n );\n case Type.Timestamp:\n return timestamp(\n // @ts-ignore\n get3(4, readInt16, TimeUnit.SECOND),\n // unit\n get3(6, readString)\n // timezone\n );\n case Type.Interval:\n return interval(\n // @ts-ignore\n get3(4, readInt16, IntervalUnit.YEAR_MONTH)\n // unit\n );\n case Type.Duration:\n return duration(\n // @ts-ignore\n get3(4, readInt16, TimeUnit.MILLISECOND)\n // unit\n );\n case Type.FixedSizeBinary:\n return fixedSizeBinary(\n get3(4, readInt32, 0)\n // stride\n );\n case Type.FixedSizeList:\n return fixedSizeList(\n children2[0],\n get3(4, readInt32, 0)\n // stride\n );\n case Type.Map:\n return mapType(\n get3(4, readBoolean, false),\n // keysSorted\n children2[0]\n );\n case Type.Union:\n return union(\n // @ts-ignore\n get3(4, readInt16, UnionMode.Sparse),\n // mode\n children2,\n readVector(buf2, get3(6, readOffset), 4, readInt32)\n // type ids\n );\n }\n return { typeId };\n}\n\n// ../../node_modules/@uwdata/flechette/src/decode/metadata.js\nfunction decodeMetadata(buf2, index2) {\n const entries = readVector(buf2, index2, 4, (buf3, pos) => {\n const get3 = readObject(buf3, pos);\n return (\n /** @type {[string, string]} */\n [\n get3(4, readString),\n // 4: key (string)\n get3(6, readString)\n // 6: key (string)\n ]\n );\n });\n return entries.length ? new Map(entries) : null;\n}\n\n// ../../node_modules/@uwdata/flechette/src/decode/schema.js\nfunction decodeSchema(buf2, index2, version) {\n const get3 = readObject(buf2, index2);\n return {\n version,\n endianness: (\n /** @type {import('../types.js').Endianness_} */\n get3(4, readInt16, 0)\n ),\n fields: get3(6, decodeSchemaFields, []),\n metadata: get3(8, decodeMetadata)\n };\n}\nfunction decodeSchemaFields(buf2, fieldsOffset) {\n return readVector(buf2, fieldsOffset, 4, decodeField);\n}\nfunction decodeField(buf2, index2) {\n const get3 = readObject(buf2, index2);\n const typeId = get3(8, readUint8, Type.NONE);\n const typeOffset = get3(10, readOffset, 0);\n const dict = get3(12, decodeDictionary);\n const children2 = get3(14, (buf3, off) => decodeFieldChildren(buf3, off));\n let type2 = decodeDataType(buf2, typeOffset, typeId, children2);\n if (dict) {\n dict.dictionary = type2;\n type2 = dict;\n }\n return {\n name: get3(4, readString),\n type: type2,\n nullable: get3(6, readBoolean, false),\n metadata: get3(16, decodeMetadata)\n };\n}\nfunction decodeFieldChildren(buf2, fieldOffset) {\n const children2 = readVector(buf2, fieldOffset, 4, decodeField);\n return children2.length ? children2 : null;\n}\nfunction decodeDictionary(buf2, index2) {\n if (!index2) return null;\n const get3 = readObject(buf2, index2);\n return dictionary(\n null,\n // data type will be populated by caller\n get3(6, decodeInt, int32()),\n // index type\n get3(8, readBoolean, false),\n // ordered\n get3(4, readInt64, 0)\n // id\n );\n}\nfunction decodeInt(buf2, index2) {\n return (\n /** @type {import('../types.js').IntType} */\n decodeDataType(buf2, index2, Type.Int)\n );\n}\n\n// ../../node_modules/@uwdata/flechette/src/decode/message.js\nvar invalidMessageMetadata = (expected, actual) => `Expected to read ${expected} metadata bytes, but only read ${actual}.`;\nvar invalidMessageBodyLength = (expected, actual) => `Expected to read ${expected} bytes for message body, but only read ${actual}.`;\nvar invalidMessageType = (type2) => `Unsupported message type: ${type2} (${keyFor(MessageHeader, type2)})`;\nfunction decodeMessage(buf2, index2) {\n let metadataLength = readInt32(buf2, index2) || 0;\n index2 += SIZEOF_INT;\n if (metadataLength === -1) {\n metadataLength = readInt32(buf2, index2) || 0;\n index2 += SIZEOF_INT;\n }\n if (metadataLength === 0) return null;\n const head = buf2.subarray(index2, index2 += metadataLength);\n if (head.byteLength < metadataLength) {\n throw new Error(invalidMessageMetadata(metadataLength, head.byteLength));\n }\n const get3 = readObject(head, 0);\n const version = (\n /** @type {import('../types.js').Version_} */\n get3(4, readInt16, Version.V1)\n );\n const type2 = (\n /** @type {import('../types.js').MessageHeader_} */\n get3(6, readUint8, MessageHeader.NONE)\n );\n const offset2 = get3(8, readOffset, 0);\n const bodyLength = get3(10, readInt64, 0);\n let content;\n if (offset2) {\n const decoder = type2 === MessageHeader.Schema ? decodeSchema : type2 === MessageHeader.DictionaryBatch ? decodeDictionaryBatch : type2 === MessageHeader.RecordBatch ? decodeRecordBatch : null;\n if (!decoder) throw new Error(invalidMessageType(type2));\n content = decoder(head, offset2, version);\n if (bodyLength > 0) {\n const body = buf2.subarray(index2, index2 += bodyLength);\n if (body.byteLength < bodyLength) {\n throw new Error(invalidMessageBodyLength(bodyLength, body.byteLength));\n }\n content.body = body;\n }\n }\n return { version, type: type2, index: index2, content };\n}\n\n// ../../node_modules/@uwdata/flechette/src/decode/decode-ipc.js\nfunction decodeIPC(data) {\n const source = data instanceof ArrayBuffer ? new Uint8Array(data) : data;\n return source instanceof Uint8Array && isArrowFileFormat(source) ? decodeIPCFile(source) : decodeIPCStream(source);\n}\nfunction isArrowFileFormat(buf2) {\n if (!buf2 || buf2.length < 4) return false;\n for (let i = 0; i < 6; ++i) {\n if (MAGIC[i] !== buf2[i]) return false;\n }\n return true;\n}\nfunction decodeIPCStream(data) {\n const stream = [data].flat();\n let schema;\n const records = [];\n const dictionaries = [];\n for (const buf2 of stream) {\n if (!(buf2 instanceof Uint8Array)) {\n throw new Error(`IPC data batch was not a Uint8Array.`);\n }\n let offset2 = 0;\n while (true) {\n const m = decodeMessage(buf2, offset2);\n if (m === null) break;\n offset2 = m.index;\n if (!m.content) continue;\n switch (m.type) {\n case MessageHeader.Schema:\n if (!schema) schema = m.content;\n break;\n case MessageHeader.RecordBatch:\n records.push(m.content);\n break;\n case MessageHeader.DictionaryBatch:\n dictionaries.push(m.content);\n break;\n }\n }\n }\n return (\n /** @type {import('../types.js').ArrowData} */\n { schema, dictionaries, records, metadata: null }\n );\n}\nfunction decodeIPCFile(data) {\n const offset2 = data.byteLength - (MAGIC.length + 4);\n const length4 = readInt32(data, offset2);\n const get3 = readObject(data, offset2 - length4);\n const version = (\n /** @type {import('../types.js').Version_} */\n get3(4, readInt16, Version.V1)\n );\n const dicts = get3(8, decodeBlocks, []);\n const recs = get3(10, decodeBlocks, []);\n return (\n /** @type {import('../types.js').ArrowData} */\n {\n schema: get3(6, (buf2, index2) => decodeSchema(buf2, index2, version)),\n dictionaries: dicts.map(({ offset: offset3 }) => decodeMessage(data, offset3).content),\n records: recs.map(({ offset: offset3 }) => decodeMessage(data, offset3).content),\n metadata: get3(12, decodeMetadata)\n }\n );\n}\n\n// ../../node_modules/@uwdata/flechette/src/decode/table-from-ipc.js\nfunction tableFromIPC(data, options) {\n return createTable(decodeIPC(data), options);\n}\nfunction createTable(data, options = {}) {\n const { schema = { fields: [] }, dictionaries, records } = data;\n const { version, fields } = schema;\n const dictionaryMap = /* @__PURE__ */ new Map();\n const context = contextGenerator(options, version, dictionaryMap);\n const dictionaryTypes = /* @__PURE__ */ new Map();\n visitSchemaFields(schema, (field3) => {\n const type2 = field3.type;\n if (type2.typeId === Type.Dictionary) {\n dictionaryTypes.set(type2.id, type2.dictionary);\n }\n });\n const dicts = /* @__PURE__ */ new Map();\n for (const dict of dictionaries) {\n const { id: id2, data: data2, isDelta, body } = dict;\n const type2 = dictionaryTypes.get(id2);\n const batch = visit(type2, context({ ...data2, body }));\n if (!dicts.has(id2)) {\n if (isDelta) {\n throw new Error(\"Delta update can not be first dictionary batch.\");\n }\n dicts.set(id2, columnBuilder(type2).add(batch));\n } else {\n const dict2 = dicts.get(id2);\n if (!isDelta) dict2.clear();\n dict2.add(batch);\n }\n }\n dicts.forEach((value, key) => dictionaryMap.set(key, value.done()));\n const cols = fields.map((f) => columnBuilder(f.type));\n for (const batch of records) {\n const ctx = context(batch);\n fields.forEach((f, i) => cols[i].add(visit(f.type, ctx)));\n }\n return new Table(schema, cols.map((c4) => c4.done()), options.useProxy);\n}\nfunction visitSchemaFields(schema, visitor) {\n schema.fields.forEach(function visitField(field3) {\n visitor(field3);\n field3.type.dictionary?.children?.forEach(visitField);\n field3.type.children?.forEach(visitField);\n });\n}\nfunction contextGenerator(options, version, dictionaryMap) {\n const base = {\n version,\n options,\n dictionary: (id2) => dictionaryMap.get(id2)\n };\n return (batch) => {\n const { length: length4, nodes, regions, variadic, body } = batch;\n let nodeIndex = -1;\n let bufferIndex = -1;\n let variadicIndex = -1;\n return {\n ...base,\n length: length4,\n node: () => nodes[++nodeIndex],\n buffer: (ArrayType) => {\n const { length: length5, offset: offset2 } = regions[++bufferIndex];\n return ArrayType ? new ArrayType(body.buffer, body.byteOffset + offset2, length5 / ArrayType.BYTES_PER_ELEMENT) : body.subarray(offset2, offset2 + length5);\n },\n variadic: () => variadic[++variadicIndex],\n visit(children2) {\n return children2.map((f) => visit(f.type, this));\n }\n };\n };\n}\nfunction visit(type2, ctx) {\n const { typeId } = type2;\n const { length: length4, options, node, buffer: buffer2, variadic, version } = ctx;\n const BatchType = batchType(type2, options);\n if (typeId === Type.Null) {\n return new BatchType({ length: length4, nullCount: length4, type: type2 });\n }\n const base = { ...node(), type: type2 };\n switch (typeId) {\n // validity and data value buffers\n case Type.Bool:\n case Type.Int:\n case Type.Time:\n case Type.Duration:\n case Type.Float:\n case Type.Decimal:\n case Type.Date:\n case Type.Timestamp:\n case Type.Interval:\n case Type.FixedSizeBinary:\n return new BatchType({\n ...base,\n validity: buffer2(),\n values: buffer2(type2.values)\n });\n // validity, offset, and value buffers\n case Type.Utf8:\n case Type.LargeUtf8:\n case Type.Binary:\n case Type.LargeBinary:\n return new BatchType({\n ...base,\n validity: buffer2(),\n offsets: buffer2(type2.offsets),\n values: buffer2()\n });\n // views with variadic buffers\n case Type.BinaryView:\n case Type.Utf8View:\n return new BatchType({\n ...base,\n validity: buffer2(),\n values: buffer2(),\n // views buffer\n data: Array.from({ length: variadic() }, () => buffer2())\n // data buffers\n });\n // validity, offset, and list child\n case Type.List:\n case Type.LargeList:\n case Type.Map:\n return new BatchType({\n ...base,\n validity: buffer2(),\n offsets: buffer2(type2.offsets),\n children: ctx.visit(type2.children)\n });\n // validity, offset, size, and list child\n case Type.ListView:\n case Type.LargeListView:\n return new BatchType({\n ...base,\n validity: buffer2(),\n offsets: buffer2(type2.offsets),\n sizes: buffer2(type2.offsets),\n children: ctx.visit(type2.children)\n });\n // validity and children\n case Type.FixedSizeList:\n case Type.Struct:\n return new BatchType({\n ...base,\n validity: buffer2(),\n children: ctx.visit(type2.children)\n });\n // children only\n case Type.RunEndEncoded:\n return new BatchType({\n ...base,\n children: ctx.visit(type2.children)\n });\n // dictionary\n case Type.Dictionary: {\n const { id: id2, indices: indices2 } = type2;\n return new BatchType({\n ...base,\n validity: buffer2(),\n values: buffer2(indices2.values)\n }).setDictionary(ctx.dictionary(id2));\n }\n // union\n case Type.Union: {\n if (version < Version.V5) {\n buffer2();\n }\n return new BatchType({\n ...base,\n typeIds: buffer2(int8Array),\n offsets: type2.mode === UnionMode.Sparse ? null : buffer2(type2.offsets),\n children: ctx.visit(type2.children)\n });\n }\n // unsupported type\n default:\n throw new Error(invalidDataType(typeId));\n }\n}\n\n// ../../node_modules/@uwdata/flechette/src/encode/schema.js\nvar isLittleEndian = new Uint16Array(new Uint8Array([1, 0]).buffer)[0] === 1;\n\n// ../core/src/util/decode-ipc.js\nfunction decodeIPC2(data) {\n return tableFromIPC(data, { useDate: true });\n}\n\n// ../core/src/connectors/socket.js\nfunction socketConnector(uri = \"ws://localhost:3000/\") {\n const queue = [];\n let connected = false;\n let request = null;\n let ws;\n const events = {\n open() {\n connected = true;\n next();\n },\n close() {\n connected = false;\n request = null;\n ws = null;\n while (queue.length) {\n queue.shift().reject(\"Socket closed\");\n }\n },\n error(event) {\n if (request) {\n const { reject } = request;\n request = null;\n next();\n reject(event);\n } else {\n console.error(\"WebSocket error: \", event);\n }\n },\n message({ data }) {\n if (request) {\n const { query, resolve, reject } = request;\n request = null;\n next();\n if (typeof data === \"string\") {\n const json = JSON.parse(data);\n json.error ? reject(json.error) : resolve(json);\n } else if (query.type === \"exec\") {\n resolve();\n } else if (query.type === \"arrow\") {\n resolve(decodeIPC2(data));\n } else {\n throw new Error(`Unexpected socket data: ${data}`);\n }\n } else {\n console.log(\"WebSocket message: \", data);\n }\n }\n };\n function init2() {\n ws = new WebSocket(uri);\n ws.binaryType = \"arraybuffer\";\n for (const type2 in events) {\n ws.addEventListener(type2, events[type2]);\n }\n }\n function enqueue(query, resolve, reject) {\n if (ws == null) init2();\n queue.push({ query, resolve, reject });\n if (connected && !request) next();\n }\n function next() {\n if (queue.length) {\n request = queue.shift();\n ws.send(JSON.stringify(request.query));\n }\n }\n return {\n get connected() {\n return connected;\n },\n /**\n * Query the DuckDB server.\n * @param {object} query\n * @param {'exec' | 'arrow' | 'json' | 'create-bundle' | 'load-bundle'} [query.type] The query type.\n * @param {string} query.sql A SQL query string.\n * @returns the query result\n */\n query(query) {\n return new Promise(\n (resolve, reject) => enqueue(query, resolve, reject)\n );\n }\n };\n}\n\n// ../sql/src/ref.js\nvar Ref = class {\n /**\n * Create a new Ref instance.\n * @param {string|Ref|null} table The table name.\n * @param {string|null} [column] The column name.\n */\n constructor(table3, column3) {\n if (table3) this.table = String(table3);\n if (column3) this.column = column3;\n }\n /**\n * Get the list of referenced columns. Either a single element array\n * if column is non-null, otherwise an empty array.\n */\n get columns() {\n return this.column ? [this.column] : [];\n }\n /**\n * Generate a SQL string for this reference.\n * @returns {string} The SQL string.\n */\n toString() {\n const { table: table3, column: column3 } = this;\n if (column3) {\n const col = column3.startsWith(\"*\") ? column3 : `\"${column3}\"`;\n return `${table3 ? `${quoteTableName(table3)}.` : \"\"}${col}`;\n } else {\n return table3 ? quoteTableName(table3) : \"NULL\";\n }\n }\n};\nfunction quoteTableName(table3) {\n const pieces = table3.split(\".\");\n return pieces.map((p) => `\"${p}\"`).join(\".\");\n}\nfunction isColumnRefFor(ref, name2) {\n return ref instanceof Ref && ref.column === name2;\n}\nfunction asColumn(value) {\n return typeof value === \"string\" ? column(value) : value;\n}\nfunction asRelation(value) {\n return typeof value === \"string\" ? relation(value) : value;\n}\nfunction relation(name2) {\n return new Ref(name2);\n}\nfunction column(table3, column3 = null) {\n if (arguments.length === 1) {\n column3 = table3;\n table3 = null;\n }\n return new Ref(table3, column3);\n}\n\n// ../sql/src/to-sql.js\nfunction literalToSQL(value) {\n switch (typeof value) {\n case \"boolean\":\n return value ? \"TRUE\" : \"FALSE\";\n case \"string\":\n return `'${value.replace(`'`, `''`)}'`;\n case \"number\":\n return Number.isFinite(value) ? String(value) : \"NULL\";\n default:\n if (value == null) {\n return \"NULL\";\n } else if (value instanceof Date) {\n const ts = +value;\n if (Number.isNaN(ts)) return \"NULL\";\n const y3 = value.getUTCFullYear();\n const m = value.getUTCMonth();\n const d = value.getUTCDate();\n return ts === Date.UTC(y3, m, d) ? `MAKE_DATE(${y3}, ${m + 1}, ${d})` : `EPOCH_MS(${ts})`;\n } else if (value instanceof RegExp) {\n return `'${value.source}'`;\n } else {\n return String(value);\n }\n }\n}\n\n// ../sql/src/expression.js\nvar isParamLike = (value) => typeof value?.addEventListener === \"function\";\nfunction isSQLExpression(value) {\n return value instanceof SQLExpression;\n}\nvar SQLExpression = class {\n /**\n * Create a new SQL expression instance.\n * @param {(string | ParamLike | SQLExpression | import('./ref.js').Ref)[]} parts The parts of the expression.\n * @param {string[]} [columns=[]] The column dependencies\n * @param {object} [props] Additional properties for this expression.\n */\n constructor(parts, columns, props) {\n this._expr = Array.isArray(parts) ? parts : [parts];\n this._deps = columns || [];\n this.annotate(props);\n const params = this._expr.filter((part) => isParamLike(part));\n if (params.length > 0) {\n this._params = Array.from(new Set(params));\n this._params.forEach((param) => {\n param.addEventListener(\"value\", () => update(this, this.map?.get(\"value\")));\n });\n } else {\n this.addEventListener = void 0;\n }\n }\n /**\n * A reference to this expression.\n * Provides compatibility with param-like objects.\n */\n get value() {\n return this;\n }\n /**\n * The column dependencies of this expression.\n * @returns {string[]} The columns dependencies.\n */\n get columns() {\n const { _params, _deps } = this;\n if (_params) {\n const pset = new Set(_params.flatMap((p) => {\n const cols = p.value?.columns;\n return Array.isArray(cols) ? cols : [];\n }));\n if (pset.size) {\n const set3 = new Set(_deps);\n pset.forEach((col) => set3.add(col));\n return Array.from(set3);\n }\n }\n return _deps;\n }\n /**\n * The first column dependency in this expression, or undefined if none.\n * @returns {string} The first column dependency.\n */\n get column() {\n return this._deps.length ? this._deps[0] : this.columns[0];\n }\n /**\n * Annotate this expression instance with additional properties.\n * @param {object[]} [props] One or more objects with properties to add.\n * @returns This SQL expression.\n */\n annotate(...props) {\n return Object.assign(this, ...props);\n }\n /**\n * Generate a SQL code string corresponding to this expression.\n * @returns {string} A SQL code string.\n */\n toString() {\n return this._expr.map((p) => isParamLike(p) && !isSQLExpression(p) ? literalToSQL(p.value) : p).join(\"\");\n }\n /**\n * Add an event listener callback for the provided event type.\n * @param {string} type The event type to listen for (for example, \"value\").\n * @param {(a: SQLExpression) => Promise?} callback The callback function to\n * invoke upon updates. A callback may optionally return a Promise that\n * upstream listeners may await before proceeding.\n */\n addEventListener(type2, callback) {\n const map5 = this.map || (this.map = /* @__PURE__ */ new Map());\n const set3 = map5.get(type2) || (map5.set(type2, /* @__PURE__ */ new Set()), map5.get(type2));\n set3.add(callback);\n }\n};\nfunction update(expr, callbacks) {\n if (callbacks?.size) {\n return Promise.allSettled(Array.from(callbacks, (fn) => fn(expr)));\n }\n}\nfunction parseSQL(strings, exprs) {\n const spans = [strings[0]];\n const cols = /* @__PURE__ */ new Set();\n const n = exprs.length;\n for (let i = 0, k2 = 0; i < n; ) {\n const e = exprs[i];\n if (isParamLike(e)) {\n spans[++k2] = e;\n } else {\n if (Array.isArray(e?.columns)) {\n e.columns.forEach((col) => cols.add(col));\n }\n spans[k2] += typeof e === \"string\" ? e : literalToSQL(e);\n }\n const s2 = strings[++i];\n if (isParamLike(spans[k2])) {\n spans[++k2] = s2;\n } else {\n spans[k2] += s2;\n }\n }\n return { spans, cols: Array.from(cols) };\n}\nfunction sql(strings, ...exprs) {\n const { spans, cols } = parseSQL(strings, exprs);\n return new SQLExpression(spans, cols);\n}\n\n// ../sql/src/desc.js\nfunction desc(expr) {\n const e = asColumn(expr);\n return sql`${e} DESC NULLS LAST`.annotate({ label: e?.label, desc: true });\n}\n\n// ../sql/src/literal.js\nvar literal = (value) => ({\n value,\n toString: () => literalToSQL(value)\n});\n\n// ../sql/src/operators.js\nfunction visit2(callback) {\n callback(this.op, this);\n this.children?.forEach((v2) => v2.visit(callback));\n}\nfunction logical(op, clauses) {\n const children2 = clauses.filter((x3) => x3 != null).map(asColumn);\n const strings = children2.map((c4, i) => i ? ` ${op} ` : \"\");\n if (children2.length === 1) {\n strings.push(\"\");\n } else if (children2.length > 1) {\n strings[0] = \"(\";\n strings.push(\")\");\n }\n return sql(strings, ...children2).annotate({ op, children: children2, visit: visit2 });\n}\nvar and = (...clauses) => logical(\"AND\", clauses.flat());\nvar or = (...clauses) => logical(\"OR\", clauses.flat());\nvar unaryOp = (op) => (a2) => sql`(${op} ${asColumn(a2)})`.annotate({ op, a: a2, visit: visit2 });\nvar not = unaryOp(\"NOT\");\nvar unaryPostOp = (op) => (a2) => sql`(${asColumn(a2)} ${op})`.annotate({ op, a: a2, visit: visit2 });\nvar isNull = unaryPostOp(\"IS NULL\");\nvar isNotNull = unaryPostOp(\"IS NOT NULL\");\nvar binaryOp = (op) => (a2, b) => sql`(${asColumn(a2)} ${op} ${asColumn(b)})`.annotate({ op, a: a2, b, visit: visit2 });\nvar eq = binaryOp(\"=\");\nvar neq = binaryOp(\"<>\");\nvar lt = binaryOp(\"<\");\nvar gt = binaryOp(\">\");\nvar lte = binaryOp(\"<=\");\nvar gte = binaryOp(\">=\");\nvar isDistinct = binaryOp(\"IS DISTINCT FROM\");\nvar isNotDistinct = binaryOp(\"IS NOT DISTINCT FROM\");\nfunction rangeOp(op, a2, range3, exclusive) {\n a2 = asColumn(a2);\n const prefix2 = op.startsWith(\"NOT \") ? \"NOT \" : \"\";\n const expr = !range3 ? sql`` : exclusive ? sql`${prefix2}(${range3[0]} <= ${a2} AND ${a2} < ${range3[1]})` : sql`(${a2} ${op} ${range3[0]} AND ${range3[1]})`;\n return expr.annotate({ op, visit: visit2, field: a2, range: range3 });\n}\nvar isBetween = (a2, range3, exclusive) => rangeOp(\"BETWEEN\", a2, range3, exclusive);\nvar isNotBetween = (a2, range3, exclusive) => rangeOp(\"NOT BETWEEN\", a2, range3, exclusive);\n\n// ../sql/src/repeat.js\nfunction repeat(length4, str) {\n return Array.from({ length: length4 }, () => str);\n}\n\n// ../sql/src/functions.js\nfunction functionCall(op, type2) {\n return (...values2) => {\n const args = values2.map(asColumn);\n const cast2 = type2 ? `::${type2}` : \"\";\n const expr = args.length ? sql([`${op}(`, ...repeat(args.length - 1, \", \"), `)${cast2}`], ...args) : sql`${op}()${cast2}`;\n return expr.annotate({ func: op, args });\n };\n}\nvar regexp_matches = functionCall(\"REGEXP_MATCHES\");\nvar contains = functionCall(\"CONTAINS\");\nvar prefix = functionCall(\"PREFIX\");\nvar suffix = functionCall(\"SUFFIX\");\nvar lower = functionCall(\"LOWER\");\nvar upper = functionCall(\"UPPER\");\nvar length = functionCall(\"LENGTH\");\nvar isNaN2 = functionCall(\"ISNAN\");\nvar isFinite2 = functionCall(\"ISFINITE\");\nvar isInfinite = functionCall(\"ISINF\");\n\n// ../sql/src/windows.js\nvar WindowFunction = class _WindowFunction extends SQLExpression {\n /**\n * Create a new WindowFunction instance.\n * @param {string} op The window operation indicator.\n * @param {*} func The window function expression.\n * @param {*} [type] The SQL data type to cast to.\n * @param {string} [name] The window definition name.\n * @param {*} [group] Grouping (partition by) expressions.\n * @param {*} [order] Sorting (order by) expressions.\n * @param {*} [frame] The window frame definition.\n */\n constructor(op, func, type2, name2, group3 = \"\", order = \"\", frame4 = \"\") {\n let expr;\n const noWindowParams = !(group3 || order || frame4);\n if (name2 && noWindowParams) {\n expr = name2 ? sql`${func} OVER \"${name2}\"` : sql`${func} OVER ()`;\n } else {\n const s1 = group3 && order ? \" \" : \"\";\n const s2 = (group3 || order) && frame4 ? \" \" : \"\";\n expr = sql`${func} OVER (${name2 ? `\"${name2}\" ` : \"\"}${group3}${s1}${order}${s2}${frame4})`;\n }\n if (type2) {\n expr = sql`(${expr})::${type2}`;\n }\n const { _expr, _deps } = expr;\n super(_expr, _deps);\n this.window = op;\n this.func = func;\n this.type = type2;\n this.name = name2;\n this.group = group3;\n this.order = order;\n this.frame = frame4;\n }\n get basis() {\n return this.column;\n }\n get label() {\n const { func } = this;\n return func.label ?? func.toString();\n }\n /**\n * Return an updated window function over a named window definition.\n * @param {string} name The window definition name.\n * @returns {WindowFunction} A new window function.\n */\n over(name2) {\n const { window: op, func, type: type2, group: group3, order, frame: frame4 } = this;\n return new _WindowFunction(op, func, type2, name2, group3, order, frame4);\n }\n /**\n * Return an updated window function with the given partitioning.\n * @param {*} expr The grouping (partition by) criteria for the window function.\n * @returns {WindowFunction} A new window function.\n */\n partitionby(...expr) {\n const exprs = expr.flat().filter((x3) => x3).map(asColumn);\n const group3 = sql(\n [\"PARTITION BY \", repeat(exprs.length - 1, \", \"), \"\"],\n ...exprs\n );\n const { window: op, func, type: type2, name: name2, order, frame: frame4 } = this;\n return new _WindowFunction(op, func, type2, name2, group3, order, frame4);\n }\n /**\n * Return an updated window function with the given ordering.\n * @param {*} expr The sorting (order by) criteria for the window function.\n * @returns {WindowFunction} A new window function.\n */\n orderby(...expr) {\n const exprs = expr.flat().filter((x3) => x3).map(asColumn);\n const order = sql(\n [\"ORDER BY \", repeat(exprs.length - 1, \", \"), \"\"],\n ...exprs\n );\n const { window: op, func, type: type2, name: name2, group: group3, frame: frame4 } = this;\n return new _WindowFunction(op, func, type2, name2, group3, order, frame4);\n }\n /**\n * Return an updated window function with the given rows frame.\n * @param {(number|null)[] | import('./expression.js').ParamLike} expr The row-based window frame.\n * @returns {WindowFunction} A new window function.\n */\n rows(expr) {\n const frame4 = windowFrame(\"ROWS\", expr);\n const { window: op, func, type: type2, name: name2, group: group3, order } = this;\n return new _WindowFunction(op, func, type2, name2, group3, order, frame4);\n }\n /**\n * Return an updated window function with the given range frame.\n * @param {(number|null)[] | import('./expression.js').ParamLike} expr The range-based window frame.\n * @returns {WindowFunction} A new window function.\n */\n range(expr) {\n const frame4 = windowFrame(\"RANGE\", expr);\n const { window: op, func, type: type2, name: name2, group: group3, order } = this;\n return new _WindowFunction(op, func, type2, name2, group3, order, frame4);\n }\n};\nfunction windowFrame(type2, frame4) {\n if (isParamLike(frame4)) {\n const expr = sql`${frame4}`;\n expr.toString = () => `${type2} ${frameToSQL(frame4.value)}`;\n return expr;\n }\n return `${type2} ${frameToSQL(frame4)}`;\n}\nfunction frameToSQL(frame4) {\n const [prev, next] = frame4;\n const a2 = prev === 0 ? \"CURRENT ROW\" : Number.isFinite(prev) ? `${Math.abs(prev)} PRECEDING` : \"UNBOUNDED PRECEDING\";\n const b = next === 0 ? \"CURRENT ROW\" : Number.isFinite(next) ? `${Math.abs(next)} FOLLOWING` : \"UNBOUNDED FOLLOWING\";\n return `BETWEEN ${a2} AND ${b}`;\n}\nfunction winf(op, type2) {\n return (...values2) => {\n const func = functionCall(op)(...values2);\n return new WindowFunction(op, func, type2);\n };\n}\nvar row_number = winf(\"ROW_NUMBER\", \"INTEGER\");\nvar rank = winf(\"RANK\", \"INTEGER\");\nvar dense_rank = winf(\"DENSE_RANK\", \"INTEGER\");\nvar percent_rank = winf(\"PERCENT_RANK\");\nvar cume_dist = winf(\"CUME_DIST\");\nvar ntile = winf(\"NTILE\");\nvar lag = winf(\"LAG\");\nvar lead = winf(\"LEAD\");\nvar first_value = winf(\"FIRST_VALUE\");\nvar last_value = winf(\"LAST_VALUE\");\nvar nth_value = winf(\"NTH_VALUE\");\n\n// ../sql/src/aggregates.js\nfunction agg(strings, ...exprs) {\n return sql(strings, ...exprs).annotate({ aggregate: true });\n}\nvar AggregateFunction = class _AggregateFunction extends SQLExpression {\n /**\n * Create a new AggregateFunction instance.\n * @param {*} op The aggregate operation.\n * @param {*} [args] The aggregate function arguments.\n * @param {*} [type] The SQL data type to cast to.\n * @param {boolean} [isDistinct] Flag indicating if this is a distinct value aggregate.\n * @param {*} [filter] Filtering expression to apply prior to aggregation.\n */\n constructor(op, args, type2, isDistinct2, filter3) {\n args = (args || []).map(asColumn);\n const { strings, exprs } = aggExpr(op, args, type2, isDistinct2, filter3);\n const { spans, cols } = parseSQL(strings, exprs);\n super(spans, cols);\n this.aggregate = op;\n this.args = args;\n this.type = type2;\n this.isDistinct = isDistinct2;\n this.filter = filter3;\n }\n get basis() {\n return this.column;\n }\n get label() {\n const { aggregate: op, args, isDistinct: isDistinct2 } = this;\n const dist2 = isDistinct2 ? \"DISTINCT\" + (args.length ? \" \" : \"\") : \"\";\n const tail = args.length ? `(${dist2}${args.map(unquoted).join(\", \")})` : \"\";\n return `${op.toLowerCase()}${tail}`;\n }\n /**\n * Return a new derived aggregate function over distinct values.\n * @returns {AggregateFunction} A new aggregate function.\n */\n distinct() {\n const { aggregate: op, args, type: type2, filter: filter3 } = this;\n return new _AggregateFunction(op, args, type2, true, filter3);\n }\n /**\n * Return a new derived aggregate function that filters values.\n * @param {*} filter The filter expresion.\n * @returns {AggregateFunction} A new aggregate function.\n */\n where(filter3) {\n const { aggregate: op, args, type: type2, isDistinct: isDistinct2 } = this;\n return new _AggregateFunction(op, args, type2, isDistinct2, filter3);\n }\n /**\n * Return a new window function over this aggregate.\n * @returns {WindowFunction} A new aggregate function.\n */\n window() {\n const { aggregate: op, args, type: type2, isDistinct: isDistinct2 } = this;\n const func = new _AggregateFunction(op, args, null, isDistinct2);\n return new WindowFunction(op, func, type2);\n }\n /**\n * Return a window function over this aggregate with the given partitioning.\n * @param {*} expr The grouping (partition by) criteria for the window function.\n * @returns {WindowFunction} A new window function.\n */\n partitionby(...expr) {\n return this.window().partitionby(...expr);\n }\n /**\n * Return a window function over this aggregate with the given ordering.\n * @param {*} expr The sorting (order by) criteria for the window function.\n * @returns {WindowFunction} A new window function.\n */\n orderby(...expr) {\n return this.window().orderby(...expr);\n }\n /**\n * Return a window function over this aggregate with the given row frame.\n * @param {(number|null)[] | import('./expression.js').ParamLike} frame The row-based window frame.\n * @returns {WindowFunction} A new window function.\n */\n rows(frame4) {\n return this.window().rows(frame4);\n }\n /**\n * Return a window function over this aggregate with the given range frame.\n * @param {(number|null)[] | import('./expression.js').ParamLike} frame The range-based window frame.\n * @returns {WindowFunction} A new window function.\n */\n range(frame4) {\n return this.window().range(frame4);\n }\n};\nfunction aggExpr(op, args, type2, isDistinct2, filter3) {\n const close = `)${type2 ? `::${type2}` : \"\"}`;\n let strings = [`${op}(${isDistinct2 ? \"DISTINCT \" : \"\"}`];\n let exprs = [];\n if (args.length) {\n strings = strings.concat([\n ...repeat(args.length - 1, \", \"),\n `${close}${filter3 ? \" FILTER (WHERE \" : \"\"}`,\n ...filter3 ? [\")\"] : []\n ]);\n exprs = [...args, ...filter3 ? [filter3] : []];\n } else {\n strings[0] += \"*\" + close;\n }\n return { exprs, strings };\n}\nfunction unquoted(value) {\n const s2 = literalToSQL(value);\n return s2 && s2.startsWith('\"') && s2.endsWith('\"') ? s2.slice(1, -1) : s2;\n}\nfunction aggf(op, type2) {\n return (...args) => new AggregateFunction(op, args, type2);\n}\nvar count = aggf(\"COUNT\", \"INTEGER\");\nvar avg = aggf(\"AVG\");\nvar mean = aggf(\"AVG\");\nvar mad = aggf(\"MAD\");\nvar max = aggf(\"MAX\");\nvar min = aggf(\"MIN\");\nvar sum = aggf(\"SUM\", \"DOUBLE\");\nvar product = aggf(\"PRODUCT\");\nvar median = aggf(\"MEDIAN\");\nvar quantile = aggf(\"QUANTILE\");\nvar mode = aggf(\"MODE\");\nvar variance = aggf(\"VARIANCE\");\nvar stddev = aggf(\"STDDEV\");\nvar skewness = aggf(\"SKEWNESS\");\nvar kurtosis = aggf(\"KURTOSIS\");\nvar entropy = aggf(\"ENTROPY\");\nvar varPop = aggf(\"VAR_POP\");\nvar stddevPop = aggf(\"STDDEV_POP\");\nvar corr = aggf(\"CORR\");\nvar covariance = aggf(\"COVAR_SAMP\");\nvar covarPop = aggf(\"COVAR_POP\");\nvar regrIntercept = aggf(\"REGR_INTERCEPT\");\nvar regrSlope = aggf(\"REGR_SLOPE\");\nvar regrCount = aggf(\"REGR_COUNT\");\nvar regrR2 = aggf(\"REGR_R2\");\nvar regrSYY = aggf(\"REGR_SYY\");\nvar regrSXX = aggf(\"REGR_SXX\");\nvar regrSXY = aggf(\"REGR_SXY\");\nvar regrAvgX = aggf(\"REGR_AVGX\");\nvar regrAvgY = aggf(\"REGR_AVGY\");\nvar first = aggf(\"FIRST\");\nvar last = aggf(\"LAST\");\nvar argmin = aggf(\"ARG_MIN\");\nvar argmax = aggf(\"ARG_MAX\");\nvar stringAgg = aggf(\"STRING_AGG\");\nvar arrayAgg = aggf(\"ARRAY_AGG\");\n\n// ../sql/src/cast.js\nfunction cast(expr, type2) {\n const arg = asColumn(expr);\n const e = sql`CAST(${arg} AS ${type2})`;\n Object.defineProperty(e, \"label\", {\n enumerable: true,\n get() {\n return expr.label;\n }\n });\n Object.defineProperty(e, \"aggregate\", {\n enumerable: true,\n get() {\n return expr.aggregate || false;\n }\n });\n return e;\n}\nvar castDouble = (expr) => cast(expr, \"DOUBLE\");\nvar castInteger = (expr) => cast(expr, \"INTEGER\");\n\n// ../sql/src/datetime.js\nvar epoch_ms = (expr) => {\n return sql`epoch_ms(${asColumn(expr)})`;\n};\nfunction dateBin(expr, interval3, steps = 1) {\n const i = `INTERVAL ${steps} ${interval3}`;\n const d = asColumn(expr);\n return sql`TIME_BUCKET(${i}, ${d})`.annotate({ label: interval3 });\n}\nvar dateMonth = (expr) => {\n const d = asColumn(expr);\n return sql`MAKE_DATE(2012, MONTH(${d}), 1)`.annotate({ label: \"month\" });\n};\nvar dateMonthDay = (expr) => {\n const d = asColumn(expr);\n return sql`MAKE_DATE(2012, MONTH(${d}), DAY(${d}))`.annotate({ label: \"date\" });\n};\nvar dateDay2 = (expr) => {\n const d = asColumn(expr);\n return sql`MAKE_DATE(2012, 1, DAY(${d}))`.annotate({ label: \"date\" });\n};\n\n// ../sql/src/spatial.js\nvar geojson = functionCall(\"ST_AsGeoJSON\");\nvar x = functionCall(\"ST_X\");\nvar y = functionCall(\"ST_Y\");\nvar centroid = functionCall(\"ST_CENTROID\");\nvar centroidX = (geom) => x(centroid(geom));\nvar centroidY = (geom) => y(centroid(geom));\n\n// ../sql/src/Query.js\nvar Query = class _Query {\n static select(...expr) {\n return new _Query().select(...expr);\n }\n static from(...expr) {\n return new _Query().from(...expr);\n }\n static with(...expr) {\n return new _Query().with(...expr);\n }\n static union(...queries) {\n return new SetOperation(\"UNION\", queries.flat());\n }\n static unionAll(...queries) {\n return new SetOperation(\"UNION ALL\", queries.flat());\n }\n static intersect(...queries) {\n return new SetOperation(\"INTERSECT\", queries.flat());\n }\n static except(...queries) {\n return new SetOperation(\"EXCEPT\", queries.flat());\n }\n static describe(query) {\n const q = query.clone();\n const { clone, toString } = q;\n return Object.assign(q, {\n describe: true,\n clone: () => _Query.describe(clone.call(q)),\n toString: () => `DESCRIBE ${toString.call(q)}`\n });\n }\n constructor() {\n this.query = {\n with: [],\n select: [],\n from: [],\n where: [],\n groupby: [],\n having: [],\n window: [],\n qualify: [],\n orderby: []\n };\n this.cteFor = null;\n }\n clone() {\n const q = new _Query();\n q.query = { ...this.query };\n return q;\n }\n /**\n * Retrieve current WITH common table expressions (CTEs).\n * @returns {any[]}\n */\n /**\n * Add WITH common table expressions (CTEs).\n * @param {...any} expr Expressions to add.\n * @returns {this}\n */\n with(...expr) {\n const { query } = this;\n if (expr.length === 0) {\n return query.with;\n } else {\n const list2 = [];\n const add2 = (as, q) => {\n const query2 = q.clone();\n query2.cteFor = this;\n list2.push({ as, query: query2 });\n };\n expr.flat().forEach((e) => {\n if (e == null) {\n } else if (e.as && e.query) {\n add2(e.as, e.query);\n } else {\n for (const as in e) {\n add2(as, e[as]);\n }\n }\n });\n query.with = query.with.concat(list2);\n return this;\n }\n }\n /**\n * Retrieve current SELECT expressions.\n * @returns {any[]}\n */\n /**\n * Add SELECT expressions.\n * @param {...any} expr Expressions to add.\n * @returns {this}\n */\n select(...expr) {\n const { query } = this;\n if (expr.length === 0) {\n return query.select;\n } else {\n const list2 = [];\n for (const e of expr.flat()) {\n if (e == null) {\n } else if (typeof e === \"string\") {\n list2.push({ as: e, expr: asColumn(e) });\n } else if (e instanceof Ref) {\n list2.push({ as: e.column, expr: e });\n } else if (Array.isArray(e)) {\n list2.push({ as: e[0], expr: e[1] });\n } else {\n for (const as in e) {\n list2.push({ as: unquote(as), expr: asColumn(e[as]) });\n }\n }\n }\n const keys = new Set(list2.map((x3) => x3.as));\n query.select = query.select.filter((x3) => !keys.has(x3.as)).concat(list2.filter((x3) => x3.expr));\n return this;\n }\n }\n $select(...expr) {\n this.query.select = [];\n return this.select(...expr);\n }\n distinct(value = true) {\n this.query.distinct = !!value;\n return this;\n }\n /**\n * Retrieve current from expressions.\n * @returns {any[]}\n */\n /**\n * Provide table from expressions.\n * @param {...any} expr\n * @returns {this}\n */\n from(...expr) {\n const { query } = this;\n if (expr.length === 0) {\n return query.from;\n } else {\n const list2 = [];\n expr.flat().forEach((e) => {\n if (e == null) {\n } else if (typeof e === \"string\") {\n list2.push({ as: e, from: asRelation(e) });\n } else if (e instanceof Ref) {\n list2.push({ as: e.table, from: e });\n } else if (isQuery(e) || isSQLExpression(e)) {\n list2.push({ from: e });\n } else if (Array.isArray(e)) {\n list2.push({ as: unquote(e[0]), from: asRelation(e[1]) });\n } else {\n for (const as in e) {\n list2.push({ as: unquote(as), from: asRelation(e[as]) });\n }\n }\n });\n query.from = query.from.concat(list2);\n return this;\n }\n }\n $from(...expr) {\n this.query.from = [];\n return this.from(...expr);\n }\n /**\n * Retrieve current SAMPLE settings.\n * @returns {any[]}\n */\n /**\n * Set SAMPLE settings.\n * @param {number|object} value The percentage or number of rows to sample.\n * @param {string} [method] The sampling method to use.\n * @returns {this}\n */\n sample(value, method) {\n const { query } = this;\n if (arguments.length === 0) {\n return query.sample;\n } else {\n let spec = value;\n if (typeof value === \"number\") {\n spec = value > 0 && value < 1 ? { perc: 100 * value, method } : { rows: Math.round(value), method };\n }\n query.sample = spec;\n return this;\n }\n }\n /**\n * Retrieve current WHERE expressions.\n * @returns {any[]}\n */\n /**\n * Add WHERE expressions.\n * @param {...any} expr Expressions to add.\n * @returns {this}\n */\n where(...expr) {\n const { query } = this;\n if (expr.length === 0) {\n return query.where;\n } else {\n query.where = query.where.concat(\n expr.flat().filter((x3) => x3)\n );\n return this;\n }\n }\n $where(...expr) {\n this.query.where = [];\n return this.where(...expr);\n }\n /**\n * Retrieve current GROUP BY expressions.\n * @returns {any[]}\n */\n /**\n * Add GROUP BY expressions.\n * @param {...any} expr Expressions to add.\n * @returns {this}\n */\n groupby(...expr) {\n const { query } = this;\n if (expr.length === 0) {\n return query.groupby;\n } else {\n query.groupby = query.groupby.concat(\n expr.flat().filter((x3) => x3).map(asColumn)\n );\n return this;\n }\n }\n $groupby(...expr) {\n this.query.groupby = [];\n return this.groupby(...expr);\n }\n /**\n * Retrieve current HAVING expressions.\n * @returns {any[]}\n */\n /**\n * Add HAVING expressions.\n * @param {...any} expr Expressions to add.\n * @returns {this}\n */\n having(...expr) {\n const { query } = this;\n if (expr.length === 0) {\n return query.having;\n } else {\n query.having = query.having.concat(\n expr.flat().filter((x3) => x3)\n );\n return this;\n }\n }\n /**\n * Retrieve current WINDOW definitions.\n * @returns {any[]}\n */\n /**\n * Add WINDOW definitions.\n * @param {...any} expr Expressions to add.\n * @returns {this}\n */\n window(...expr) {\n const { query } = this;\n if (expr.length === 0) {\n return query.window;\n } else {\n const list2 = [];\n expr.flat().forEach((e) => {\n if (e == null) {\n } else {\n for (const as in e) {\n list2.push({ as: unquote(as), expr: e[as] });\n }\n }\n });\n query.window = query.window.concat(list2);\n return this;\n }\n }\n /**\n * Retrieve current QUALIFY expressions.\n * @returns {any[]}\n */\n /**\n * Add QUALIFY expressions.\n * @param {...any} expr Expressions to add.\n * @returns {this}\n */\n qualify(...expr) {\n const { query } = this;\n if (expr.length === 0) {\n return query.qualify;\n } else {\n query.qualify = query.qualify.concat(\n expr.flat().filter((x3) => x3)\n );\n return this;\n }\n }\n /**\n * Retrieve current ORDER BY expressions.\n * @returns {any[]}\n */\n /**\n * Add ORDER BY expressions.\n * @param {...any} expr Expressions to add.\n * @returns {this}\n */\n orderby(...expr) {\n const { query } = this;\n if (expr.length === 0) {\n return query.orderby;\n } else {\n query.orderby = query.orderby.concat(\n expr.flat().filter((x3) => x3).map(asColumn)\n );\n return this;\n }\n }\n /**\n * Retrieve current LIMIT value.\n * @returns {number|null}\n */\n /**\n * Set the query result LIMIT.\n * @param {number} value The limit value.\n * @returns {this}\n */\n limit(value) {\n const { query } = this;\n if (arguments.length === 0) {\n return query.limit;\n } else {\n query.limit = Number.isFinite(value) ? value : void 0;\n return this;\n }\n }\n /**\n * Retrieve current OFFSET value.\n * @returns {number|null}\n */\n /**\n * Set the query result OFFSET.\n * @param {number} value The offset value.\n * @returns {this}\n */\n offset(value) {\n const { query } = this;\n if (arguments.length === 0) {\n return query.offset;\n } else {\n query.offset = Number.isFinite(value) ? value : void 0;\n return this;\n }\n }\n get subqueries() {\n const { query, cteFor } = this;\n const ctes = (cteFor?.query || query).with;\n const cte = ctes?.reduce((o, { as, query: query2 }) => (o[as] = query2, o), {});\n const q = [];\n query.from.forEach(({ from: from2 }) => {\n if (isQuery(from2)) {\n q.push(from2);\n } else if (cte[from2.table]) {\n const sub = cte[from2.table];\n q.push(sub);\n }\n });\n return q;\n }\n toString() {\n const {\n with: cte,\n select: select2,\n distinct: distinct2,\n from: from2,\n sample,\n where,\n groupby,\n having,\n window: window3,\n qualify,\n orderby,\n limit,\n offset: offset2\n } = this.query;\n const sql2 = [];\n if (cte.length) {\n const list2 = cte.map(({ as, query }) => `\"${as}\" AS (${query})`);\n sql2.push(`WITH ${list2.join(\", \")}`);\n }\n const sels = select2.map(\n ({ as, expr }) => isColumnRefFor(expr, as) && !expr.table ? `${expr}` : `${expr} AS \"${as}\"`\n );\n sql2.push(`SELECT${distinct2 ? \" DISTINCT\" : \"\"} ${sels.join(\", \")}`);\n if (from2.length) {\n const rels = from2.map(({ as, from: from3 }) => {\n const rel = isQuery(from3) ? `(${from3})` : `${from3}`;\n return !as || as === from3.table ? rel : `${rel} AS \"${as}\"`;\n });\n sql2.push(`FROM ${rels.join(\", \")}`);\n }\n if (where.length) {\n const clauses = where.map(String).filter((x3) => x3).join(\" AND \");\n if (clauses) sql2.push(`WHERE ${clauses}`);\n }\n if (sample) {\n const { rows, perc, method, seed } = sample;\n const size = rows ? `${rows} ROWS` : `${perc} PERCENT`;\n const how = method ? ` (${method}${seed != null ? `, ${seed}` : \"\"})` : \"\";\n sql2.push(`USING SAMPLE ${size}${how}`);\n }\n if (groupby.length) {\n sql2.push(`GROUP BY ${groupby.join(\", \")}`);\n }\n if (having.length) {\n const clauses = having.map(String).filter((x3) => x3).join(\" AND \");\n if (clauses) sql2.push(`HAVING ${clauses}`);\n }\n if (window3.length) {\n const windows = window3.map(({ as, expr }) => `\"${as}\" AS (${expr})`);\n sql2.push(`WINDOW ${windows.join(\", \")}`);\n }\n if (qualify.length) {\n const clauses = qualify.map(String).filter((x3) => x3).join(\" AND \");\n if (clauses) sql2.push(`QUALIFY ${clauses}`);\n }\n if (orderby.length) {\n sql2.push(`ORDER BY ${orderby.join(\", \")}`);\n }\n if (Number.isFinite(limit)) {\n sql2.push(`LIMIT ${limit}`);\n }\n if (Number.isFinite(offset2)) {\n sql2.push(`OFFSET ${offset2}`);\n }\n return sql2.join(\" \");\n }\n};\nvar SetOperation = class _SetOperation {\n constructor(op, queries) {\n this.op = op;\n this.queries = queries.map((q) => q.clone());\n this.query = { orderby: [] };\n this.cteFor = null;\n }\n clone() {\n const q = new _SetOperation(this.op, this.queries);\n q.query = { ...this.query };\n return q;\n }\n orderby(...expr) {\n const { query } = this;\n if (expr.length === 0) {\n return query.orderby;\n } else {\n query.orderby = query.orderby.concat(\n expr.flat().filter((x3) => x3).map(asColumn)\n );\n return this;\n }\n }\n limit(value) {\n const { query } = this;\n if (arguments.length === 0) {\n return query.limit;\n } else {\n query.limit = Number.isFinite(value) ? value : void 0;\n return this;\n }\n }\n offset(value) {\n const { query } = this;\n if (arguments.length === 0) {\n return query.offset;\n } else {\n query.offset = Number.isFinite(value) ? value : void 0;\n return this;\n }\n }\n get subqueries() {\n const { queries, cteFor } = this;\n if (cteFor) queries.forEach((q) => q.cteFor = cteFor);\n return queries;\n }\n toString() {\n const { op, queries, query: { orderby, limit, offset: offset2 } } = this;\n const sql2 = [queries.join(` ${op} `)];\n if (orderby.length) {\n sql2.push(`ORDER BY ${orderby.join(\", \")}`);\n }\n if (Number.isFinite(limit)) {\n sql2.push(`LIMIT ${limit}`);\n }\n if (Number.isFinite(offset2)) {\n sql2.push(`OFFSET ${offset2}`);\n }\n return sql2.join(\" \");\n }\n};\nfunction isQuery(value) {\n return value instanceof Query || value instanceof SetOperation;\n}\nfunction isDescribeQuery(value) {\n return isQuery(value) && value.describe;\n}\nfunction unquote(s2) {\n return isDoubleQuoted(s2) ? s2.slice(1, -1) : s2;\n}\nfunction isDoubleQuoted(s2) {\n return s2[0] === '\"' && s2[s2.length - 1] === '\"';\n}\n\n// ../sql/src/scales.js\nvar identity = (x3) => x3;\nfunction scaleLinear() {\n return {\n apply: identity,\n invert: identity,\n sqlApply: asColumn,\n sqlInvert: identity\n };\n}\nfunction scaleLog({ base = null } = {}) {\n if (base == null || base === Math.E) {\n return {\n apply: Math.log,\n invert: Math.exp,\n sqlApply: (c4) => sql`LN(${asColumn(c4)})`,\n sqlInvert: (c4) => sql`EXP(${c4})`\n };\n } else if (base === 10) {\n return {\n apply: Math.log10,\n invert: (x3) => Math.pow(10, x3),\n sqlApply: (c4) => sql`LOG(${asColumn(c4)})`,\n sqlInvert: (c4) => sql`POW(10, ${c4})`\n };\n } else {\n const b = +base;\n return {\n apply: (x3) => Math.log(x3) / Math.log(b),\n invert: (x3) => Math.pow(b, x3),\n sqlApply: (c4) => sql`LN(${asColumn(c4)}) / LN(${b})`,\n sqlInvert: (c4) => sql`POW(${b}, ${c4})`\n };\n }\n}\nfunction scaleSymlog({ constant: constant2 = 1 } = {}) {\n const _ = +constant2;\n return {\n apply: (x3) => Math.sign(x3) * Math.log1p(Math.abs(x3)),\n invert: (x3) => Math.sign(x3) * Math.exp(Math.abs(x3) - _),\n sqlApply: (c4) => (c4 = asColumn(c4), sql`SIGN(${c4}) * LN(${_} + ABS(${c4}))`),\n sqlInvert: (c4) => sql`SIGN(${c4}) * (EXP(ABS(${c4})) - ${_})`\n };\n}\nfunction scaleSqrt() {\n return {\n apply: (x3) => Math.sign(x3) * Math.sqrt(Math.abs(x3)),\n invert: (x3) => Math.sign(x3) * x3 * x3,\n sqlApply: (c4) => (c4 = asColumn(c4), sql`SIGN(${c4}) * SQRT(ABS(${c4}))`),\n sqlInvert: (c4) => sql`SIGN(${c4}) * (${c4}) ** 2`\n };\n}\nfunction scalePow({ exponent = 1 } = {}) {\n const e = +exponent;\n return {\n apply: (x3) => Math.sign(x3) * Math.pow(Math.abs(x3), e),\n invert: (x3) => Math.sign(x3) * Math.pow(Math.abs(x3), 1 / e),\n sqlApply: (c4) => (c4 = asColumn(c4), sql`SIGN(${c4}) * POW(ABS(${c4}), ${e})`),\n sqlInvert: (c4) => sql`SIGN(${c4}) * POW(ABS(${c4}), 1/${e})`\n };\n}\nfunction scaleTime() {\n return {\n apply: (x3) => +x3,\n invert: (x3) => new Date(x3),\n sqlApply: (c4) => c4 instanceof Date ? +c4 : epoch_ms(asColumn(c4)),\n sqlInvert: identity\n };\n}\nvar scales = {\n identity: scaleLinear,\n linear: scaleLinear,\n log: scaleLog,\n symlog: scaleSymlog,\n sqrt: scaleSqrt,\n pow: scalePow,\n time: scaleTime,\n utc: scaleTime\n};\nfunction scaleTransform(options) {\n const scale3 = scales[options.type];\n return scale3 ? { ...options, ...scale3(options) } : null;\n}\n\n// ../sql/src/load/create.js\nfunction create(name2, query, {\n replace = false,\n temp = true,\n view = false\n} = {}) {\n return \"CREATE\" + (replace ? \" OR REPLACE \" : \" \") + (temp ? \"TEMP \" : \"\") + (view ? \"VIEW\" : \"TABLE\") + (replace ? \" \" : \" IF NOT EXISTS \") + name2 + \" AS \" + query;\n}\n\n// ../sql/src/load/extension.js\nfunction loadExtension(name2) {\n return `INSTALL ${name2}; LOAD ${name2}`;\n}\n\n// ../sql/src/load/sql-from.js\nfunction sqlFrom(data, {\n columns = Object.keys(data?.[0] || {})\n} = {}) {\n let keys = [];\n if (Array.isArray(columns)) {\n keys = columns;\n columns = keys.reduce((m, k2) => (m[k2] = k2, m), {});\n } else if (columns) {\n keys = Object.keys(columns);\n }\n if (!keys.length) {\n throw new Error(\"Can not create table from empty column set.\");\n }\n const subq = [];\n for (const datum2 of data) {\n const sel = keys.map((k2) => `${literalToSQL(datum2[k2])} AS \"${columns[k2]}\"`);\n subq.push(`(SELECT ${sel.join(\", \")})`);\n }\n return subq.join(\" UNION ALL \");\n}\n\n// ../sql/src/load/load.js\nfunction load(method, tableName, fileName, options = {}, defaults22 = {}) {\n const { select: select2 = [\"*\"], where, view, temp, replace, ...file } = options;\n const params = parameters({ ...defaults22, ...file });\n const read = `${method}('${fileName}'${params ? \", \" + params : \"\"})`;\n const filter3 = where ? ` WHERE ${where}` : \"\";\n const query = `SELECT ${select2.join(\", \")} FROM ${read}${filter3}`;\n return create(tableName, query, { view, temp, replace });\n}\nfunction loadCSV(tableName, fileName, options) {\n return load(\"read_csv\", tableName, fileName, options, { auto_detect: true, sample_size: -1 });\n}\nfunction loadJSON(tableName, fileName, options) {\n return load(\"read_json\", tableName, fileName, options, { auto_detect: true, json_format: \"auto\" });\n}\nfunction loadParquet(tableName, fileName, options) {\n return load(\"read_parquet\", tableName, fileName, options);\n}\nfunction loadSpatial(tableName, fileName, options = {}) {\n const { options: opt, ...rest } = options;\n if (opt) {\n const open = Array.isArray(opt) ? opt.join(\", \") : typeof opt === \"string\" ? opt : Object.entries(opt).map(([key, value]) => `${key}=${value}`).join(\", \");\n Object.assign(rest, { open_options: open.toUpperCase() });\n }\n return load(\"st_read\", tableName, fileName, rest);\n}\nfunction loadObjects(tableName, data, options = {}) {\n const { select: select2 = [\"*\"], ...opt } = options;\n const values2 = sqlFrom(data);\n const query = select2.length === 1 && select2[0] === \"*\" ? values2 : `SELECT ${select2} FROM ${values2}`;\n return create(tableName, query, opt);\n}\nfunction parameters(options) {\n return Object.entries(options).map(([key, value]) => `${key}=${toDuckDBValue(value)}`).join(\", \");\n}\nfunction toDuckDBValue(value) {\n switch (typeof value) {\n case \"boolean\":\n return String(value);\n case \"string\":\n return `'${value}'`;\n case \"undefined\":\n case \"object\":\n if (value == null) {\n return \"NULL\";\n } else if (Array.isArray(value)) {\n return \"[\" + value.map((v2) => toDuckDBValue(v2)).join(\", \") + \"]\";\n } else {\n return \"{\" + Object.entries(value).map(([k2, v2]) => `'${k2}': ${toDuckDBValue(v2)}`).join(\", \") + \"}\";\n }\n default:\n return value;\n }\n}\n\n// ../core/src/util/index-columns.js\nfunction indexColumns(client) {\n if (!client.filterIndexable) return null;\n const q = client.query();\n const from2 = getBase(q, (q2) => q2.from()?.[0].from.table);\n if (typeof from2 !== \"string\" || !q.select) return null;\n const aggr = [];\n const dims = [];\n const aux = {};\n const avg2 = (ref) => {\n const name2 = ref.column;\n const expr = getBase(q, (q2) => q2.select().find((c4) => c4.as === name2)?.expr);\n return `(SELECT AVG(${expr ?? ref}) FROM \"${from2}\")`;\n };\n for (const entry of q.select()) {\n const { as, expr: { aggregate, args } } = entry;\n const op = aggregate?.toUpperCase?.();\n switch (op) {\n case \"COUNT\":\n case \"SUM\":\n aggr.push({ [as]: agg`SUM(\"${as}\")::DOUBLE` });\n break;\n case \"AVG\":\n aggr.push({ [as]: avgExpr(aux, as, args[0]) });\n break;\n case \"ARG_MAX\":\n aggr.push({ [as]: argmaxExpr(aux, as, args) });\n break;\n case \"ARG_MIN\":\n aggr.push({ [as]: argminExpr(aux, as, args) });\n break;\n // variance statistics drop the original aggregate operation\n // in favor of tracking auxiliary sufficient statistics\n case \"VARIANCE\":\n case \"VAR_SAMP\":\n aux[as] = null;\n aggr.push({ [as]: varianceExpr(aux, args[0], avg2) });\n break;\n case \"VAR_POP\":\n aux[as] = null;\n aggr.push({ [as]: varianceExpr(aux, args[0], avg2, false) });\n break;\n case \"STDDEV\":\n case \"STDDEV_SAMP\":\n aux[as] = null;\n aggr.push({ [as]: agg`SQRT(${varianceExpr(aux, args[0], avg2)})` });\n break;\n case \"STDDEV_POP\":\n aux[as] = null;\n aggr.push({ [as]: agg`SQRT(${varianceExpr(aux, args[0], avg2, false)})` });\n break;\n case \"COVAR_SAMP\":\n aux[as] = null;\n aggr.push({ [as]: covarianceExpr(aux, args, avg2) });\n break;\n case \"COVAR_POP\":\n aux[as] = null;\n aggr.push({ [as]: covarianceExpr(aux, args, avg2, false) });\n break;\n case \"CORR\":\n aux[as] = null;\n aggr.push({ [as]: corrExpr(aux, args, avg2) });\n break;\n // regression statistics\n case \"REGR_COUNT\":\n aux[as] = null;\n aggr.push({ [as]: agg`${regrCountExpr(aux, args)}::DOUBLE` });\n break;\n case \"REGR_AVGX\":\n aux[as] = null;\n aggr.push({ [as]: regrAvgXExpr(aux, args) });\n break;\n case \"REGR_AVGY\":\n aux[as] = null;\n aggr.push({ [as]: regrAvgYExpr(aux, args) });\n break;\n case \"REGR_SYY\":\n aux[as] = null;\n aggr.push({ [as]: regrVarExpr(aux, 0, args, avg2) });\n break;\n case \"REGR_SXX\":\n aux[as] = null;\n aggr.push({ [as]: regrVarExpr(aux, 1, args, avg2) });\n break;\n case \"REGR_SXY\":\n aux[as] = null;\n aggr.push({ [as]: covarianceExpr(aux, args, avg2, null) });\n break;\n case \"REGR_SLOPE\":\n aux[as] = null;\n aggr.push({ [as]: regrSlopeExpr(aux, args, avg2) });\n break;\n case \"REGR_INTERCEPT\":\n aux[as] = null;\n aggr.push({ [as]: regrInterceptExpr(aux, args, avg2) });\n break;\n case \"REGR_R2\":\n aux[as] = null;\n aggr.push({ [as]: agg`(${corrExpr(aux, args, avg2)}) ** 2` });\n break;\n // aggregates that commute directly\n case \"MAX\":\n case \"MIN\":\n case \"BIT_AND\":\n case \"BIT_OR\":\n case \"BIT_XOR\":\n case \"BOOL_AND\":\n case \"BOOL_OR\":\n case \"PRODUCT\":\n aggr.push({ [as]: agg`${op}(\"${as}\")` });\n break;\n // otherwise, check if dimension\n default:\n if (!aggregate) dims.push(as);\n else return null;\n }\n }\n if (!aggr.length) return null;\n return { from: from2, dims, aggr, aux };\n}\nfunction auxName(type2, ...args) {\n const cols = args.length ? \"_\" + args.map(sanitize).join(\"_\") : \"\";\n return `__${type2}${cols}__`;\n}\nfunction sanitize(col) {\n return `${col}`.replaceAll('\"', \"\").replaceAll(\" \", \"_\");\n}\nfunction getBase(query, get3) {\n const subq = query.subqueries;\n if (query.select && subq.length === 0) {\n return get3(query);\n }\n const base = getBase(subq[0], get3);\n for (let i = 1; i < subq.length; ++i) {\n const value = getBase(subq[i], get3);\n if (value === void 0) continue;\n if (value !== base) return NaN;\n }\n return base;\n}\nfunction countExpr(aux, arg) {\n const n = auxName(\"count\", arg);\n aux[n] = agg`COUNT(${arg})`;\n return agg`SUM(${n})`.annotate({ name: n });\n}\nfunction avgExpr(aux, as, arg) {\n const n = countExpr(aux, arg);\n return agg`(SUM(\"${as}\" * ${n.name}) / ${n})`;\n}\nfunction argmaxExpr(aux, as, [, y3]) {\n const max4 = auxName(\"max\", y3);\n aux[max4] = agg`MAX(${y3})`;\n return agg`ARG_MAX(\"${as}\", ${max4})`;\n}\nfunction argminExpr(aux, as, [, y3]) {\n const min5 = auxName(\"min\", y3);\n aux[min5] = agg`MIN(${y3})`;\n return agg`ARG_MIN(\"${as}\", ${min5})`;\n}\nfunction varianceExpr(aux, x3, avg2, correction = true) {\n const n = countExpr(aux, x3);\n const ssq = auxName(\"rssq\", x3);\n const sum4 = auxName(\"rsum\", x3);\n const delta = sql`${x3} - ${avg2(x3)}`;\n aux[ssq] = agg`SUM((${delta}) ** 2)`;\n aux[sum4] = agg`SUM(${delta})`;\n const adj = correction ? ` - 1` : \"\";\n return agg`(SUM(${ssq}) - (SUM(${sum4}) ** 2 / ${n})) / (${n}${adj})`;\n}\nfunction covarianceExpr(aux, args, avg2, correction = true) {\n const n = regrCountExpr(aux, args);\n const sxy = regrSumXYExpr(aux, args, avg2);\n const sx = regrSumExpr(aux, 1, args, avg2);\n const sy = regrSumExpr(aux, 0, args, avg2);\n const adj = correction === null ? \"\" : correction ? ` / (${n} - 1)` : ` / ${n}`;\n return agg`(${sxy} - ${sx} * ${sy} / ${n})${adj}`;\n}\nfunction corrExpr(aux, args, avg2) {\n const n = regrCountExpr(aux, args);\n const sxy = regrSumXYExpr(aux, args, avg2);\n const sxx = regrSumSqExpr(aux, 1, args, avg2);\n const syy = regrSumSqExpr(aux, 0, args, avg2);\n const sx = regrSumExpr(aux, 1, args, avg2);\n const sy = regrSumExpr(aux, 0, args, avg2);\n const vx = agg`(${sxx} - (${sx} ** 2) / ${n})`;\n const vy = agg`(${syy} - (${sy} ** 2) / ${n})`;\n return agg`(${sxy} - ${sx} * ${sy} / ${n}) / SQRT(${vx} * ${vy})`;\n}\nfunction regrCountExpr(aux, [y3, x3]) {\n const n = auxName(\"count\", y3, x3);\n aux[n] = agg`REGR_COUNT(${y3}, ${x3})`;\n return agg`SUM(${n})`.annotate({ name: n });\n}\nfunction regrSumExpr(aux, i, args, avg2) {\n const v2 = args[i];\n const o = args[1 - i];\n const sum4 = auxName(\"rs\", v2);\n aux[sum4] = agg`SUM(${v2} - ${avg2(v2)}) FILTER (${o} IS NOT NULL)`;\n return agg`SUM(${sum4})`;\n}\nfunction regrSumSqExpr(aux, i, args, avg2) {\n const v2 = args[i];\n const u4 = args[1 - i];\n const ssq = auxName(\"rss\", v2);\n aux[ssq] = agg`SUM((${v2} - ${avg2(v2)}) ** 2) FILTER (${u4} IS NOT NULL)`;\n return agg`SUM(${ssq})`;\n}\nfunction regrSumXYExpr(aux, args, avg2) {\n const [y3, x3] = args;\n const sxy = auxName(\"sxy\", y3, x3);\n aux[sxy] = agg`SUM((${x3} - ${avg2(x3)}) * (${y3} - ${avg2(y3)}))`;\n return agg`SUM(${sxy})`;\n}\nfunction regrAvgXExpr(aux, args) {\n const [y3, x3] = args;\n const n = regrCountExpr(aux, args);\n const a2 = auxName(\"avg\", x3, y3);\n aux[a2] = agg`REGR_AVGX(${y3}, ${x3})`;\n return agg`(SUM(${a2} * ${n.name}) / ${n})`;\n}\nfunction regrAvgYExpr(aux, args) {\n const [y3, x3] = args;\n const n = regrCountExpr(aux, args);\n const a2 = auxName(\"avg\", y3, x3);\n aux[a2] = agg`REGR_AVGY(${y3}, ${x3})`;\n return agg`(SUM(${a2} * ${n.name}) / ${n})`;\n}\nfunction regrVarExpr(aux, i, args, avg2) {\n const n = regrCountExpr(aux, args);\n const sum4 = regrSumExpr(aux, i, args, avg2);\n const ssq = regrSumSqExpr(aux, i, args, avg2);\n return agg`(${ssq} - (${sum4} ** 2 / ${n}))`;\n}\nfunction regrSlopeExpr(aux, args, avg2) {\n const cov = covarianceExpr(aux, args, avg2, null);\n const varx = regrVarExpr(aux, 1, args, avg2);\n return agg`(${cov}) / ${varx}`;\n}\nfunction regrInterceptExpr(aux, args, avg2) {\n const ax = regrAvgXExpr(aux, args);\n const ay = regrAvgYExpr(aux, args);\n const m = regrSlopeExpr(aux, args, avg2);\n return agg`${ay} - (${m}) * ${ax}`;\n}\n\n// ../core/src/util/hash.js\nfunction fnv_hash(v2) {\n let a2 = 2166136261;\n for (let i = 0, n = v2.length; i < n; ++i) {\n const c4 = v2.charCodeAt(i);\n const d = c4 & 65280;\n if (d) a2 = fnv_multiply(a2 ^ d >> 8);\n a2 = fnv_multiply(a2 ^ c4 & 255);\n }\n return fnv_mix(a2);\n}\nfunction fnv_multiply(a2) {\n return a2 + (a2 << 1) + (a2 << 4) + (a2 << 7) + (a2 << 8) + (a2 << 24);\n}\nfunction fnv_mix(a2) {\n a2 += a2 << 13;\n a2 ^= a2 >>> 7;\n a2 += a2 << 3;\n a2 ^= a2 >>> 17;\n a2 += a2 << 5;\n return a2 & 4294967295;\n}\n\n// ../core/src/DataCubeIndexer.js\nvar Skip = { skip: true, result: null };\nvar DataCubeIndexer = class {\n /**\n * Create a new data cube index table manager.\n * @param {import('./Coordinator.js').Coordinator} coordinator A Mosaic coordinator.\n * @param {DataCubeIndexerOptions} [options] Data cube indexer options.\n */\n constructor(coordinator2, {\n schema = \"mosaic\",\n enabled = true\n } = {}) {\n this.indexes = /* @__PURE__ */ new Map();\n this.active = null;\n this.mc = coordinator2;\n this._schema = schema;\n this._enabled = enabled;\n }\n /**\n * Set the enabled state of this indexer. If false, any local state is\n * cleared and subsequent index calls will return null until re-enabled.\n * This method has no effect on any index tables already in the database.\n * @param {boolean} [state] The enabled state to set.\n */\n set enabled(state) {\n if (this._enabled !== state) {\n if (!state) this.clear();\n this._enabled = state;\n }\n }\n /**\n * Get the enabled state of this indexer.\n * @returns {boolean} The current enabled state.\n */\n get enabled() {\n return this._enabled;\n }\n /**\n * Set the database schema used by this indexer. Upon changes, any local\n * state is cleared. This method does _not_ drop any existing data cube\n * tables, use `dropIndexTables` before changing the schema to also remove\n * existing index tables in the database.\n * @param {string} [schema] The schema name to set.\n */\n set schema(schema) {\n if (this._schema !== schema) {\n this.clear();\n this._schema = schema;\n }\n }\n /**\n * Get the database schema used by this indexer.\n * @returns {string} The current schema name.\n */\n get schema() {\n return this._schema;\n }\n /**\n * Issues a query through the coordinator to drop the current index table\n * schema. *All* tables in the schema will be removed and local state is\n * cleared. Call this method if the underlying base tables have been updated,\n * causing derived index tables to become stale and inaccurate. Use this\n * method with care! Once dropped, the schema will be repopulated by future\n * data cube indexer requests.\n * @returns A query result promise.\n */\n dropIndexTables() {\n this.clear();\n return this.mc.exec(`DROP SCHEMA IF EXISTS \"${this.schema}\" CASCADE`);\n }\n /**\n * Clear the cache of data cube index table entries for the current active\n * selection clause. This method does _not_ drop any existing data cube\n * tables. Use `dropIndexTables` to remove existing index tables from the\n * database.\n */\n clear() {\n this.indexes.clear();\n this.active = null;\n }\n /**\n * Return data cube index table information for the active state of a\n * client-selection pair, or null if the client is not indexable. This\n * method has multiple possible side effects, including data cube table\n * generation and updating internal caches.\n * @param {import('./MosaicClient.js').MosaicClient} client A Mosaic client.\n * @param {import('./Selection.js').Selection} selection A Mosaic selection\n * to filter the client by.\n * @param {import('./util/selection-types.js').SelectionClause} activeClause\n * A representative active selection clause for which to (possibly) generate\n * data cube index tables.\n * @returns {DataCubeInfo | Skip | null} Data cube index table\n * information and query generator, or null if the client is not indexable.\n */\n index(client, selection2, activeClause) {\n if (!this.enabled) return null;\n const { indexes: indexes2, mc, schema } = this;\n const { source } = activeClause;\n if (!source) return null;\n if (this.active) {\n if (this.active.source !== source) this.clear();\n if (this.active?.source === null) return null;\n }\n let { active } = this;\n if (!active) {\n this.active = active = activeColumns(activeClause);\n if (active.source === null) return null;\n }\n if (indexes2.has(client)) {\n return indexes2.get(client);\n }\n const indexCols = indexColumns(client);\n let info;\n if (!indexCols) {\n info = null;\n } else if (selection2.skip(client, activeClause)) {\n info = Skip;\n } else {\n const filter3 = selection2.remove(source).predicate(client);\n info = dataCubeInfo(client.query(filter3), active, indexCols, schema);\n info.result = mc.exec([\n `CREATE SCHEMA IF NOT EXISTS ${schema}`,\n create(info.table, info.create, { temp: false })\n ]);\n info.result.catch((e) => mc.logger().error(e));\n }\n indexes2.set(client, info);\n return info;\n }\n};\nfunction activeColumns(clause) {\n const { source, meta } = clause;\n const clausePred = clause.predicate;\n const clauseCols = clausePred?.columns;\n let predicate;\n let columns;\n if (!meta || !clauseCols) {\n return { source: null, columns, predicate };\n }\n const { type: type2, scales: scales2, bin: bin3, pixelSize = 1 } = meta;\n if (type2 === \"point\") {\n predicate = (x3) => x3;\n columns = Object.fromEntries(\n clauseCols.map((col) => [`${col}`, asColumn(col)])\n );\n } else if (type2 === \"interval\" && scales2) {\n const bins2 = scales2.map((s2) => binInterval(s2, pixelSize, bin3));\n if (bins2.some((b) => !b)) {\n } else if (bins2.length === 1) {\n predicate = (p) => p ? isBetween(\"active0\", p.range.map(bins2[0])) : [];\n columns = { active0: bins2[0](clausePred.field) };\n } else {\n predicate = (p) => p ? and(p.children.map(\n ({ range: range3 }, i) => isBetween(`active${i}`, range3.map(bins2[i]))\n )) : [];\n columns = Object.fromEntries(\n // @ts-ignore\n clausePred.children.map((p, i) => [`active${i}`, bins2[i](p.field)])\n );\n }\n }\n return { source: columns ? source : null, columns, predicate };\n}\nvar BIN = { ceil: \"CEIL\", round: \"ROUND\" };\nfunction binInterval(scale3, pixelSize, bin3) {\n const { type: type2, domain, range: range3, apply: apply2, sqlApply } = scaleTransform(scale3);\n if (!apply2) return;\n const fn = BIN[`${bin3}`.toLowerCase()] || \"FLOOR\";\n const lo = apply2(Math.min(...domain));\n const hi = apply2(Math.max(...domain));\n const a2 = type2 === \"identity\" ? 1 : Math.abs(range3[1] - range3[0]) / (hi - lo);\n const s2 = a2 / pixelSize === 1 ? \"\" : `${a2 / pixelSize}::DOUBLE * `;\n const d = lo === 0 ? \"\" : ` - ${lo}::DOUBLE`;\n return (value) => sql`${fn}(${s2}(${sqlApply(value)}${d}))::INTEGER`;\n}\nfunction dataCubeInfo(clientQuery, active, indexCols, schema) {\n const { dims, aggr, aux } = indexCols;\n const { columns } = active;\n const query = clientQuery.select({ ...columns, ...aux }).groupby(Object.keys(columns));\n const [subq] = query.subqueries;\n if (subq) {\n const cols = Object.values(columns).flatMap((c4) => c4.columns);\n subqueryPushdown(subq, cols);\n }\n const order = query.orderby();\n query.query.orderby = [];\n const create5 = query.toString();\n const id2 = (fnv_hash(create5) >>> 0).toString(16);\n const table3 = `${schema}.cube_${id2}`;\n const select2 = Query.select(dims, aggr).from(table3).groupby(dims).orderby(order);\n return new DataCubeInfo({ id: id2, table: table3, create: create5, active, select: select2 });\n}\nfunction subqueryPushdown(query, cols) {\n const memo2 = /* @__PURE__ */ new Set();\n const pushdown = (q) => {\n if (memo2.has(q)) return;\n memo2.add(q);\n if (q.select && q.from().length) {\n q.select(cols);\n }\n q.subqueries.forEach(pushdown);\n };\n pushdown(query);\n}\nvar DataCubeInfo = class {\n /**\n * Create a new DataCubeInfo instance.\n * @param {object} options\n */\n constructor({ table: table3, create: create5, active, select: select2 } = {}) {\n this.table = table3;\n this.create = create5;\n this.result = null;\n this.active = active;\n this.select = select2;\n this.skip = false;\n }\n /**\n * Generate a data cube index table query for the given predicate.\n * @param {import('@uwdata/mosaic-sql').SQLExpression} predicate The current\n * active clause predicate.\n * @returns {Query} A data cube index table query.\n */\n query(predicate) {\n return this.select.clone().where(this.active.predicate(predicate));\n }\n};\n\n// ../core/src/util/query-result.js\nvar QueryResult = class extends Promise {\n /**\n * Create a new query result Promise.\n */\n constructor() {\n let resolve;\n let reject;\n super((r, e) => {\n resolve = r;\n reject = e;\n });\n this._resolve = resolve;\n this._reject = reject;\n }\n /**\n * Resolve the result Promise with the provided value.\n * @param {*} value The result value.\n * @returns {this}\n */\n fulfill(value) {\n this._resolve(value);\n return this;\n }\n /**\n * Rejects the result Promise with the provided error.\n * @param {*} error The error value.\n * @returns {this}\n */\n reject(error2) {\n this._reject(error2);\n return this;\n }\n};\nQueryResult.prototype.constructor = Promise;\n\n// ../core/src/QueryConsolidator.js\nfunction wait(callback) {\n const method = typeof requestAnimationFrame !== \"undefined\" ? requestAnimationFrame : typeof setImmediate !== \"undefined\" ? setImmediate : setTimeout;\n return method(callback);\n}\nfunction consolidator(enqueue, cache, record) {\n let pending = [];\n let id2 = 0;\n function run() {\n const groups2 = entryGroups(pending, cache);\n pending = [];\n id2 = 0;\n for (const group3 of groups2) {\n consolidate(group3, enqueue, record);\n processResults(group3, cache);\n }\n }\n return {\n add(entry, priority) {\n if (entry.request.type === \"arrow\") {\n id2 = id2 || wait(() => run());\n pending.push({ entry, priority, index: pending.length });\n } else {\n enqueue(entry, priority);\n }\n }\n };\n}\nfunction entryGroups(entries, cache) {\n const groups2 = [];\n const groupMap = /* @__PURE__ */ new Map();\n for (const query of entries) {\n const { entry: { request } } = query;\n const key = consolidationKey(request.query, cache);\n if (!groupMap.has(key)) {\n const list2 = [];\n groups2.push(list2);\n groupMap.set(key, list2);\n }\n groupMap.get(key).push(query);\n }\n return groups2;\n}\nfunction consolidationKey(query, cache) {\n const sql2 = `${query}`;\n if (query instanceof Query && !cache.get(sql2)) {\n if (\n // @ts-ignore\n query.orderby().length || query.where().length || // @ts-ignore\n query.qualify().length || query.having().length\n ) {\n return sql2;\n }\n const q = query.clone().$select(\"*\");\n const groupby = query.groupby();\n if (groupby.length) {\n const map5 = {};\n query.select().forEach(({ as, expr }) => map5[as] = expr);\n q.$groupby(groupby.map((e) => e instanceof Ref && map5[e.column] || e));\n } else if (query.select().some(({ expr }) => expr.aggregate)) {\n q.$groupby(\"ALL\");\n }\n return `${q}`;\n } else {\n return sql2;\n }\n}\nfunction consolidate(group3, enqueue, record) {\n if (shouldConsolidate(group3)) {\n enqueue({\n request: {\n type: \"arrow\",\n cache: false,\n record: false,\n query: group3.query = consolidatedQuery(group3, record)\n },\n result: group3.result = new QueryResult()\n });\n } else {\n for (const { entry, priority } of group3) {\n enqueue(entry, priority);\n }\n }\n}\nfunction shouldConsolidate(group3) {\n if (group3.length > 1) {\n const sql2 = `${group3[0].entry.request.query}`;\n for (let i = 1; i < group3.length; ++i) {\n if (sql2 !== `${group3[i].entry.request.query}`) {\n return true;\n }\n }\n }\n return false;\n}\nfunction consolidatedQuery(group3, record) {\n const maps = group3.maps = [];\n const fields = /* @__PURE__ */ new Map();\n for (const item of group3) {\n const { query: query2 } = item.entry.request;\n const fieldMap = [];\n maps.push(fieldMap);\n for (const { as, expr } of query2.select()) {\n const e = `${expr}`;\n if (!fields.has(e)) {\n fields.set(e, [`col${fields.size}`, expr]);\n }\n const [name2] = fields.get(e);\n fieldMap.push([name2, as]);\n }\n record(`${query2}`);\n }\n const query = group3[0].entry.request.query.clone();\n const groupby = query.groupby();\n if (groupby.length) {\n const map5 = {};\n group3.maps[0].forEach(([name2, as]) => map5[as] = name2);\n query.$groupby(groupby.map((e) => e instanceof Ref && map5[e.column] || e));\n }\n return query.$select(Array.from(fields.values()));\n}\nasync function processResults(group3, cache) {\n const { maps, query, result } = group3;\n if (!maps) return;\n let data;\n try {\n data = await result;\n } catch (err) {\n for (const { entry } of group3) {\n entry.result.reject(err);\n }\n return;\n }\n const describe = isDescribeQuery(query);\n group3.forEach(({ entry }, index2) => {\n const { request, result: result2 } = entry;\n const map5 = maps[index2];\n const extract = describe && map5 ? filterResult(data, map5) : map5 ? projectResult(data, map5) : data;\n if (request.cache) {\n cache.set(String(request.query), extract);\n }\n result2.fulfill(extract);\n });\n}\nfunction projectResult(data, map5) {\n return data.select(map5.map((x3) => x3[0]), map5.map((x3) => x3[1]));\n}\nfunction filterResult(data, map5) {\n const lookup = new Map(map5);\n const result = [];\n for (const d of data) {\n if (lookup.has(d.column_name)) {\n result.push({ ...d, column_name: lookup.get(d.column_name) });\n }\n }\n return result;\n}\n\n// ../core/src/util/cache.js\nvar requestIdle = typeof requestIdleCallback !== \"undefined\" ? requestIdleCallback : setTimeout;\nvar voidCache = () => ({\n get: () => void 0,\n set: (key, value) => value,\n clear: () => {\n }\n});\nfunction lruCache({\n max: max4 = 1e3,\n // max entries\n ttl = 3 * 60 * 60 * 1e3\n // time-to-live, default 3 hours\n} = {}) {\n let cache = /* @__PURE__ */ new Map();\n function evict() {\n const expire = performance.now() - ttl;\n let lruKey = null;\n let lruLast = Infinity;\n for (const [key, value] of cache) {\n const { last: last2 } = value;\n if (last2 < lruLast) {\n lruKey = key;\n lruLast = last2;\n }\n if (expire > last2) {\n cache.delete(key);\n }\n }\n if (lruKey) {\n cache.delete(lruKey);\n }\n }\n return {\n get(key) {\n const entry = cache.get(key);\n if (entry) {\n entry.last = performance.now();\n return entry.value;\n }\n },\n set(key, value) {\n cache.set(key, { last: performance.now(), value });\n if (cache.size > max4) requestIdle(evict);\n return value;\n },\n clear() {\n cache = /* @__PURE__ */ new Map();\n }\n };\n}\n\n// ../core/src/util/priority-queue.js\nvar PriorityQueue = class {\n /**\n * Create a new priority queue instance.\n * @param {number} ranks An integer number of rank-order priority levels.\n */\n constructor(ranks) {\n this.queue = Array.from(\n { length: ranks },\n () => ({ head: null, tail: null })\n );\n }\n /**\n * Indicate if the queue is empty.\n * @returns {boolean} true if empty, false otherwise.\n */\n isEmpty() {\n return this.queue.every((list2) => !list2.head);\n }\n /**\n * Insert an item into the queue with a given priority rank.\n * @param {*} item The item to add.\n * @param {number} rank The integer priority rank.\n * Priority ranks are integers starting at zero.\n * Lower ranks indicate higher priority.\n */\n insert(item, rank3) {\n const list2 = this.queue[rank3];\n if (!list2) {\n throw new Error(`Invalid queue priority rank: ${rank3}`);\n }\n const node = { item, next: null };\n if (list2.head === null) {\n list2.head = list2.tail = node;\n } else {\n list2.tail = list2.tail.next = node;\n }\n }\n /**\n * Remove a set of items from the queue, regardless of priority rank.\n * If a provided item is not in the queue it will be ignored.\n * @param {(item: *) => boolean} test A predicate function to test\n * if an item should be removed (true to drop, false to keep).\n */\n remove(test) {\n for (const list2 of this.queue) {\n let { head, tail } = list2;\n for (let prev = null, curr = head; curr; prev = curr, curr = curr.next) {\n if (test(curr.item)) {\n if (curr === head) {\n head = curr.next;\n } else {\n prev.next = curr.next;\n }\n if (curr === tail) tail = prev || head;\n }\n }\n list2.head = head;\n list2.tail = tail;\n }\n }\n /**\n * Remove and return the next highest priority item.\n * @returns {*} The next item in the queue,\n * or undefined if this queue is empty.\n */\n next() {\n for (const list2 of this.queue) {\n const { head } = list2;\n if (head !== null) {\n list2.head = head.next;\n if (list2.tail === head) {\n list2.tail = null;\n }\n return head.item;\n }\n }\n }\n};\n\n// ../core/src/QueryManager.js\nvar Priority = { High: 0, Normal: 1, Low: 2 };\nvar QueryManager = class {\n constructor() {\n this.queue = new PriorityQueue(3);\n this.db = null;\n this.clientCache = null;\n this._logger = null;\n this._logQueries = false;\n this.recorders = [];\n this.pending = null;\n this._consolidate = null;\n }\n next() {\n if (this.pending || this.queue.isEmpty()) return;\n const { request, result } = this.queue.next();\n this.pending = this.submit(request, result);\n this.pending.finally(() => {\n this.pending = null;\n this.next();\n });\n }\n enqueue(entry, priority = Priority.Normal) {\n this.queue.insert(entry, priority);\n this.next();\n }\n recordQuery(sql2) {\n if (this.recorders.length && sql2) {\n this.recorders.forEach((rec) => rec.add(sql2));\n }\n }\n async submit(request, result) {\n try {\n const { query, type: type2, cache = false, record = true, options } = request;\n const sql2 = query ? `${query}` : null;\n if (record) {\n this.recordQuery(sql2);\n }\n if (cache) {\n const cached = this.clientCache.get(sql2);\n if (cached) {\n this._logger.debug(\"Cache\");\n result.fulfill(cached);\n return;\n }\n }\n const t03 = performance.now();\n if (this._logQueries) {\n this._logger.debug(\"Query\", { type: type2, sql: sql2, ...options });\n }\n const data = await this.db.query({ type: type2, sql: sql2, ...options });\n if (cache) this.clientCache.set(sql2, data);\n this._logger.debug(`Request: ${(performance.now() - t03).toFixed(1)}`);\n result.fulfill(data);\n } catch (err) {\n result.reject(err);\n }\n }\n cache(value) {\n return value !== void 0 ? this.clientCache = value === true ? lruCache() : value || voidCache() : this.clientCache;\n }\n logger(value) {\n return value ? this._logger = value : this._logger;\n }\n logQueries(value) {\n return value !== void 0 ? this._logQueries = !!value : this._logQueries;\n }\n connector(connector) {\n return connector ? this.db = connector : this.db;\n }\n consolidate(flag) {\n if (flag && !this._consolidate) {\n this._consolidate = consolidator(this.enqueue.bind(this), this.clientCache, this.recordQuery.bind(this));\n } else if (!flag && this._consolidate) {\n this._consolidate = null;\n }\n }\n request(request, priority = Priority.Normal) {\n const result = new QueryResult();\n const entry = { request, result };\n if (this._consolidate) {\n this._consolidate.add(entry, priority);\n } else {\n this.enqueue(entry, priority);\n }\n return result;\n }\n cancel(requests) {\n const set3 = new Set(requests);\n if (set3.size) {\n this.queue.remove(({ result }) => {\n if (set3.has(result)) {\n result.reject(\"Canceled\");\n return true;\n }\n return false;\n });\n }\n }\n clear() {\n this.queue.remove(({ result }) => {\n result.reject(\"Cleared\");\n return true;\n });\n }\n record() {\n let state = [];\n const recorder = {\n add(query) {\n state.push(query);\n },\n reset() {\n state = [];\n },\n snapshot() {\n return state.slice();\n },\n stop() {\n this.recorders = this.recorders.filter((x3) => x3 !== recorder);\n return state;\n }\n };\n this.recorders.push(recorder);\n return recorder;\n }\n};\n\n// ../core/src/util/js-type.js\nfunction jsType(type2) {\n switch (type2) {\n case \"BIGINT\":\n case \"HUGEINT\":\n case \"INTEGER\":\n case \"SMALLINT\":\n case \"TINYINT\":\n case \"UBIGINT\":\n case \"UINTEGER\":\n case \"USMALLINT\":\n case \"UTINYINT\":\n // integers\n case \"DOUBLE\":\n case \"FLOAT\":\n case \"REAL\":\n return \"number\";\n case \"DATE\":\n case \"TIMESTAMP\":\n case \"TIMESTAMPTZ\":\n case \"TIMESTAMP WITH TIME ZONE\":\n case \"TIME\":\n case \"TIMESTAMP_NS\":\n return \"date\";\n case \"BOOLEAN\":\n return \"boolean\";\n case \"VARCHAR\":\n case \"UUID\":\n case \"JSON\":\n return \"string\";\n case \"ARRAY\":\n case \"LIST\":\n return \"array\";\n case \"BLOB\":\n case \"STRUCT\":\n case \"MAP\":\n case \"GEOMETRY\":\n return \"object\";\n default:\n if (type2.startsWith(\"DECIMAL\")) {\n return \"number\";\n } else if (type2.startsWith(\"STRUCT\") || type2.startsWith(\"MAP\")) {\n return \"object\";\n } else if (type2.endsWith(\"]\")) {\n return \"array\";\n }\n throw new Error(`Unsupported type: ${type2}`);\n }\n}\n\n// ../core/src/util/field-info.js\nvar Count = \"count\";\nvar Nulls = \"nulls\";\nvar Max = \"max\";\nvar Min = \"min\";\nvar Distinct = \"distinct\";\nvar statMap = {\n [Count]: count,\n [Distinct]: (column3) => count(column3).distinct(),\n [Max]: max,\n [Min]: min,\n [Nulls]: (column3) => count().where(isNull(column3))\n};\nfunction summarize(table3, column3, stats) {\n return Query.from(table3).select(Array.from(stats, (s2) => [s2, statMap[s2](column3)]));\n}\nasync function queryFieldInfo(mc, fields) {\n if (fields.length === 1 && `${fields[0].column}` === \"*\") {\n return getTableInfo(mc, fields[0].table);\n } else {\n return (await Promise.all(fields.map((f) => getFieldInfo(mc, f)))).filter((x3) => x3);\n }\n}\nasync function getFieldInfo(mc, { table: table3, column: column3, stats }) {\n const q = Query.from({ source: table3 }).select({ column: column3 }).groupby(column3.aggregate ? sql`ALL` : []);\n const [desc2] = Array.from(await mc.query(Query.describe(q)));\n const info = {\n table: table3,\n column: `${column3}`,\n sqlType: desc2.column_type,\n type: jsType(desc2.column_type),\n nullable: desc2.null === \"YES\"\n };\n if (!(stats?.length || stats?.size)) return info;\n const [result] = await mc.query(\n summarize(table3, column3, stats),\n { persist: true }\n );\n return Object.assign(info, result);\n}\nasync function getTableInfo(mc, table3) {\n const result = await mc.query(`DESCRIBE ${asRelation(table3)}`);\n return Array.from(result).map((desc2) => ({\n table: table3,\n column: desc2.column_name,\n sqlType: desc2.column_type,\n type: jsType(desc2.column_type),\n nullable: desc2.null === \"YES\"\n }));\n}\n\n// ../core/src/util/void-logger.js\nfunction voidLogger() {\n return {\n debug() {\n },\n info() {\n },\n log() {\n },\n warn() {\n },\n error() {\n }\n };\n}\n\n// ../core/src/Coordinator.js\nvar _instance;\nfunction coordinator(instance) {\n if (instance) {\n _instance = instance;\n } else if (_instance == null) {\n _instance = new Coordinator();\n }\n return _instance;\n}\nvar Coordinator = class {\n constructor(db = socketConnector(), {\n logger = console,\n manager = new QueryManager(),\n cache = true,\n consolidate: consolidate2 = true,\n indexes: indexes2 = {}\n } = {}) {\n this.manager = manager;\n this.manager.cache(cache);\n this.manager.consolidate(consolidate2);\n this.databaseConnector(db);\n this.logger(logger);\n this.clear();\n this.dataCubeIndexer = new DataCubeIndexer(this, indexes2);\n }\n /**\n * Clear the coordinator state.\n * @param {object} [options] Options object.\n * @param {boolean} [options.clients=true] If true, disconnect all clients.\n * @param {boolean} [options.cache=true] If true, clear the query cache.\n */\n clear({ clients = true, cache = true } = {}) {\n this.manager.clear();\n if (clients) {\n this.filterGroups?.forEach((group3) => group3.disconnect());\n this.filterGroups = /* @__PURE__ */ new Map();\n this.clients?.forEach((client) => this.disconnect(client));\n this.clients = /* @__PURE__ */ new Set();\n }\n if (cache) this.manager.cache().clear();\n }\n /**\n * Get or set the database connector.\n * @param {*} [db] The database connector to use.\n * @returns The current database connector.\n */\n databaseConnector(db) {\n return this.manager.connector(db);\n }\n /**\n * Get or set the logger.\n * @param {*} logger The logger to use.\n * @returns The current logger\n */\n logger(logger) {\n if (arguments.length) {\n this._logger = logger || voidLogger();\n this.manager.logger(this._logger);\n }\n return this._logger;\n }\n // -- Query Management ----\n /**\n * Cancel previosuly submitted query requests. These queries will be\n * canceled if they are queued but have not yet been submitted.\n * @param {QueryResult[]} requests An array\n * of query result objects, such as those returned by the `query` method.\n */\n cancel(requests) {\n this.manager.cancel(requests);\n }\n /**\n * Issue a query for which no result (return value) is needed.\n * @param {QueryType | QueryType[]} query The query or an array of queries.\n * Each query should be either a Query builder object or a SQL string.\n * @param {object} [options] An options object.\n * @param {number} [options.priority] The query priority, defaults to\n * `Priority.Normal`.\n * @returns {QueryResult} A query result\n * promise.\n */\n exec(query, { priority = Priority.Normal } = {}) {\n query = Array.isArray(query) ? query.filter((x3) => x3).join(\";\\n\") : query;\n return this.manager.request({ type: \"exec\", query }, priority);\n }\n /**\n * Issue a query to the backing database. The submitted query may be\n * consolidate with other queries and its results may be cached.\n * @param {QueryType} query The query as either a Query builder object\n * or a SQL string.\n * @param {object} [options] An options object.\n * @param {'arrow' | 'json'} [options.type] The query result format type.\n * @param {boolean} [options.cache=true] If true, cache the query result.\n * @param {number} [options.priority] The query priority, defaults to\n * `Priority.Normal`.\n * @returns {QueryResult} A query result promise.\n */\n query(query, {\n type: type2 = \"arrow\",\n cache = true,\n priority = Priority.Normal,\n ...options\n } = {}) {\n return this.manager.request({ type: type2, query, cache, options }, priority);\n }\n /**\n * Issue a query to prefetch data for later use. The query result is cached\n * for efficient future access.\n * @param {QueryType} query The query as either a Query builder object\n * or a SQL string.\n * @param {object} [options] An options object.\n * @param {'arrow' | 'json'} [options.type] The query result format type.\n * @returns {QueryResult} A query result promise.\n */\n prefetch(query, options = {}) {\n return this.query(query, { ...options, cache: true, priority: Priority.Low });\n }\n /**\n * Create a bundle of queries that can be loaded into the cache.\n *\n * @param {string} name The name of the bundle.\n * @param {[string | {sql: string}, {alias: string}]} queries The queries to save into the bundle.\n * @param {number} priority Request priority.\n * @returns {QueryResult} A query result promise.\n */\n createBundle(name2, queries, priority = Priority.Low) {\n const options = { name: name2, queries: queries.map((q) => typeof q == \"string\" ? { sql: q } : q) };\n return this.manager.request({ type: \"create-bundle\", options }, priority);\n }\n /**\n * Load a bundle into the cache.\n * @param {string} name The name of the bundle.\n * @param {number} priority Request priority.\n * @returns {QueryResult} A query result promise.\n */\n loadBundle(name2, priority = Priority.High) {\n const options = { name: name2 };\n return this.manager.request({ type: \"load-bundle\", options }, priority);\n }\n // -- Client Management ----\n /**\n * Update client data by submitting the given query and returning the\n * data (or error) to the client.\n * @param {MosaicClient} client A Mosaic client.\n * @param {QueryType} query The data query.\n * @param {number} [priority] The query priority.\n * @returns {Promise} A Promise that resolves upon completion of the update.\n */\n updateClient(client, query, priority = Priority.Normal) {\n client.queryPending();\n return this.query(query, { priority }).then(\n (data) => client.queryResult(data).update(),\n (err) => {\n this._logger.error(err);\n client.queryError(err);\n }\n ).catch((err) => this._logger.error(err));\n }\n /**\n * Issue a query request for a client. If the query is null or undefined,\n * the client is simply updated. Otherwise `updateClient` is called. As a\n * side effect, this method clears the current data cube indexer state.\n * @param {MosaicClient} client The client to update.\n * @param {QueryType | null} [query] The query to issue.\n */\n requestQuery(client, query) {\n this.dataCubeIndexer.clear();\n return query ? this.updateClient(client, query) : Promise.resolve(client.update());\n }\n /**\n * Connect a client to the coordinator.\n * @param {MosaicClient} client The Mosaic client to connect.\n */\n async connect(client) {\n const { clients } = this;\n if (clients.has(client)) {\n throw new Error(\"Client already connected.\");\n }\n clients.add(client);\n client.coordinator = this;\n this.initializeClient(client);\n connectSelection(this, client.filterBy, client);\n }\n async initializeClient(client) {\n const fields = client.fields();\n if (fields?.length) {\n client.fieldInfo(await queryFieldInfo(this, fields));\n }\n return client.requestQuery();\n }\n /**\n * Disconnect a client from the coordinator.\n * @param {MosaicClient} client The Mosaic client to disconnect.\n */\n disconnect(client) {\n const { clients, filterGroups } = this;\n if (!clients.has(client)) return;\n clients.delete(client);\n client.coordinator = null;\n const group3 = filterGroups.get(client.filterBy);\n if (group3) {\n group3.clients.delete(client);\n }\n }\n};\nfunction connectSelection(mc, selection2, client) {\n if (!selection2) return;\n let entry = mc.filterGroups.get(selection2);\n if (!entry) {\n const activate = (clause) => activateSelection(mc, selection2, clause);\n const value = () => updateSelection(mc, selection2);\n selection2.addEventListener(\"activate\", activate);\n selection2.addEventListener(\"value\", value);\n entry = {\n selection: selection2,\n clients: /* @__PURE__ */ new Set(),\n disconnect() {\n selection2.removeEventListener(\"activate\", activate);\n selection2.removeEventListener(\"value\", value);\n }\n };\n mc.filterGroups.set(selection2, entry);\n }\n entry.clients.add(client);\n}\nfunction activateSelection(mc, selection2, clause) {\n const { dataCubeIndexer, filterGroups } = mc;\n const { clients } = filterGroups.get(selection2);\n for (const client of clients) {\n dataCubeIndexer.index(client, selection2, clause);\n }\n}\nfunction updateSelection(mc, selection2) {\n const { dataCubeIndexer, filterGroups } = mc;\n const { clients } = filterGroups.get(selection2);\n const { active } = selection2;\n return Promise.allSettled(Array.from(clients, (client) => {\n const info = dataCubeIndexer.index(client, selection2, active);\n const filter3 = info ? null : selection2.predicate(client);\n if (info?.skip || !info && !filter3) return;\n const query = info?.query(active.predicate) ?? client.query(filter3);\n return mc.updateClient(client, query);\n }));\n}\n\n// ../core/src/util/AsyncDispatch.js\nvar AsyncDispatch = class {\n /**\n * Create a new asynchronous dispatcher instance.\n */\n constructor() {\n this._callbacks = /* @__PURE__ */ new Map();\n }\n /**\n * Add an event listener callback for the provided event type.\n * @param {string} type The event type.\n * @param {(value: *) => void | Promise} callback The event handler\n * callback function to add. If the callback has already been\n * added for the event type, this method has no effect.\n */\n addEventListener(type2, callback) {\n if (!this._callbacks.has(type2)) {\n this._callbacks.set(type2, {\n callbacks: /* @__PURE__ */ new Set(),\n pending: null,\n queue: new DispatchQueue()\n });\n }\n const entry = this._callbacks.get(type2);\n entry.callbacks.add(callback);\n }\n /**\n * Remove an event listener callback for the provided event type.\n * @param {string} type The event type.\n * @param {(value: *) => void | Promise} callback The event handler\n * callback function to remove.\n */\n removeEventListener(type2, callback) {\n const entry = this._callbacks.get(type2);\n if (entry) {\n entry.callbacks.delete(callback);\n }\n }\n /**\n * Lifecycle method that returns the event value to emit.\n * This default implementation simply returns the input value as-is.\n * Subclasses may override this method to implement custom transformations\n * prior to emitting an event value to all listeners.\n * @param {string} type The event type.\n * @param {*} value The event value.\n * @returns The (possibly transformed) event value to emit.\n */\n willEmit(type2, value) {\n return value;\n }\n /**\n * Lifecycle method that returns a filter function for updating the\n * queue of unemitted event values prior to enqueueing a new value.\n * This default implementation simply returns null, indicating that\n * any other unemitted event values should be dropped (that is, all\n * queued events are filtered).\n * @param {string} type The event type.\n * @param {*} value The new event value that will be enqueued.\n * @returns {(value: *) => boolean|null} A dispatch queue filter\n * function, or null if all unemitted event values should be filtered.\n */\n emitQueueFilter(type2, value) {\n return null;\n }\n /**\n * Cancel all unemitted event values for the given event type.\n * @param {string} type The event type.\n */\n cancel(type2) {\n const entry = this._callbacks.get(type2);\n entry?.queue.clear();\n }\n /**\n * Returns a promise that resolves when any pending updates complete for\n * the event of the given type currently being processed. The Promise will\n * resolve immediately if the queue for the given event type is empty.\n * @param {string} type The event type to wait for.\n * @returns {Promise} A pending event promise.\n */\n async pending(type2) {\n await this._callbacks.get(type2)?.pending;\n }\n /**\n * Emit an event value to listeners for the given event type.\n * If a previous emit has not yet resolved, the event value\n * will be queued to be emitted later.\n * The actual event value given to listeners will be the result\n * of passing the input value through the emitValue() method.\n * @param {string} type The event type.\n * @param {*} value The event value.\n */\n emit(type2, value) {\n const entry = this._callbacks.get(type2) || {};\n if (entry.pending) {\n entry.queue.enqueue(value, this.emitQueueFilter(type2, value));\n } else {\n const event = this.willEmit(type2, value);\n const { callbacks, queue } = entry;\n if (callbacks?.size) {\n const callbackValues = Array.from(callbacks, (cb) => cb(event));\n entry.pending = Promise.allSettled(callbackValues).then(() => {\n entry.pending = null;\n if (!queue.isEmpty()) {\n this.emit(type2, queue.dequeue());\n }\n });\n }\n }\n }\n};\nvar DispatchQueue = class {\n /**\n * Create a new dispatch queue instance.\n */\n constructor() {\n this.clear();\n }\n /**\n * Clear the queue state of all event values.\n */\n clear() {\n this.next = null;\n }\n /**\n * Indicate if the queue is empty.\n * @returns {boolean} True if queue is empty, false otherwise.\n */\n isEmpty() {\n return !this.next;\n }\n /**\n * Add a new value to the queue, and optionally filter the\n * current queue content in response.\n * @param {*} value The value to add.\n * @param {(value: *) => boolean} [filter] An optional filter\n * function to apply to existing queue content. If unspecified\n * or falsy, all previously queued values are removed. Otherwise,\n * the provided function is applied to all queue entries. The\n * entry is retained if the filter function returns a truthy value,\n * otherwise the entry is removed.\n */\n enqueue(value, filter3) {\n const tail = { value };\n if (filter3 && this.next) {\n let curr = this;\n while (curr.next) {\n if (filter3(curr.next.value)) {\n curr = curr.next;\n } else {\n curr.next = curr.next.next;\n }\n }\n curr.next = tail;\n } else {\n this.next = tail;\n }\n }\n /**\n * Remove and return the next queued event value.\n * @returns {*} The next event value in the queue.\n */\n dequeue() {\n const { next } = this;\n this.next = next?.next;\n return next?.value;\n }\n};\n\n// ../core/src/util/distinct.js\nfunction distinct(a2, b) {\n return a2 === b ? false : a2 instanceof Date && b instanceof Date ? +a2 !== +b : Array.isArray(a2) && Array.isArray(b) ? distinctArray(a2, b) : true;\n}\nfunction distinctArray(a2, b) {\n if (a2.length !== b.length) return true;\n for (let i = 0; i < a2.length; ++i) {\n if (a2[i] !== b[i]) return true;\n }\n return false;\n}\n\n// ../core/src/Param.js\nfunction isParam(x3) {\n return x3 instanceof Param;\n}\nvar Param = class _Param extends AsyncDispatch {\n /**\n * Create a new Param instance.\n * @param {*} value The initial value of the Param.\n */\n constructor(value) {\n super();\n this._value = value;\n }\n /**\n * Create a new Param instance with the given initial value.\n * @param {*} value The initial value of the Param.\n * @returns {Param} The new Param instance.\n */\n static value(value) {\n return new _Param(value);\n }\n /**\n * Create a new Param instance over an array of initial values,\n * which may contain nested Params.\n * @param {*} values The initial values of the Param.\n * @returns {Param} The new Param instance.\n */\n static array(values2) {\n if (values2.some((v2) => isParam(v2))) {\n const p = new _Param();\n const update2 = () => {\n p.update(values2.map((v2) => isParam(v2) ? v2.value : v2));\n };\n update2();\n values2.forEach((v2) => isParam(v2) ? v2.addEventListener(\"value\", update2) : 0);\n return p;\n }\n return new _Param(values2);\n }\n /**\n * The current value of the Param.\n */\n get value() {\n return this._value;\n }\n /**\n * Update the Param value\n * @param {*} value The new value of the Param.\n * @param {object} [options] The update options.\n * @param {boolean} [options.force] A boolean flag indicating if the Param\n * should emit a 'value' event even if the internal value is unchanged.\n * @returns {this} This Param instance.\n */\n update(value, { force } = {}) {\n const shouldEmit = distinct(this._value, value) || force;\n if (shouldEmit) {\n this.emit(\"value\", value);\n } else {\n this.cancel(\"value\");\n }\n return this;\n }\n /**\n * Upon value-typed updates, sets the current value to the input value\n * immediately prior to the event value being emitted to listeners.\n * @param {string} type The event type.\n * @param {*} value The input event value.\n * @returns {*} The input event value.\n */\n willEmit(type2, value) {\n if (type2 === \"value\") {\n this._value = value;\n }\n return value;\n }\n};\n\n// ../core/src/Selection.js\nfunction isSelection(x3) {\n return x3 instanceof Selection;\n}\nfunction create2(options, include) {\n return new Selection(\n new SelectionResolver(options),\n include ? [include].flat() : include\n );\n}\nvar Selection = class _Selection extends Param {\n /**\n * Create a new Selection instance with an\n * intersect (conjunction) resolution strategy.\n * @param {object} [options] The selection options.\n * @param {boolean} [options.cross=false] Boolean flag indicating\n * cross-filtered resolution. If true, selection clauses will not\n * be applied to the clients they are associated with.\n * @param {boolean} [options.empty=false] Boolean flag indicating if a lack\n * of clauses should correspond to an empty selection with no records. This\n * setting determines the default selection state.\n * @param {Selection|Selection[]} [options.include] Upstream selections whose\n * clauses should be included as part of the new selection. Any clauses\n * published to upstream selections will be relayed to the new selection.\n * @returns {Selection} The new Selection instance.\n */\n static intersect({ cross: cross3 = false, empty: empty4 = false, include = [] } = {}) {\n return create2({ cross: cross3, empty: empty4 }, include);\n }\n /**\n * Create a new Selection instance with a\n * union (disjunction) resolution strategy.\n * @param {object} [options] The selection options.\n * @param {boolean} [options.cross=false] Boolean flag indicating\n * cross-filtered resolution. If true, selection clauses will not\n * be applied to the clients they are associated with.\n * @param {boolean} [options.empty=false] Boolean flag indicating if a lack\n * of clauses should correspond to an empty selection with no records. This\n * setting determines the default selection state.\n * @param {Selection|Selection[]} [options.include] Upstream selections whose\n * clauses should be included as part of the new selection. Any clauses\n * published to upstream selections will be relayed to the new selection.\n * @returns {Selection} The new Selection instance.\n */\n static union({ cross: cross3 = false, empty: empty4 = false, include = [] } = {}) {\n return create2({ cross: cross3, empty: empty4, union: true }, include);\n }\n /**\n * Create a new Selection instance with a singular resolution strategy\n * that keeps only the most recent selection clause.\n * @param {object} [options] The selection options.\n * @param {boolean} [options.cross=false] Boolean flag indicating\n * cross-filtered resolution. If true, selection clauses will not\n * be applied to the clients they are associated with.\n * @param {boolean} [options.empty=false] Boolean flag indicating if a lack\n * of clauses should correspond to an empty selection with no records. This\n * setting determines the default selection state.\n * @param {Selection|Selection[]} [options.include] Upstream selections whose\n * clauses should be included as part of the new selection. Any clauses\n * published to upstream selections will be relayed to the new selection.\n * @returns {Selection} The new Selection instance.\n */\n static single({ cross: cross3 = false, empty: empty4 = false, include = [] } = {}) {\n return create2({ cross: cross3, empty: empty4, single: true }, include);\n }\n /**\n * Create a new Selection instance with a\n * cross-filtered intersect resolution strategy.\n * @param {object} [options] The selection options.\n * @param {boolean} [options.empty=false] Boolean flag indicating if a lack\n * of clauses should correspond to an empty selection with no records. This\n * setting determines the default selection state.\n * @param {Selection|Selection[]} [options.include] Upstream selections whose\n * clauses should be included as part of the new selection. Any clauses\n * published to upstream selections will be relayed to the new selection.\n * @returns {Selection} The new Selection instance.\n */\n static crossfilter({ empty: empty4 = false, include = [] } = {}) {\n return create2({ cross: true, empty: empty4 }, include);\n }\n /**\n * Create a new Selection instance.\n * @param {SelectionResolver} [resolver] The selection resolution\n * strategy to apply.\n * @param {Selection[]} [include] Upstream selections whose clauses\n * should be included as part of this selection. Any clauses published\n * to these upstream selections will be relayed to this selection.\n */\n constructor(resolver = new SelectionResolver(), include = []) {\n super([]);\n this._resolved = this._value;\n this._resolver = resolver;\n this._relay = /* @__PURE__ */ new Set();\n if (Array.isArray(include)) {\n for (const sel of include) {\n sel._relay.add(this);\n }\n }\n }\n /**\n * Create a cloned copy of this Selection instance.\n * @returns {Selection} A clone of this selection.\n */\n clone() {\n const s2 = new _Selection(this._resolver);\n s2._value = s2._resolved = this._value;\n return s2;\n }\n /**\n * Create a clone of this Selection with clauses corresponding\n * to the provided source removed.\n * @param {*} source The clause source to remove.\n * @returns {Selection} A cloned and updated Selection.\n */\n remove(source) {\n const s2 = this.clone();\n s2._value = s2._resolved = s2._resolver.resolve(this._resolved, { source });\n s2._value.active = { source };\n return s2;\n }\n /**\n * The selection clause resolver.\n */\n get resolver() {\n return this._resolver;\n }\n /**\n * Indicate if this selection has a single resolution strategy.\n */\n get single() {\n return this._resolver.single;\n }\n /**\n * The current array of selection clauses.\n */\n get clauses() {\n return super.value;\n }\n /**\n * The current active (most recently updated) selection clause.\n */\n get active() {\n return this.clauses.active;\n }\n /**\n * The value corresponding to the current active selection clause.\n * This method ensures compatibility where a normal Param is expected.\n */\n get value() {\n return this.active?.value;\n }\n /**\n * The value corresponding to a given source. Returns undefined if\n * this selection does not include a clause from this source.\n * @param {*} source The clause source to look up the value for.\n */\n valueFor(source) {\n return this.clauses.find((c4) => c4.source === source)?.value;\n }\n /**\n * Emit an activate event with the given selection clause.\n * @param {*} clause The clause repesenting the potential activation.\n */\n activate(clause) {\n this.emit(\"activate\", clause);\n this._relay.forEach((sel) => sel.activate(clause));\n }\n /**\n * Update the selection with a new selection clause.\n * @param {*} clause The selection clause to add.\n * @returns {this} This Selection instance.\n */\n update(clause) {\n this._resolved = this._resolver.resolve(this._resolved, clause, true);\n this._resolved.active = clause;\n this._relay.forEach((sel) => sel.update(clause));\n return super.update(this._resolved);\n }\n /**\n * Upon value-typed updates, sets the current clause list to the\n * input value and returns the active clause value.\n * @param {string} type The event type.\n * @param {*} value The input event value.\n * @returns {*} For value-typed events, returns the active clause\n * values. Otherwise returns the input event value as-is.\n */\n willEmit(type2, value) {\n if (type2 === \"value\") {\n this._value = value;\n return this.value;\n }\n return value;\n }\n /**\n * Upon value-typed updates, returns a dispatch queue filter function.\n * The return value depends on the selection resolution strategy.\n * @param {string} type The event type.\n * @param {*} value The new event value that will be enqueued.\n * @returns {(value: *) => boolean|null} For value-typed events,\n * returns a dispatch queue filter function. Otherwise returns null.\n */\n emitQueueFilter(type2, value) {\n return type2 === \"value\" ? this._resolver.queueFilter(value) : null;\n }\n /**\n * Indicates if a selection clause should not be applied to a given client.\n * The return value depends on the selection resolution strategy.\n * @param {*} client The selection clause.\n * @param {*} clause The client to test.\n * @returns True if the client should be skipped, false otherwise.\n */\n skip(client, clause) {\n return this._resolver.skip(client, clause);\n }\n /**\n * Return a selection query predicate for the given client.\n * @param {*} client The client whose data may be filtered.\n * @param {boolean} [noSkip=false] Disable skipping of active\n * cross-filtered sources. If set true, the source of the active\n * clause in a cross-filtered selection will not be skipped.\n * @returns {*} The query predicate for filtering client data,\n * based on the current state of this selection.\n */\n predicate(client, noSkip = false) {\n const { clauses } = this;\n const active = noSkip ? null : clauses.active;\n return this._resolver.predicate(clauses, active, client);\n }\n};\nvar SelectionResolver = class {\n /**\n * Create a new selection resolved instance.\n * @param {object} [options] The resolution strategy options.\n * @param {boolean} [options.union=false] Boolean flag to indicate a union strategy.\n * If false, an intersection strategy is used.\n * @param {boolean} [options.cross=false] Boolean flag to indicate cross-filtering.\n * @param {boolean} [options.single=false] Boolean flag to indicate single clauses only.\n * @param {boolean} [options.empty=false] Boolean flag indicating if a lack\n * of clauses should correspond to an empty selection with no records. This\n * setting determines the default selection state.\n */\n constructor({ union: union2, cross: cross3, single, empty: empty4 } = {}) {\n this.union = !!union2;\n this.cross = !!cross3;\n this.single = !!single;\n this.empty = !!empty4;\n }\n /**\n * Resolve a list of selection clauses according to the resolution strategy.\n * @param {*[]} clauseList An array of selection clauses.\n * @param {*} clause A new selection clause to add.\n * @returns {*[]} An updated array of selection clauses.\n */\n resolve(clauseList, clause, reset = false) {\n const { source, predicate } = clause;\n const filtered = clauseList.filter((c4) => source !== c4.source);\n const clauses = this.single ? [] : filtered;\n if (this.single && reset) filtered.forEach((c4) => c4.source?.reset?.());\n if (predicate) clauses.push(clause);\n return clauses;\n }\n /**\n * Indicates if a selection clause should not be applied to a given client.\n * The return value depends on the resolution strategy.\n * @param {*} client The selection clause.\n * @param {*} clause The client to test.\n * @returns True if the client should be skipped, false otherwise.\n */\n skip(client, clause) {\n return this.cross && clause?.clients?.has(client);\n }\n /**\n * Return a selection query predicate for the given client.\n * @param {*[]} clauseList An array of selection clauses.\n * @param {*} active The current active selection clause.\n * @param {*} client The client whose data may be filtered.\n * @returns {*} The query predicate for filtering client data,\n * based on the current state of this selection.\n */\n predicate(clauseList, active, client) {\n const { empty: empty4, union: union2 } = this;\n if (empty4 && !clauseList.length) {\n return [\"FALSE\"];\n }\n if (this.skip(client, active)) return void 0;\n const predicates = clauseList.filter((clause) => !this.skip(client, clause)).map((clause) => clause.predicate);\n return union2 && predicates.length > 1 ? or(predicates) : predicates;\n }\n /**\n * Returns a filter function for queued selection updates.\n * @param {*} value The new event value that will be enqueued.\n * @returns {(value: *) => boolean|null} A dispatch queue filter\n * function, or null if all unemitted event values should be filtered.\n */\n queueFilter(value) {\n if (this.cross) {\n const source = value.active?.source;\n return (clauses) => clauses.active?.source !== source;\n }\n return null;\n }\n};\n\n// ../core/src/SelectionClause.js\nfunction clausePoint(field3, value, {\n source,\n clients = source ? /* @__PURE__ */ new Set([source]) : void 0\n}) {\n const predicate = value !== void 0 ? isNotDistinct(field3, literal(value)) : null;\n return {\n meta: { type: \"point\" },\n source,\n clients,\n value,\n predicate\n };\n}\nfunction clausePoints(fields, value, {\n source,\n clients = source ? /* @__PURE__ */ new Set([source]) : void 0\n}) {\n let predicate = null;\n if (value) {\n const clauses = value.map((vals) => {\n const list2 = vals.map((v2, i) => isNotDistinct(fields[i], literal(v2)));\n return list2.length > 1 ? and(list2) : list2[0];\n });\n predicate = clauses.length > 1 ? or(clauses) : clauses[0];\n }\n return {\n meta: { type: \"point\" },\n source,\n clients,\n value,\n predicate\n };\n}\nfunction clauseInterval(field3, value, {\n source,\n clients = source ? /* @__PURE__ */ new Set([source]) : void 0,\n bin: bin3,\n scale: scale3,\n pixelSize = 1\n}) {\n const predicate = value != null ? isBetween(field3, value) : null;\n const meta = { type: \"interval\", scales: scale3 && [scale3], bin: bin3, pixelSize };\n return { meta, source, clients, value, predicate };\n}\nfunction clauseIntervals(fields, value, {\n source,\n clients = source ? /* @__PURE__ */ new Set([source]) : void 0,\n bin: bin3,\n scales: scales2 = [],\n pixelSize = 1\n}) {\n const predicate = value != null ? and(fields.map((f, i) => isBetween(f, value[i]))) : null;\n const meta = { type: \"interval\", scales: scales2, bin: bin3, pixelSize };\n return { meta, source, clients, value, predicate };\n}\nvar MATCH_METHODS = { contains, prefix, suffix, regexp: regexp_matches };\nfunction clauseMatch(field3, value, {\n source,\n clients = void 0,\n method = \"contains\"\n}) {\n let fn = MATCH_METHODS[method];\n const predicate = value ? fn(field3, literal(value)) : null;\n const meta = { type: \"match\", method };\n return { meta, source, clients, value, predicate };\n}\n\n// ../core/src/util/is-arrow-table.js\nfunction isArrowTable(values2) {\n return typeof values2?.getChild === \"function\";\n}\n\n// ../core/src/util/synchronizer.js\nfunction synchronizer() {\n const set3 = /* @__PURE__ */ new Set();\n let done;\n let promise = new Promise((resolve) => done = resolve);\n return {\n /**\n * Mark an item as pending.\n * @param {*} item An item to synchronize on.\n */\n pending(item) {\n set3.add(item);\n },\n /**\n * Mark a pending item as ready, indicating it is\n * ready for a synchronized update.\n * @param {*} item An item to synchronize on.\n * @returns {boolean} True if the synchronizer is ready to\n * resolve, false otherwise.\n */\n ready(item) {\n set3.delete(item);\n return set3.size === 0;\n },\n /**\n * Resolve the current synchronization cycle, causing the synchronize\n * promise to resolve and thereby trigger downstream updates.\n */\n resolve() {\n promise = new Promise((resolve) => {\n done();\n done = resolve;\n });\n },\n /**\n * The promise for the current synchronization cycle.\n * @return {Promise} The synchronization promise.\n */\n get promise() {\n return promise;\n }\n };\n}\n\n// ../core/src/util/to-data-columns.js\nfunction toDataColumns(data) {\n return isArrowTable(data) ? arrowToColumns(data) : arrayToColumns(data);\n}\nfunction arrowToColumns(data) {\n const { numRows } = data;\n return { numRows, columns: data.toColumns() };\n}\nfunction arrayToColumns(data) {\n const numRows = data.length;\n if (typeof data[0] === \"object\") {\n const names = numRows ? Object.keys(data[0]) : [];\n const columns = {};\n if (names.length > 0) {\n names.forEach((name2) => {\n columns[name2] = data.map((d) => d[name2]);\n });\n }\n return { numRows, columns };\n } else {\n return { numRows, values: data };\n }\n}\n\n// ../vgplot/src/api.js\nvar api_exports = {};\n__export(api_exports, {\n Fixed: () => Fixed,\n Param: () => Param,\n Query: () => Query,\n Selection: () => Selection,\n agg: () => agg,\n align: () => align2,\n and: () => and,\n area: () => area2,\n areaX: () => areaX2,\n areaY: () => areaY2,\n argmax: () => argmax,\n argmin: () => argmin,\n arrayAgg: () => arrayAgg,\n arrow: () => arrow2,\n aspectRatio: () => aspectRatio,\n avg: () => avg,\n axis: () => axis2,\n axisFx: () => axisFx2,\n axisFy: () => axisFy2,\n axisX: () => axisX2,\n axisY: () => axisY2,\n barX: () => barX2,\n barY: () => barY2,\n bin: () => bin2,\n cast: () => cast,\n castDouble: () => castDouble,\n castInteger: () => castInteger,\n cell: () => cell2,\n cellX: () => cellX2,\n cellY: () => cellY2,\n centroid: () => centroid,\n centroidX: () => centroidX,\n centroidY: () => centroidY,\n circle: () => circle2,\n colorBase: () => colorBase,\n colorClamp: () => colorClamp,\n colorConstant: () => colorConstant2,\n colorDomain: () => colorDomain,\n colorExponent: () => colorExponent,\n colorInterpolate: () => colorInterpolate,\n colorLabel: () => colorLabel,\n colorLegend: () => colorLegend,\n colorN: () => colorN,\n colorNice: () => colorNice,\n colorPercent: () => colorPercent,\n colorPivot: () => colorPivot,\n colorRange: () => colorRange,\n colorReverse: () => colorReverse,\n colorScale: () => colorScale2,\n colorScheme: () => colorScheme2,\n colorSymmetric: () => colorSymmetric,\n colorTickFormat: () => colorTickFormat,\n colorZero: () => colorZero,\n column: () => column,\n contour: () => contour2,\n coordinator: () => coordinator,\n corr: () => corr,\n count: () => count,\n covarPop: () => covarPop,\n covariance: () => covariance,\n create: () => create,\n cume_dist: () => cume_dist,\n dateDay: () => dateDay2,\n dateMonth: () => dateMonth,\n dateMonthDay: () => dateMonthDay,\n delaunayLink: () => delaunayLink2,\n delaunayMesh: () => delaunayMesh2,\n denseLine: () => denseLine,\n dense_rank: () => dense_rank,\n density: () => density2,\n densityX: () => densityX,\n densityY: () => densityY,\n dot: () => dot2,\n dotX: () => dotX2,\n dotY: () => dotY2,\n entropy: () => entropy,\n eq: () => eq,\n errorbarX: () => errorbarX,\n errorbarY: () => errorbarY,\n facetGrid: () => facetGrid,\n facetLabel: () => facetLabel,\n facetMargin: () => facetMargin,\n facetMarginBottom: () => facetMarginBottom,\n facetMarginLeft: () => facetMarginLeft,\n facetMarginRight: () => facetMarginRight,\n facetMarginTop: () => facetMarginTop,\n first: () => first,\n first_value: () => first_value,\n frame: () => frame3,\n from: () => from,\n fxAlign: () => fxAlign,\n fxAriaDescription: () => fxAriaDescription,\n fxAriaLabel: () => fxAriaLabel,\n fxAxis: () => fxAxis,\n fxDomain: () => fxDomain,\n fxFontVariant: () => fxFontVariant,\n fxGrid: () => fxGrid,\n fxInset: () => fxInset,\n fxInsetLeft: () => fxInsetLeft,\n fxInsetRight: () => fxInsetRight,\n fxLabel: () => fxLabel,\n fxLabelAnchor: () => fxLabelAnchor,\n fxLabelOffset: () => fxLabelOffset,\n fxLine: () => fxLine,\n fxPadding: () => fxPadding,\n fxPaddingInner: () => fxPaddingInner,\n fxPaddingOuter: () => fxPaddingOuter,\n fxRange: () => fxRange,\n fxReverse: () => fxReverse,\n fxRound: () => fxRound,\n fxTickFormat: () => fxTickFormat,\n fxTickPadding: () => fxTickPadding,\n fxTickRotate: () => fxTickRotate,\n fxTickSize: () => fxTickSize,\n fxTickSpacing: () => fxTickSpacing,\n fxTicks: () => fxTicks,\n fyAlign: () => fyAlign,\n fyAriaDescription: () => fyAriaDescription,\n fyAriaLabel: () => fyAriaLabel,\n fyAxis: () => fyAxis,\n fyDomain: () => fyDomain,\n fyFontVariant: () => fyFontVariant,\n fyGrid: () => fyGrid,\n fyInset: () => fyInset,\n fyInsetBottom: () => fyInsetBottom,\n fyInsetTop: () => fyInsetTop,\n fyLabel: () => fyLabel,\n fyLabelAnchor: () => fyLabelAnchor,\n fyLabelOffset: () => fyLabelOffset,\n fyLine: () => fyLine,\n fyPadding: () => fyPadding,\n fyPaddingInner: () => fyPaddingInner,\n fyPaddingOuter: () => fyPaddingOuter,\n fyRange: () => fyRange,\n fyReverse: () => fyReverse,\n fyRound: () => fyRound,\n fyTickFormat: () => fyTickFormat,\n fyTickPadding: () => fyTickPadding,\n fyTickRotate: () => fyTickRotate,\n fyTickSize: () => fyTickSize,\n fyTickSpacing: () => fyTickSpacing,\n fyTicks: () => fyTicks,\n geo: () => geo2,\n geojson: () => geojson,\n graticule: () => graticule3,\n grid: () => grid,\n gridFx: () => gridFx2,\n gridFy: () => gridFy2,\n gridX: () => gridX2,\n gridY: () => gridY2,\n gt: () => gt,\n gte: () => gte,\n hconcat: () => hconcat,\n heatmap: () => heatmap,\n height: () => height,\n hexagon: () => hexagon2,\n hexbin: () => hexbin2,\n hexgrid: () => hexgrid2,\n highlight: () => highlight,\n hspace: () => hspace,\n hull: () => hull2,\n image: () => image2,\n inset: () => inset,\n intervalX: () => intervalX,\n intervalXY: () => intervalXY,\n intervalY: () => intervalY,\n isBetween: () => isBetween,\n isDistinct: () => isDistinct,\n isNotBetween: () => isNotBetween,\n isNotDistinct: () => isNotDistinct,\n isNotNull: () => isNotNull,\n isNull: () => isNull,\n kurtosis: () => kurtosis,\n label: () => label,\n lag: () => lag,\n last: () => last,\n last_value: () => last_value,\n lead: () => lead,\n lengthBase: () => lengthBase,\n lengthClamp: () => lengthClamp,\n lengthConstant: () => lengthConstant,\n lengthDomain: () => lengthDomain,\n lengthExponent: () => lengthExponent,\n lengthNice: () => lengthNice,\n lengthPercent: () => lengthPercent,\n lengthRange: () => lengthRange,\n lengthScale: () => lengthScale,\n lengthZero: () => lengthZero,\n line: () => line2,\n lineX: () => lineX2,\n lineY: () => lineY2,\n link: () => link3,\n literal: () => literal,\n loadCSV: () => loadCSV,\n loadExtension: () => loadExtension,\n loadJSON: () => loadJSON,\n loadObjects: () => loadObjects,\n loadParquet: () => loadParquet,\n loadSpatial: () => loadSpatial,\n lt: () => lt,\n lte: () => lte,\n mad: () => mad,\n margin: () => margin,\n marginBottom: () => marginBottom,\n marginLeft: () => marginLeft,\n marginRight: () => marginRight,\n marginTop: () => marginTop,\n margins: () => margins,\n max: () => max,\n median: () => median,\n menu: () => menu2,\n min: () => min,\n mode: () => mode,\n name: () => name,\n nearest: () => nearest,\n nearestX: () => nearestX,\n nearestY: () => nearestY,\n neq: () => neq,\n not: () => not,\n nth_value: () => nth_value,\n ntile: () => ntile,\n opacityBase: () => opacityBase,\n opacityClamp: () => opacityClamp,\n opacityConstant: () => opacityConstant,\n opacityDomain: () => opacityDomain,\n opacityExponent: () => opacityExponent,\n opacityLabel: () => opacityLabel,\n opacityLegend: () => opacityLegend,\n opacityNice: () => opacityNice,\n opacityPercent: () => opacityPercent,\n opacityRange: () => opacityRange,\n opacityReverse: () => opacityReverse,\n opacityScale: () => opacityScale,\n opacityTickFormat: () => opacityTickFormat,\n opacityZero: () => opacityZero,\n or: () => or,\n padding: () => padding,\n pan: () => pan,\n panX: () => panX,\n panY: () => panY,\n panZoom: () => panZoom,\n panZoomX: () => panZoomX,\n panZoomY: () => panZoomY,\n percent_rank: () => percent_rank,\n plot: () => plot2,\n product: () => product,\n projectionClip: () => projectionClip,\n projectionDomain: () => projectionDomain,\n projectionInset: () => projectionInset,\n projectionInsetBottom: () => projectionInsetBottom,\n projectionInsetLeft: () => projectionInsetLeft,\n projectionInsetRight: () => projectionInsetRight,\n projectionInsetTop: () => projectionInsetTop,\n projectionParallels: () => projectionParallels,\n projectionPrecision: () => projectionPrecision,\n projectionRotate: () => projectionRotate,\n projectionType: () => projectionType,\n quantile: () => quantile,\n rBase: () => rBase,\n rClamp: () => rClamp,\n rConstant: () => rConstant,\n rDomain: () => rDomain,\n rExponent: () => rExponent,\n rLabel: () => rLabel,\n rNice: () => rNice,\n rPercent: () => rPercent,\n rRange: () => rRange,\n rScale: () => rScale,\n rZero: () => rZero,\n rank: () => rank,\n raster: () => raster2,\n rasterTile: () => rasterTile,\n rect: () => rect2,\n rectX: () => rectX2,\n rectY: () => rectY2,\n regressionY: () => regressionY,\n row_number: () => row_number,\n ruleX: () => ruleX2,\n ruleY: () => ruleY2,\n search: () => search2,\n skewness: () => skewness,\n slider: () => slider2,\n sphere: () => sphere2,\n spike: () => spike2,\n sql: () => sql,\n stddev: () => stddev,\n stddevPop: () => stddevPop,\n stringAgg: () => stringAgg,\n style: () => style,\n sum: () => sum,\n symbolDomain: () => symbolDomain,\n symbolLegend: () => symbolLegend,\n symbolRange: () => symbolRange,\n symbolScale: () => symbolScale,\n table: () => table2,\n text: () => text2,\n textX: () => textX2,\n textY: () => textY2,\n tickX: () => tickX2,\n tickY: () => tickY2,\n toggle: () => toggle,\n toggleColor: () => toggleColor,\n toggleX: () => toggleX,\n toggleY: () => toggleY,\n toggleZ: () => toggleZ,\n varPop: () => varPop,\n variance: () => variance,\n vconcat: () => vconcat,\n vector: () => vector2,\n vectorX: () => vectorX2,\n vectorY: () => vectorY2,\n voronoi: () => voronoi2,\n voronoiMesh: () => voronoiMesh2,\n vspace: () => vspace,\n width: () => width,\n xAlign: () => xAlign,\n xAriaDescription: () => xAriaDescription,\n xAriaLabel: () => xAriaLabel,\n xAxis: () => xAxis,\n xBase: () => xBase,\n xClamp: () => xClamp,\n xConstant: () => xConstant,\n xDomain: () => xDomain,\n xExponent: () => xExponent,\n xFontVariant: () => xFontVariant,\n xGrid: () => xGrid,\n xInset: () => xInset,\n xInsetLeft: () => xInsetLeft,\n xInsetRight: () => xInsetRight,\n xLabel: () => xLabel,\n xLabelAnchor: () => xLabelAnchor,\n xLabelArrow: () => xLabelArrow,\n xLabelOffset: () => xLabelOffset,\n xLine: () => xLine,\n xNice: () => xNice,\n xPadding: () => xPadding,\n xPaddingInner: () => xPaddingInner,\n xPaddingOuter: () => xPaddingOuter,\n xPercent: () => xPercent,\n xRange: () => xRange,\n xReverse: () => xReverse,\n xRound: () => xRound,\n xScale: () => xScale,\n xTickFormat: () => xTickFormat,\n xTickPadding: () => xTickPadding,\n xTickRotate: () => xTickRotate,\n xTickSize: () => xTickSize,\n xTickSpacing: () => xTickSpacing,\n xTicks: () => xTicks,\n xZero: () => xZero,\n xyDomain: () => xyDomain,\n yAlign: () => yAlign,\n yAriaDescription: () => yAriaDescription,\n yAriaLabel: () => yAriaLabel,\n yAxis: () => yAxis,\n yBase: () => yBase,\n yClamp: () => yClamp,\n yConstant: () => yConstant,\n yDomain: () => yDomain,\n yExponent: () => yExponent,\n yFontVariant: () => yFontVariant,\n yGrid: () => yGrid,\n yInset: () => yInset,\n yInsetBottom: () => yInsetBottom,\n yInsetTop: () => yInsetTop,\n yLabel: () => yLabel,\n yLabelAnchor: () => yLabelAnchor,\n yLabelArrow: () => yLabelArrow,\n yLabelOffset: () => yLabelOffset,\n yLine: () => yLine,\n yNice: () => yNice,\n yPadding: () => yPadding,\n yPaddingInner: () => yPaddingInner,\n yPaddingOuter: () => yPaddingOuter,\n yPercent: () => yPercent,\n yRange: () => yRange,\n yReverse: () => yReverse,\n yRound: () => yRound,\n yScale: () => yScale,\n yTickFormat: () => yTickFormat,\n yTickPadding: () => yTickPadding,\n yTickRotate: () => yTickRotate,\n yTickSize: () => yTickSize,\n yTickSpacing: () => yTickSpacing,\n yTicks: () => yTicks,\n yZero: () => yZero\n});\n\n// ../plot/src/symbols.js\nvar Fixed = Symbol(\"Fixed\");\nvar Transient = Symbol(\"Transient\");\nvar Transform = Symbol(\"Transform\");\n\n// ../../node_modules/@observablehq/plot/src/index.js\nvar src_exports = {};\n__export(src_exports, {\n Area: () => Area,\n Arrow: () => Arrow,\n BarX: () => BarX,\n BarY: () => BarY,\n Cell: () => Cell,\n Contour: () => Contour,\n Density: () => Density,\n Dot: () => Dot,\n Frame: () => Frame,\n Geo: () => Geo,\n Hexgrid: () => Hexgrid,\n Image: () => Image,\n Line: () => Line,\n Link: () => Link,\n Mark: () => Mark,\n Raster: () => Raster,\n Rect: () => Rect,\n RuleX: () => RuleX,\n RuleY: () => RuleY,\n Text: () => Text,\n TickX: () => TickX,\n TickY: () => TickY,\n Tip: () => Tip,\n Vector: () => Vector,\n WaffleX: () => WaffleX,\n WaffleY: () => WaffleY,\n area: () => area,\n areaX: () => areaX,\n areaY: () => areaY,\n arrow: () => arrow,\n auto: () => auto,\n autoSpec: () => autoSpec,\n axisFx: () => axisFx,\n axisFy: () => axisFy,\n axisX: () => axisX,\n axisY: () => axisY,\n barX: () => barX,\n barY: () => barY,\n bin: () => bin,\n binX: () => binX,\n binY: () => binY,\n bollinger: () => bollinger,\n bollingerX: () => bollingerX,\n bollingerY: () => bollingerY,\n boxX: () => boxX,\n boxY: () => boxY,\n cell: () => cell,\n cellX: () => cellX,\n cellY: () => cellY,\n centroid: () => centroid2,\n circle: () => circle,\n cluster: () => cluster,\n column: () => column2,\n contour: () => contour,\n crosshair: () => crosshair,\n crosshairX: () => crosshairX,\n crosshairY: () => crosshairY,\n delaunayLink: () => delaunayLink,\n delaunayMesh: () => delaunayMesh,\n density: () => density,\n differenceX: () => differenceX,\n differenceY: () => differenceY,\n dodgeX: () => dodgeX,\n dodgeY: () => dodgeY,\n dot: () => dot,\n dotX: () => dotX,\n dotY: () => dotY,\n filter: () => filter2,\n find: () => find2,\n formatIsoDate: () => formatIsoDate,\n formatMonth: () => formatMonth,\n formatNumber: () => formatNumber,\n formatWeekday: () => formatWeekday,\n frame: () => frame2,\n geo: () => geo,\n geoCentroid: () => geoCentroid,\n graticule: () => graticule2,\n gridFx: () => gridFx,\n gridFy: () => gridFy,\n gridX: () => gridX,\n gridY: () => gridY,\n group: () => group2,\n groupX: () => groupX,\n groupY: () => groupY,\n groupZ: () => groupZ,\n hexagon: () => hexagon,\n hexbin: () => hexbin,\n hexgrid: () => hexgrid,\n hull: () => hull,\n identity: () => identity7,\n image: () => image,\n indexOf: () => indexOf,\n initializer: () => initializer,\n interpolateNearest: () => interpolateNearest,\n interpolateNone: () => interpolateNone,\n interpolatorBarycentric: () => interpolatorBarycentric,\n interpolatorRandomWalk: () => interpolatorRandomWalk,\n legend: () => legend,\n line: () => line,\n lineX: () => lineX,\n lineY: () => lineY,\n linearRegressionX: () => linearRegressionX,\n linearRegressionY: () => linearRegressionY,\n link: () => link2,\n map: () => map4,\n mapX: () => mapX,\n mapY: () => mapY,\n marks: () => marks,\n normalize: () => normalize3,\n normalizeX: () => normalizeX,\n normalizeY: () => normalizeY,\n numberInterval: () => numberInterval,\n plot: () => plot,\n pointer: () => pointer,\n pointerX: () => pointerX,\n pointerY: () => pointerY,\n raster: () => raster,\n rect: () => rect,\n rectX: () => rectX,\n rectY: () => rectY,\n reverse: () => reverse2,\n ruleX: () => ruleX,\n ruleY: () => ruleY,\n scale: () => scale2,\n select: () => select,\n selectFirst: () => selectFirst,\n selectLast: () => selectLast,\n selectMaxX: () => selectMaxX,\n selectMaxY: () => selectMaxY,\n selectMinX: () => selectMinX,\n selectMinY: () => selectMinY,\n shiftX: () => shiftX,\n shiftY: () => shiftY,\n shuffle: () => shuffle,\n sort: () => sort2,\n sphere: () => sphere,\n spike: () => spike,\n stackX: () => stackX,\n stackX1: () => stackX1,\n stackX2: () => stackX2,\n stackY: () => stackY,\n stackY1: () => stackY1,\n stackY2: () => stackY2,\n text: () => text,\n textX: () => textX,\n textY: () => textY,\n tickX: () => tickX,\n tickY: () => tickY,\n timeInterval: () => timeInterval2,\n tip: () => tip,\n transform: () => basic,\n tree: () => tree,\n treeLink: () => treeLink,\n treeNode: () => treeNode,\n utcInterval: () => utcInterval,\n valueof: () => valueof,\n vector: () => vector,\n vectorX: () => vectorX,\n vectorY: () => vectorY,\n voronoi: () => voronoi,\n voronoiMesh: () => voronoiMesh,\n waffleX: () => waffleX,\n waffleY: () => waffleY,\n window: () => window2,\n windowX: () => windowX,\n windowY: () => windowY\n});\n\n// ../../node_modules/d3-array/src/ascending.js\nfunction ascending(a2, b) {\n return a2 == null || b == null ? NaN : a2 < b ? -1 : a2 > b ? 1 : a2 >= b ? 0 : NaN;\n}\n\n// ../../node_modules/d3-array/src/descending.js\nfunction descending(a2, b) {\n return a2 == null || b == null ? NaN : b < a2 ? -1 : b > a2 ? 1 : b >= a2 ? 0 : NaN;\n}\n\n// ../../node_modules/d3-array/src/bisector.js\nfunction bisector(f) {\n let compare1, compare2, delta;\n if (f.length !== 2) {\n compare1 = ascending;\n compare2 = (d, x3) => ascending(f(d), x3);\n delta = (d, x3) => f(d) - x3;\n } else {\n compare1 = f === ascending || f === descending ? f : zero;\n compare2 = f;\n delta = f;\n }\n function left2(a2, x3, lo = 0, hi = a2.length) {\n if (lo < hi) {\n if (compare1(x3, x3) !== 0) return hi;\n do {\n const mid2 = lo + hi >>> 1;\n if (compare2(a2[mid2], x3) < 0) lo = mid2 + 1;\n else hi = mid2;\n } while (lo < hi);\n }\n return lo;\n }\n function right2(a2, x3, lo = 0, hi = a2.length) {\n if (lo < hi) {\n if (compare1(x3, x3) !== 0) return hi;\n do {\n const mid2 = lo + hi >>> 1;\n if (compare2(a2[mid2], x3) <= 0) lo = mid2 + 1;\n else hi = mid2;\n } while (lo < hi);\n }\n return lo;\n }\n function center2(a2, x3, lo = 0, hi = a2.length) {\n const i = left2(a2, x3, lo, hi - 1);\n return i > lo && delta(a2[i - 1], x3) > -delta(a2[i], x3) ? i - 1 : i;\n }\n return { left: left2, center: center2, right: right2 };\n}\nfunction zero() {\n return 0;\n}\n\n// ../../node_modules/d3-array/src/number.js\nfunction number(x3) {\n return x3 === null ? NaN : +x3;\n}\nfunction* numbers(values2, valueof2) {\n if (valueof2 === void 0) {\n for (let value of values2) {\n if (value != null && (value = +value) >= value) {\n yield value;\n }\n }\n } else {\n let index2 = -1;\n for (let value of values2) {\n if ((value = valueof2(value, ++index2, values2)) != null && (value = +value) >= value) {\n yield value;\n }\n }\n }\n}\n\n// ../../node_modules/d3-array/src/bisect.js\nvar ascendingBisect = bisector(ascending);\nvar bisectRight = ascendingBisect.right;\nvar bisectLeft = ascendingBisect.left;\nvar bisectCenter = bisector(number).center;\nvar bisect_default = bisectRight;\n\n// ../../node_modules/d3-array/src/blur.js\nvar blur2 = Blur2(blurf);\nvar blurImage = Blur2(blurfImage);\nfunction Blur2(blur3) {\n return function(data, rx, ry = rx) {\n if (!((rx = +rx) >= 0)) throw new RangeError(\"invalid rx\");\n if (!((ry = +ry) >= 0)) throw new RangeError(\"invalid ry\");\n let { data: values2, width: width2, height: height2 } = data;\n if (!((width2 = Math.floor(width2)) >= 0)) throw new RangeError(\"invalid width\");\n if (!((height2 = Math.floor(height2 !== void 0 ? height2 : values2.length / width2)) >= 0)) throw new RangeError(\"invalid height\");\n if (!width2 || !height2 || !rx && !ry) return data;\n const blurx = rx && blur3(rx);\n const blury = ry && blur3(ry);\n const temp = values2.slice();\n if (blurx && blury) {\n blurh(blurx, temp, values2, width2, height2);\n blurh(blurx, values2, temp, width2, height2);\n blurh(blurx, temp, values2, width2, height2);\n blurv(blury, values2, temp, width2, height2);\n blurv(blury, temp, values2, width2, height2);\n blurv(blury, values2, temp, width2, height2);\n } else if (blurx) {\n blurh(blurx, values2, temp, width2, height2);\n blurh(blurx, temp, values2, width2, height2);\n blurh(blurx, values2, temp, width2, height2);\n } else if (blury) {\n blurv(blury, values2, temp, width2, height2);\n blurv(blury, temp, values2, width2, height2);\n blurv(blury, values2, temp, width2, height2);\n }\n return data;\n };\n}\nfunction blurh(blur3, T, S, w, h) {\n for (let y3 = 0, n = w * h; y3 < n; ) {\n blur3(T, S, y3, y3 += w, 1);\n }\n}\nfunction blurv(blur3, T, S, w, h) {\n for (let x3 = 0, n = w * h; x3 < w; ++x3) {\n blur3(T, S, x3, x3 + n, w);\n }\n}\nfunction blurfImage(radius2) {\n const blur3 = blurf(radius2);\n return (T, S, start2, stop, step) => {\n start2 <<= 2, stop <<= 2, step <<= 2;\n blur3(T, S, start2 + 0, stop + 0, step);\n blur3(T, S, start2 + 1, stop + 1, step);\n blur3(T, S, start2 + 2, stop + 2, step);\n blur3(T, S, start2 + 3, stop + 3, step);\n };\n}\nfunction blurf(radius2) {\n const radius0 = Math.floor(radius2);\n if (radius0 === radius2) return bluri(radius2);\n const t = radius2 - radius0;\n const w = 2 * radius2 + 1;\n return (T, S, start2, stop, step) => {\n if (!((stop -= step) >= start2)) return;\n let sum4 = radius0 * S[start2];\n const s0 = step * radius0;\n const s1 = s0 + step;\n for (let i = start2, j = start2 + s0; i < j; i += step) {\n sum4 += S[Math.min(stop, i)];\n }\n for (let i = start2, j = stop; i <= j; i += step) {\n sum4 += S[Math.min(stop, i + s0)];\n T[i] = (sum4 + t * (S[Math.max(start2, i - s1)] + S[Math.min(stop, i + s1)])) / w;\n sum4 -= S[Math.max(start2, i - s0)];\n }\n };\n}\nfunction bluri(radius2) {\n const w = 2 * radius2 + 1;\n return (T, S, start2, stop, step) => {\n if (!((stop -= step) >= start2)) return;\n let sum4 = radius2 * S[start2];\n const s2 = step * radius2;\n for (let i = start2, j = start2 + s2; i < j; i += step) {\n sum4 += S[Math.min(stop, i)];\n }\n for (let i = start2, j = stop; i <= j; i += step) {\n sum4 += S[Math.min(stop, i + s2)];\n T[i] = sum4 / w;\n sum4 -= S[Math.max(start2, i - s2)];\n }\n };\n}\n\n// ../../node_modules/d3-array/src/count.js\nfunction count2(values2, valueof2) {\n let count4 = 0;\n if (valueof2 === void 0) {\n for (let value of values2) {\n if (value != null && (value = +value) >= value) {\n ++count4;\n }\n }\n } else {\n let index2 = -1;\n for (let value of values2) {\n if ((value = valueof2(value, ++index2, values2)) != null && (value = +value) >= value) {\n ++count4;\n }\n }\n }\n return count4;\n}\n\n// ../../node_modules/d3-array/src/cross.js\nfunction length2(array4) {\n return array4.length | 0;\n}\nfunction empty(length4) {\n return !(length4 > 0);\n}\nfunction arrayify(values2) {\n return typeof values2 !== \"object\" || \"length\" in values2 ? values2 : Array.from(values2);\n}\nfunction reducer(reduce) {\n return (values2) => reduce(...values2);\n}\nfunction cross(...values2) {\n const reduce = typeof values2[values2.length - 1] === \"function\" && reducer(values2.pop());\n values2 = values2.map(arrayify);\n const lengths = values2.map(length2);\n const j = values2.length - 1;\n const index2 = new Array(j + 1).fill(0);\n const product2 = [];\n if (j < 0 || lengths.some(empty)) return product2;\n while (true) {\n product2.push(index2.map((j2, i2) => values2[i2][j2]));\n let i = j;\n while (++index2[i] === lengths[i]) {\n if (i === 0) return reduce ? product2.map(reduce) : product2;\n index2[i--] = 0;\n }\n }\n}\n\n// ../../node_modules/d3-array/src/cumsum.js\nfunction cumsum(values2, valueof2) {\n var sum4 = 0, index2 = 0;\n return Float64Array.from(values2, valueof2 === void 0 ? (v2) => sum4 += +v2 || 0 : (v2) => sum4 += +valueof2(v2, index2++, values2) || 0);\n}\n\n// ../../node_modules/d3-array/src/variance.js\nfunction variance2(values2, valueof2) {\n let count4 = 0;\n let delta;\n let mean3 = 0;\n let sum4 = 0;\n if (valueof2 === void 0) {\n for (let value of values2) {\n if (value != null && (value = +value) >= value) {\n delta = value - mean3;\n mean3 += delta / ++count4;\n sum4 += delta * (value - mean3);\n }\n }\n } else {\n let index2 = -1;\n for (let value of values2) {\n if ((value = valueof2(value, ++index2, values2)) != null && (value = +value) >= value) {\n delta = value - mean3;\n mean3 += delta / ++count4;\n sum4 += delta * (value - mean3);\n }\n }\n }\n if (count4 > 1) return sum4 / (count4 - 1);\n}\n\n// ../../node_modules/d3-array/src/deviation.js\nfunction deviation(values2, valueof2) {\n const v2 = variance2(values2, valueof2);\n return v2 ? Math.sqrt(v2) : v2;\n}\n\n// ../../node_modules/d3-array/src/extent.js\nfunction extent(values2, valueof2) {\n let min5;\n let max4;\n if (valueof2 === void 0) {\n for (const value of values2) {\n if (value != null) {\n if (min5 === void 0) {\n if (value >= value) min5 = max4 = value;\n } else {\n if (min5 > value) min5 = value;\n if (max4 < value) max4 = value;\n }\n }\n }\n } else {\n let index2 = -1;\n for (let value of values2) {\n if ((value = valueof2(value, ++index2, values2)) != null) {\n if (min5 === void 0) {\n if (value >= value) min5 = max4 = value;\n } else {\n if (min5 > value) min5 = value;\n if (max4 < value) max4 = value;\n }\n }\n }\n }\n return [min5, max4];\n}\n\n// ../../node_modules/d3-array/src/fsum.js\nvar Adder = class {\n constructor() {\n this._partials = new Float64Array(32);\n this._n = 0;\n }\n add(x3) {\n const p = this._partials;\n let i = 0;\n for (let j = 0; j < this._n && j < 32; j++) {\n const y3 = p[j], hi = x3 + y3, lo = Math.abs(x3) < Math.abs(y3) ? x3 - (hi - y3) : y3 - (hi - x3);\n if (lo) p[i++] = lo;\n x3 = hi;\n }\n p[i] = x3;\n this._n = i + 1;\n return this;\n }\n valueOf() {\n const p = this._partials;\n let n = this._n, x3, y3, lo, hi = 0;\n if (n > 0) {\n hi = p[--n];\n while (n > 0) {\n x3 = hi;\n y3 = p[--n];\n hi = x3 + y3;\n lo = y3 - (hi - x3);\n if (lo) break;\n }\n if (n > 0 && (lo < 0 && p[n - 1] < 0 || lo > 0 && p[n - 1] > 0)) {\n y3 = lo * 2;\n x3 = hi + y3;\n if (y3 == x3 - hi) hi = x3;\n }\n }\n return hi;\n }\n};\n\n// ../../node_modules/internmap/src/index.js\nvar InternMap = class extends Map {\n constructor(entries, key = keyof) {\n super();\n Object.defineProperties(this, { _intern: { value: /* @__PURE__ */ new Map() }, _key: { value: key } });\n if (entries != null) for (const [key2, value] of entries) this.set(key2, value);\n }\n get(key) {\n return super.get(intern_get(this, key));\n }\n has(key) {\n return super.has(intern_get(this, key));\n }\n set(key, value) {\n return super.set(intern_set(this, key), value);\n }\n delete(key) {\n return super.delete(intern_delete(this, key));\n }\n};\nvar InternSet = class extends Set {\n constructor(values2, key = keyof) {\n super();\n Object.defineProperties(this, { _intern: { value: /* @__PURE__ */ new Map() }, _key: { value: key } });\n if (values2 != null) for (const value of values2) this.add(value);\n }\n has(value) {\n return super.has(intern_get(this, value));\n }\n add(value) {\n return super.add(intern_set(this, value));\n }\n delete(value) {\n return super.delete(intern_delete(this, value));\n }\n};\nfunction intern_get({ _intern, _key }, value) {\n const key = _key(value);\n return _intern.has(key) ? _intern.get(key) : value;\n}\nfunction intern_set({ _intern, _key }, value) {\n const key = _key(value);\n if (_intern.has(key)) return _intern.get(key);\n _intern.set(key, value);\n return value;\n}\nfunction intern_delete({ _intern, _key }, value) {\n const key = _key(value);\n if (_intern.has(key)) {\n value = _intern.get(key);\n _intern.delete(key);\n }\n return value;\n}\nfunction keyof(value) {\n return value !== null && typeof value === \"object\" ? value.valueOf() : value;\n}\n\n// ../../node_modules/d3-array/src/identity.js\nfunction identity2(x3) {\n return x3;\n}\n\n// ../../node_modules/d3-array/src/group.js\nfunction group(values2, ...keys) {\n return nest(values2, identity2, identity2, keys);\n}\nfunction rollup(values2, reduce, ...keys) {\n return nest(values2, identity2, reduce, keys);\n}\nfunction rollups(values2, reduce, ...keys) {\n return nest(values2, Array.from, reduce, keys);\n}\nfunction nest(values2, map5, reduce, keys) {\n return function regroup(values3, i) {\n if (i >= keys.length) return reduce(values3);\n const groups2 = new InternMap();\n const keyof3 = keys[i++];\n let index2 = -1;\n for (const value of values3) {\n const key = keyof3(value, ++index2, values3);\n const group3 = groups2.get(key);\n if (group3) group3.push(value);\n else groups2.set(key, [value]);\n }\n for (const [key, values4] of groups2) {\n groups2.set(key, regroup(values4, i));\n }\n return map5(groups2);\n }(values2, 0);\n}\n\n// ../../node_modules/d3-array/src/permute.js\nfunction permute(source, keys) {\n return Array.from(keys, (key) => source[key]);\n}\n\n// ../../node_modules/d3-array/src/sort.js\nfunction sort(values2, ...F) {\n if (typeof values2[Symbol.iterator] !== \"function\") throw new TypeError(\"values is not iterable\");\n values2 = Array.from(values2);\n let [f] = F;\n if (f && f.length !== 2 || F.length > 1) {\n const index2 = Uint32Array.from(values2, (d, i) => i);\n if (F.length > 1) {\n F = F.map((f2) => values2.map(f2));\n index2.sort((i, j) => {\n for (const f2 of F) {\n const c4 = ascendingDefined(f2[i], f2[j]);\n if (c4) return c4;\n }\n });\n } else {\n f = values2.map(f);\n index2.sort((i, j) => ascendingDefined(f[i], f[j]));\n }\n return permute(values2, index2);\n }\n return values2.sort(compareDefined(f));\n}\nfunction compareDefined(compare = ascending) {\n if (compare === ascending) return ascendingDefined;\n if (typeof compare !== \"function\") throw new TypeError(\"compare is not a function\");\n return (a2, b) => {\n const x3 = compare(a2, b);\n if (x3 || x3 === 0) return x3;\n return (compare(b, b) === 0) - (compare(a2, a2) === 0);\n };\n}\nfunction ascendingDefined(a2, b) {\n return (a2 == null || !(a2 >= a2)) - (b == null || !(b >= b)) || (a2 < b ? -1 : a2 > b ? 1 : 0);\n}\n\n// ../../node_modules/d3-array/src/groupSort.js\nfunction groupSort(values2, reduce, key) {\n return (reduce.length !== 2 ? sort(rollup(values2, reduce, key), ([ak, av], [bk, bv]) => ascending(av, bv) || ascending(ak, bk)) : sort(group(values2, key), ([ak, av], [bk, bv]) => reduce(av, bv) || ascending(ak, bk))).map(([key2]) => key2);\n}\n\n// ../../node_modules/d3-array/src/ticks.js\nvar e10 = Math.sqrt(50);\nvar e5 = Math.sqrt(10);\nvar e2 = Math.sqrt(2);\nfunction tickSpec(start2, stop, count4) {\n const step = (stop - start2) / Math.max(0, count4), power = Math.floor(Math.log10(step)), error2 = step / Math.pow(10, power), factor = error2 >= e10 ? 10 : error2 >= e5 ? 5 : error2 >= e2 ? 2 : 1;\n let i1, i2, inc2;\n if (power < 0) {\n inc2 = Math.pow(10, -power) / factor;\n i1 = Math.round(start2 * inc2);\n i2 = Math.round(stop * inc2);\n if (i1 / inc2 < start2) ++i1;\n if (i2 / inc2 > stop) --i2;\n inc2 = -inc2;\n } else {\n inc2 = Math.pow(10, power) * factor;\n i1 = Math.round(start2 / inc2);\n i2 = Math.round(stop / inc2);\n if (i1 * inc2 < start2) ++i1;\n if (i2 * inc2 > stop) --i2;\n }\n if (i2 < i1 && 0.5 <= count4 && count4 < 2) return tickSpec(start2, stop, count4 * 2);\n return [i1, i2, inc2];\n}\nfunction ticks(start2, stop, count4) {\n stop = +stop, start2 = +start2, count4 = +count4;\n if (!(count4 > 0)) return [];\n if (start2 === stop) return [start2];\n const reverse3 = stop < start2, [i1, i2, inc2] = reverse3 ? tickSpec(stop, start2, count4) : tickSpec(start2, stop, count4);\n if (!(i2 >= i1)) return [];\n const n = i2 - i1 + 1, ticks2 = new Array(n);\n if (reverse3) {\n if (inc2 < 0) for (let i = 0; i < n; ++i) ticks2[i] = (i2 - i) / -inc2;\n else for (let i = 0; i < n; ++i) ticks2[i] = (i2 - i) * inc2;\n } else {\n if (inc2 < 0) for (let i = 0; i < n; ++i) ticks2[i] = (i1 + i) / -inc2;\n else for (let i = 0; i < n; ++i) ticks2[i] = (i1 + i) * inc2;\n }\n return ticks2;\n}\nfunction tickIncrement(start2, stop, count4) {\n stop = +stop, start2 = +start2, count4 = +count4;\n return tickSpec(start2, stop, count4)[2];\n}\nfunction tickStep(start2, stop, count4) {\n stop = +stop, start2 = +start2, count4 = +count4;\n const reverse3 = stop < start2, inc2 = reverse3 ? tickIncrement(stop, start2, count4) : tickIncrement(start2, stop, count4);\n return (reverse3 ? -1 : 1) * (inc2 < 0 ? 1 / -inc2 : inc2);\n}\n\n// ../../node_modules/d3-array/src/nice.js\nfunction nice(start2, stop, count4) {\n let prestep;\n while (true) {\n const step = tickIncrement(start2, stop, count4);\n if (step === prestep || step === 0 || !isFinite(step)) {\n return [start2, stop];\n } else if (step > 0) {\n start2 = Math.floor(start2 / step) * step;\n stop = Math.ceil(stop / step) * step;\n } else if (step < 0) {\n start2 = Math.ceil(start2 * step) / step;\n stop = Math.floor(stop * step) / step;\n }\n prestep = step;\n }\n}\n\n// ../../node_modules/d3-array/src/threshold/sturges.js\nfunction thresholdSturges(values2) {\n return Math.max(1, Math.ceil(Math.log(count2(values2)) / Math.LN2) + 1);\n}\n\n// ../../node_modules/d3-array/src/max.js\nfunction max2(values2, valueof2) {\n let max4;\n if (valueof2 === void 0) {\n for (const value of values2) {\n if (value != null && (max4 < value || max4 === void 0 && value >= value)) {\n max4 = value;\n }\n }\n } else {\n let index2 = -1;\n for (let value of values2) {\n if ((value = valueof2(value, ++index2, values2)) != null && (max4 < value || max4 === void 0 && value >= value)) {\n max4 = value;\n }\n }\n }\n return max4;\n}\n\n// ../../node_modules/d3-array/src/maxIndex.js\nfunction maxIndex(values2, valueof2) {\n let max4;\n let maxIndex2 = -1;\n let index2 = -1;\n if (valueof2 === void 0) {\n for (const value of values2) {\n ++index2;\n if (value != null && (max4 < value || max4 === void 0 && value >= value)) {\n max4 = value, maxIndex2 = index2;\n }\n }\n } else {\n for (let value of values2) {\n if ((value = valueof2(value, ++index2, values2)) != null && (max4 < value || max4 === void 0 && value >= value)) {\n max4 = value, maxIndex2 = index2;\n }\n }\n }\n return maxIndex2;\n}\n\n// ../../node_modules/d3-array/src/min.js\nfunction min2(values2, valueof2) {\n let min5;\n if (valueof2 === void 0) {\n for (const value of values2) {\n if (value != null && (min5 > value || min5 === void 0 && value >= value)) {\n min5 = value;\n }\n }\n } else {\n let index2 = -1;\n for (let value of values2) {\n if ((value = valueof2(value, ++index2, values2)) != null && (min5 > value || min5 === void 0 && value >= value)) {\n min5 = value;\n }\n }\n }\n return min5;\n}\n\n// ../../node_modules/d3-array/src/minIndex.js\nfunction minIndex(values2, valueof2) {\n let min5;\n let minIndex2 = -1;\n let index2 = -1;\n if (valueof2 === void 0) {\n for (const value of values2) {\n ++index2;\n if (value != null && (min5 > value || min5 === void 0 && value >= value)) {\n min5 = value, minIndex2 = index2;\n }\n }\n } else {\n for (let value of values2) {\n if ((value = valueof2(value, ++index2, values2)) != null && (min5 > value || min5 === void 0 && value >= value)) {\n min5 = value, minIndex2 = index2;\n }\n }\n }\n return minIndex2;\n}\n\n// ../../node_modules/d3-array/src/quickselect.js\nfunction quickselect(array4, k2, left2 = 0, right2 = Infinity, compare) {\n k2 = Math.floor(k2);\n left2 = Math.floor(Math.max(0, left2));\n right2 = Math.floor(Math.min(array4.length - 1, right2));\n if (!(left2 <= k2 && k2 <= right2)) return array4;\n compare = compare === void 0 ? ascendingDefined : compareDefined(compare);\n while (right2 > left2) {\n if (right2 - left2 > 600) {\n const n = right2 - left2 + 1;\n const m = k2 - left2 + 1;\n const z = Math.log(n);\n const s2 = 0.5 * Math.exp(2 * z / 3);\n const sd = 0.5 * Math.sqrt(z * s2 * (n - s2) / n) * (m - n / 2 < 0 ? -1 : 1);\n const newLeft = Math.max(left2, Math.floor(k2 - m * s2 / n + sd));\n const newRight = Math.min(right2, Math.floor(k2 + (n - m) * s2 / n + sd));\n quickselect(array4, k2, newLeft, newRight, compare);\n }\n const t = array4[k2];\n let i = left2;\n let j = right2;\n swap(array4, left2, k2);\n if (compare(array4[right2], t) > 0) swap(array4, left2, right2);\n while (i < j) {\n swap(array4, i, j), ++i, --j;\n while (compare(array4[i], t) < 0) ++i;\n while (compare(array4[j], t) > 0) --j;\n }\n if (compare(array4[left2], t) === 0) swap(array4, left2, j);\n else ++j, swap(array4, j, right2);\n if (j <= k2) left2 = j + 1;\n if (k2 <= j) right2 = j - 1;\n }\n return array4;\n}\nfunction swap(array4, i, j) {\n const t = array4[i];\n array4[i] = array4[j];\n array4[j] = t;\n}\n\n// ../../node_modules/d3-array/src/greatest.js\nfunction greatest(values2, compare = ascending) {\n let max4;\n let defined2 = false;\n if (compare.length === 1) {\n let maxValue;\n for (const element of values2) {\n const value = compare(element);\n if (defined2 ? ascending(value, maxValue) > 0 : ascending(value, value) === 0) {\n max4 = element;\n maxValue = value;\n defined2 = true;\n }\n }\n } else {\n for (const value of values2) {\n if (defined2 ? compare(value, max4) > 0 : compare(value, value) === 0) {\n max4 = value;\n defined2 = true;\n }\n }\n }\n return max4;\n}\n\n// ../../node_modules/d3-array/src/quantile.js\nfunction quantile2(values2, p, valueof2) {\n values2 = Float64Array.from(numbers(values2, valueof2));\n if (!(n = values2.length) || isNaN(p = +p)) return;\n if (p <= 0 || n < 2) return min2(values2);\n if (p >= 1) return max2(values2);\n var n, i = (n - 1) * p, i0 = Math.floor(i), value0 = max2(quickselect(values2, i0).subarray(0, i0 + 1)), value1 = min2(values2.subarray(i0 + 1));\n return value0 + (value1 - value0) * (i - i0);\n}\nfunction quantileSorted(values2, p, valueof2 = number) {\n if (!(n = values2.length) || isNaN(p = +p)) return;\n if (p <= 0 || n < 2) return +valueof2(values2[0], 0, values2);\n if (p >= 1) return +valueof2(values2[n - 1], n - 1, values2);\n var n, i = (n - 1) * p, i0 = Math.floor(i), value0 = +valueof2(values2[i0], i0, values2), value1 = +valueof2(values2[i0 + 1], i0 + 1, values2);\n return value0 + (value1 - value0) * (i - i0);\n}\n\n// ../../node_modules/d3-array/src/threshold/freedmanDiaconis.js\nfunction thresholdFreedmanDiaconis(values2, min5, max4) {\n const c4 = count2(values2), d = quantile2(values2, 0.75) - quantile2(values2, 0.25);\n return c4 && d ? Math.ceil((max4 - min5) / (2 * d * Math.pow(c4, -1 / 3))) : 1;\n}\n\n// ../../node_modules/d3-array/src/threshold/scott.js\nfunction thresholdScott(values2, min5, max4) {\n const c4 = count2(values2), d = deviation(values2);\n return c4 && d ? Math.ceil((max4 - min5) * Math.cbrt(c4) / (3.49 * d)) : 1;\n}\n\n// ../../node_modules/d3-array/src/mean.js\nfunction mean2(values2, valueof2) {\n let count4 = 0;\n let sum4 = 0;\n if (valueof2 === void 0) {\n for (let value of values2) {\n if (value != null && (value = +value) >= value) {\n ++count4, sum4 += value;\n }\n }\n } else {\n let index2 = -1;\n for (let value of values2) {\n if ((value = valueof2(value, ++index2, values2)) != null && (value = +value) >= value) {\n ++count4, sum4 += value;\n }\n }\n }\n if (count4) return sum4 / count4;\n}\n\n// ../../node_modules/d3-array/src/median.js\nfunction median2(values2, valueof2) {\n return quantile2(values2, 0.5, valueof2);\n}\n\n// ../../node_modules/d3-array/src/merge.js\nfunction* flatten(arrays) {\n for (const array4 of arrays) {\n yield* array4;\n }\n}\nfunction merge(arrays) {\n return Array.from(flatten(arrays));\n}\n\n// ../../node_modules/d3-array/src/mode.js\nfunction mode2(values2, valueof2) {\n const counts = new InternMap();\n if (valueof2 === void 0) {\n for (let value of values2) {\n if (value != null && value >= value) {\n counts.set(value, (counts.get(value) || 0) + 1);\n }\n }\n } else {\n let index2 = -1;\n for (let value of values2) {\n if ((value = valueof2(value, ++index2, values2)) != null && value >= value) {\n counts.set(value, (counts.get(value) || 0) + 1);\n }\n }\n }\n let modeValue;\n let modeCount = 0;\n for (const [value, count4] of counts) {\n if (count4 > modeCount) {\n modeCount = count4;\n modeValue = value;\n }\n }\n return modeValue;\n}\n\n// ../../node_modules/d3-array/src/pairs.js\nfunction pairs2(values2, pairof = pair) {\n const pairs3 = [];\n let previous;\n let first3 = false;\n for (const value of values2) {\n if (first3) pairs3.push(pairof(previous, value));\n previous = value;\n first3 = true;\n }\n return pairs3;\n}\nfunction pair(a2, b) {\n return [a2, b];\n}\n\n// ../../node_modules/d3-array/src/range.js\nfunction range(start2, stop, step) {\n start2 = +start2, stop = +stop, step = (n = arguments.length) < 2 ? (stop = start2, start2 = 0, 1) : n < 3 ? 1 : +step;\n var i = -1, n = Math.max(0, Math.ceil((stop - start2) / step)) | 0, range3 = new Array(n);\n while (++i < n) {\n range3[i] = start2 + i * step;\n }\n return range3;\n}\n\n// ../../node_modules/d3-array/src/rank.js\nfunction rank2(values2, valueof2 = ascending) {\n if (typeof values2[Symbol.iterator] !== \"function\") throw new TypeError(\"values is not iterable\");\n let V = Array.from(values2);\n const R = new Float64Array(V.length);\n if (valueof2.length !== 2) V = V.map(valueof2), valueof2 = ascending;\n const compareIndex = (i, j) => valueof2(V[i], V[j]);\n let k2, r;\n values2 = Uint32Array.from(V, (_, i) => i);\n values2.sort(valueof2 === ascending ? (i, j) => ascendingDefined(V[i], V[j]) : compareDefined(compareIndex));\n values2.forEach((j, i) => {\n const c4 = compareIndex(j, k2 === void 0 ? j : k2);\n if (c4 >= 0) {\n if (k2 === void 0 || c4 > 0) k2 = j, r = i;\n R[j] = r;\n } else {\n R[j] = NaN;\n }\n });\n return R;\n}\n\n// ../../node_modules/d3-array/src/least.js\nfunction least(values2, compare = ascending) {\n let min5;\n let defined2 = false;\n if (compare.length === 1) {\n let minValue;\n for (const element of values2) {\n const value = compare(element);\n if (defined2 ? ascending(value, minValue) < 0 : ascending(value, value) === 0) {\n min5 = element;\n minValue = value;\n defined2 = true;\n }\n }\n } else {\n for (const value of values2) {\n if (defined2 ? compare(value, min5) < 0 : compare(value, value) === 0) {\n min5 = value;\n defined2 = true;\n }\n }\n }\n return min5;\n}\n\n// ../../node_modules/d3-array/src/sum.js\nfunction sum2(values2, valueof2) {\n let sum4 = 0;\n if (valueof2 === void 0) {\n for (let value of values2) {\n if (value = +value) {\n sum4 += value;\n }\n }\n } else {\n let index2 = -1;\n for (let value of values2) {\n if (value = +valueof2(value, ++index2, values2)) {\n sum4 += value;\n }\n }\n }\n return sum4;\n}\n\n// ../../node_modules/d3-array/src/reverse.js\nfunction reverse(values2) {\n if (typeof values2[Symbol.iterator] !== \"function\") throw new TypeError(\"values is not iterable\");\n return Array.from(values2).reverse();\n}\n\n// ../../node_modules/d3-axis/src/identity.js\nfunction identity_default(x3) {\n return x3;\n}\n\n// ../../node_modules/d3-axis/src/axis.js\nvar top = 1;\nvar right = 2;\nvar bottom = 3;\nvar left = 4;\nvar epsilon = 1e-6;\nfunction translateX(x3) {\n return \"translate(\" + x3 + \",0)\";\n}\nfunction translateY(y3) {\n return \"translate(0,\" + y3 + \")\";\n}\nfunction number2(scale3) {\n return (d) => +scale3(d);\n}\nfunction center(scale3, offset2) {\n offset2 = Math.max(0, scale3.bandwidth() - offset2 * 2) / 2;\n if (scale3.round()) offset2 = Math.round(offset2);\n return (d) => +scale3(d) + offset2;\n}\nfunction entering() {\n return !this.__axis;\n}\nfunction axis(orient, scale3) {\n var tickArguments = [], tickValues = null, tickFormat2 = null, tickSizeInner = 6, tickSizeOuter = 6, tickPadding = 3, offset2 = typeof window !== \"undefined\" && window.devicePixelRatio > 1 ? 0 : 0.5, k2 = orient === top || orient === left ? -1 : 1, x3 = orient === left || orient === right ? \"x\" : \"y\", transform3 = orient === top || orient === bottom ? translateX : translateY;\n function axis3(context) {\n var values2 = tickValues == null ? scale3.ticks ? scale3.ticks.apply(scale3, tickArguments) : scale3.domain() : tickValues, format3 = tickFormat2 == null ? scale3.tickFormat ? scale3.tickFormat.apply(scale3, tickArguments) : identity_default : tickFormat2, spacing = Math.max(tickSizeInner, 0) + tickPadding, range3 = scale3.range(), range0 = +range3[0] + offset2, range1 = +range3[range3.length - 1] + offset2, position3 = (scale3.bandwidth ? center : number2)(scale3.copy(), offset2), selection2 = context.selection ? context.selection() : context, path2 = selection2.selectAll(\".domain\").data([null]), tick = selection2.selectAll(\".tick\").data(values2, scale3).order(), tickExit = tick.exit(), tickEnter = tick.enter().append(\"g\").attr(\"class\", \"tick\"), line3 = tick.select(\"line\"), text3 = tick.select(\"text\");\n path2 = path2.merge(path2.enter().insert(\"path\", \".tick\").attr(\"class\", \"domain\").attr(\"stroke\", \"currentColor\"));\n tick = tick.merge(tickEnter);\n line3 = line3.merge(tickEnter.append(\"line\").attr(\"stroke\", \"currentColor\").attr(x3 + \"2\", k2 * tickSizeInner));\n text3 = text3.merge(tickEnter.append(\"text\").attr(\"fill\", \"currentColor\").attr(x3, k2 * spacing).attr(\"dy\", orient === top ? \"0em\" : orient === bottom ? \"0.71em\" : \"0.32em\"));\n if (context !== selection2) {\n path2 = path2.transition(context);\n tick = tick.transition(context);\n line3 = line3.transition(context);\n text3 = text3.transition(context);\n tickExit = tickExit.transition(context).attr(\"opacity\", epsilon).attr(\"transform\", function(d) {\n return isFinite(d = position3(d)) ? transform3(d + offset2) : this.getAttribute(\"transform\");\n });\n tickEnter.attr(\"opacity\", epsilon).attr(\"transform\", function(d) {\n var p = this.parentNode.__axis;\n return transform3((p && isFinite(p = p(d)) ? p : position3(d)) + offset2);\n });\n }\n tickExit.remove();\n path2.attr(\"d\", orient === left || orient === right ? tickSizeOuter ? \"M\" + k2 * tickSizeOuter + \",\" + range0 + \"H\" + offset2 + \"V\" + range1 + \"H\" + k2 * tickSizeOuter : \"M\" + offset2 + \",\" + range0 + \"V\" + range1 : tickSizeOuter ? \"M\" + range0 + \",\" + k2 * tickSizeOuter + \"V\" + offset2 + \"H\" + range1 + \"V\" + k2 * tickSizeOuter : \"M\" + range0 + \",\" + offset2 + \"H\" + range1);\n tick.attr(\"opacity\", 1).attr(\"transform\", function(d) {\n return transform3(position3(d) + offset2);\n });\n line3.attr(x3 + \"2\", k2 * tickSizeInner);\n text3.attr(x3, k2 * spacing).text(format3);\n selection2.filter(entering).attr(\"fill\", \"none\").attr(\"font-size\", 10).attr(\"font-family\", \"sans-serif\").attr(\"text-anchor\", orient === right ? \"start\" : orient === left ? \"end\" : \"middle\");\n selection2.each(function() {\n this.__axis = position3;\n });\n }\n axis3.scale = function(_) {\n return arguments.length ? (scale3 = _, axis3) : scale3;\n };\n axis3.ticks = function() {\n return tickArguments = Array.from(arguments), axis3;\n };\n axis3.tickArguments = function(_) {\n return arguments.length ? (tickArguments = _ == null ? [] : Array.from(_), axis3) : tickArguments.slice();\n };\n axis3.tickValues = function(_) {\n return arguments.length ? (tickValues = _ == null ? null : Array.from(_), axis3) : tickValues && tickValues.slice();\n };\n axis3.tickFormat = function(_) {\n return arguments.length ? (tickFormat2 = _, axis3) : tickFormat2;\n };\n axis3.tickSize = function(_) {\n return arguments.length ? (tickSizeInner = tickSizeOuter = +_, axis3) : tickSizeInner;\n };\n axis3.tickSizeInner = function(_) {\n return arguments.length ? (tickSizeInner = +_, axis3) : tickSizeInner;\n };\n axis3.tickSizeOuter = function(_) {\n return arguments.length ? (tickSizeOuter = +_, axis3) : tickSizeOuter;\n };\n axis3.tickPadding = function(_) {\n return arguments.length ? (tickPadding = +_, axis3) : tickPadding;\n };\n axis3.offset = function(_) {\n return arguments.length ? (offset2 = +_, axis3) : offset2;\n };\n return axis3;\n}\nfunction axisBottom(scale3) {\n return axis(bottom, scale3);\n}\n\n// ../../node_modules/d3-dispatch/src/dispatch.js\nvar noop = { value: () => {\n} };\nfunction dispatch() {\n for (var i = 0, n = arguments.length, _ = {}, t; i < n; ++i) {\n if (!(t = arguments[i] + \"\") || t in _ || /[\\s.]/.test(t)) throw new Error(\"illegal type: \" + t);\n _[t] = [];\n }\n return new Dispatch(_);\n}\nfunction Dispatch(_) {\n this._ = _;\n}\nfunction parseTypenames(typenames, types) {\n return typenames.trim().split(/^|\\s+/).map(function(t) {\n var name2 = \"\", i = t.indexOf(\".\");\n if (i >= 0) name2 = t.slice(i + 1), t = t.slice(0, i);\n if (t && !types.hasOwnProperty(t)) throw new Error(\"unknown type: \" + t);\n return { type: t, name: name2 };\n });\n}\nDispatch.prototype = dispatch.prototype = {\n constructor: Dispatch,\n on: function(typename, callback) {\n var _ = this._, T = parseTypenames(typename + \"\", _), t, i = -1, n = T.length;\n if (arguments.length < 2) {\n while (++i < n) if ((t = (typename = T[i]).type) && (t = get(_[t], typename.name))) return t;\n return;\n }\n if (callback != null && typeof callback !== \"function\") throw new Error(\"invalid callback: \" + callback);\n while (++i < n) {\n if (t = (typename = T[i]).type) _[t] = set(_[t], typename.name, callback);\n else if (callback == null) for (t in _) _[t] = set(_[t], typename.name, null);\n }\n return this;\n },\n copy: function() {\n var copy4 = {}, _ = this._;\n for (var t in _) copy4[t] = _[t].slice();\n return new Dispatch(copy4);\n },\n call: function(type2, that) {\n if ((n = arguments.length - 2) > 0) for (var args = new Array(n), i = 0, n, t; i < n; ++i) args[i] = arguments[i + 2];\n if (!this._.hasOwnProperty(type2)) throw new Error(\"unknown type: \" + type2);\n for (t = this._[type2], i = 0, n = t.length; i < n; ++i) t[i].value.apply(that, args);\n },\n apply: function(type2, that, args) {\n if (!this._.hasOwnProperty(type2)) throw new Error(\"unknown type: \" + type2);\n for (var t = this._[type2], i = 0, n = t.length; i < n; ++i) t[i].value.apply(that, args);\n }\n};\nfunction get(type2, name2) {\n for (var i = 0, n = type2.length, c4; i < n; ++i) {\n if ((c4 = type2[i]).name === name2) {\n return c4.value;\n }\n }\n}\nfunction set(type2, name2, callback) {\n for (var i = 0, n = type2.length; i < n; ++i) {\n if (type2[i].name === name2) {\n type2[i] = noop, type2 = type2.slice(0, i).concat(type2.slice(i + 1));\n break;\n }\n }\n if (callback != null) type2.push({ name: name2, value: callback });\n return type2;\n}\nvar dispatch_default = dispatch;\n\n// ../../node_modules/d3-selection/src/namespaces.js\nvar xhtml = \"http://www.w3.org/1999/xhtml\";\nvar namespaces_default = {\n svg: \"http://www.w3.org/2000/svg\",\n xhtml,\n xlink: \"http://www.w3.org/1999/xlink\",\n xml: \"http://www.w3.org/XML/1998/namespace\",\n xmlns: \"http://www.w3.org/2000/xmlns/\"\n};\n\n// ../../node_modules/d3-selection/src/namespace.js\nfunction namespace_default(name2) {\n var prefix2 = name2 += \"\", i = prefix2.indexOf(\":\");\n if (i >= 0 && (prefix2 = name2.slice(0, i)) !== \"xmlns\") name2 = name2.slice(i + 1);\n return namespaces_default.hasOwnProperty(prefix2) ? { space: namespaces_default[prefix2], local: name2 } : name2;\n}\n\n// ../../node_modules/d3-selection/src/creator.js\nfunction creatorInherit(name2) {\n return function() {\n var document2 = this.ownerDocument, uri = this.namespaceURI;\n return uri === xhtml && document2.documentElement.namespaceURI === xhtml ? document2.createElement(name2) : document2.createElementNS(uri, name2);\n };\n}\nfunction creatorFixed(fullname) {\n return function() {\n return this.ownerDocument.createElementNS(fullname.space, fullname.local);\n };\n}\nfunction creator_default(name2) {\n var fullname = namespace_default(name2);\n return (fullname.local ? creatorFixed : creatorInherit)(fullname);\n}\n\n// ../../node_modules/d3-selection/src/selector.js\nfunction none() {\n}\nfunction selector_default(selector) {\n return selector == null ? none : function() {\n return this.querySelector(selector);\n };\n}\n\n// ../../node_modules/d3-selection/src/selection/select.js\nfunction select_default(select2) {\n if (typeof select2 !== \"function\") select2 = selector_default(select2);\n for (var groups2 = this._groups, m = groups2.length, subgroups = new Array(m), j = 0; j < m; ++j) {\n for (var group3 = groups2[j], n = group3.length, subgroup = subgroups[j] = new Array(n), node, subnode, i = 0; i < n; ++i) {\n if ((node = group3[i]) && (subnode = select2.call(node, node.__data__, i, group3))) {\n if (\"__data__\" in node) subnode.__data__ = node.__data__;\n subgroup[i] = subnode;\n }\n }\n }\n return new Selection2(subgroups, this._parents);\n}\n\n// ../../node_modules/d3-selection/src/array.js\nfunction array(x3) {\n return x3 == null ? [] : Array.isArray(x3) ? x3 : Array.from(x3);\n}\n\n// ../../node_modules/d3-selection/src/selectorAll.js\nfunction empty2() {\n return [];\n}\nfunction selectorAll_default(selector) {\n return selector == null ? empty2 : function() {\n return this.querySelectorAll(selector);\n };\n}\n\n// ../../node_modules/d3-selection/src/selection/selectAll.js\nfunction arrayAll(select2) {\n return function() {\n return array(select2.apply(this, arguments));\n };\n}\nfunction selectAll_default(select2) {\n if (typeof select2 === \"function\") select2 = arrayAll(select2);\n else select2 = selectorAll_default(select2);\n for (var groups2 = this._groups, m = groups2.length, subgroups = [], parents = [], j = 0; j < m; ++j) {\n for (var group3 = groups2[j], n = group3.length, node, i = 0; i < n; ++i) {\n if (node = group3[i]) {\n subgroups.push(select2.call(node, node.__data__, i, group3));\n parents.push(node);\n }\n }\n }\n return new Selection2(subgroups, parents);\n}\n\n// ../../node_modules/d3-selection/src/matcher.js\nfunction matcher_default(selector) {\n return function() {\n return this.matches(selector);\n };\n}\nfunction childMatcher(selector) {\n return function(node) {\n return node.matches(selector);\n };\n}\n\n// ../../node_modules/d3-selection/src/selection/selectChild.js\nvar find = Array.prototype.find;\nfunction childFind(match) {\n return function() {\n return find.call(this.children, match);\n };\n}\nfunction childFirst() {\n return this.firstElementChild;\n}\nfunction selectChild_default(match) {\n return this.select(match == null ? childFirst : childFind(typeof match === \"function\" ? match : childMatcher(match)));\n}\n\n// ../../node_modules/d3-selection/src/selection/selectChildren.js\nvar filter = Array.prototype.filter;\nfunction children() {\n return Array.from(this.children);\n}\nfunction childrenFilter(match) {\n return function() {\n return filter.call(this.children, match);\n };\n}\nfunction selectChildren_default(match) {\n return this.selectAll(match == null ? children : childrenFilter(typeof match === \"function\" ? match : childMatcher(match)));\n}\n\n// ../../node_modules/d3-selection/src/selection/filter.js\nfunction filter_default(match) {\n if (typeof match !== \"function\") match = matcher_default(match);\n for (var groups2 = this._groups, m = groups2.length, subgroups = new Array(m), j = 0; j < m; ++j) {\n for (var group3 = groups2[j], n = group3.length, subgroup = subgroups[j] = [], node, i = 0; i < n; ++i) {\n if ((node = group3[i]) && match.call(node, node.__data__, i, group3)) {\n subgroup.push(node);\n }\n }\n }\n return new Selection2(subgroups, this._parents);\n}\n\n// ../../node_modules/d3-selection/src/selection/sparse.js\nfunction sparse_default(update2) {\n return new Array(update2.length);\n}\n\n// ../../node_modules/d3-selection/src/selection/enter.js\nfunction enter_default() {\n return new Selection2(this._enter || this._groups.map(sparse_default), this._parents);\n}\nfunction EnterNode(parent, datum2) {\n this.ownerDocument = parent.ownerDocument;\n this.namespaceURI = parent.namespaceURI;\n this._next = null;\n this._parent = parent;\n this.__data__ = datum2;\n}\nEnterNode.prototype = {\n constructor: EnterNode,\n appendChild: function(child) {\n return this._parent.insertBefore(child, this._next);\n },\n insertBefore: function(child, next) {\n return this._parent.insertBefore(child, next);\n },\n querySelector: function(selector) {\n return this._parent.querySelector(selector);\n },\n querySelectorAll: function(selector) {\n return this._parent.querySelectorAll(selector);\n }\n};\n\n// ../../node_modules/d3-selection/src/constant.js\nfunction constant_default(x3) {\n return function() {\n return x3;\n };\n}\n\n// ../../node_modules/d3-selection/src/selection/data.js\nfunction bindIndex(parent, group3, enter, update2, exit, data) {\n var i = 0, node, groupLength = group3.length, dataLength = data.length;\n for (; i < dataLength; ++i) {\n if (node = group3[i]) {\n node.__data__ = data[i];\n update2[i] = node;\n } else {\n enter[i] = new EnterNode(parent, data[i]);\n }\n }\n for (; i < groupLength; ++i) {\n if (node = group3[i]) {\n exit[i] = node;\n }\n }\n}\nfunction bindKey(parent, group3, enter, update2, exit, data, key) {\n var i, node, nodeByKeyValue = /* @__PURE__ */ new Map(), groupLength = group3.length, dataLength = data.length, keyValues = new Array(groupLength), keyValue;\n for (i = 0; i < groupLength; ++i) {\n if (node = group3[i]) {\n keyValues[i] = keyValue = key.call(node, node.__data__, i, group3) + \"\";\n if (nodeByKeyValue.has(keyValue)) {\n exit[i] = node;\n } else {\n nodeByKeyValue.set(keyValue, node);\n }\n }\n }\n for (i = 0; i < dataLength; ++i) {\n keyValue = key.call(parent, data[i], i, data) + \"\";\n if (node = nodeByKeyValue.get(keyValue)) {\n update2[i] = node;\n node.__data__ = data[i];\n nodeByKeyValue.delete(keyValue);\n } else {\n enter[i] = new EnterNode(parent, data[i]);\n }\n }\n for (i = 0; i < groupLength; ++i) {\n if ((node = group3[i]) && nodeByKeyValue.get(keyValues[i]) === node) {\n exit[i] = node;\n }\n }\n}\nfunction datum(node) {\n return node.__data__;\n}\nfunction data_default(value, key) {\n if (!arguments.length) return Array.from(this, datum);\n var bind = key ? bindKey : bindIndex, parents = this._parents, groups2 = this._groups;\n if (typeof value !== \"function\") value = constant_default(value);\n for (var m = groups2.length, update2 = new Array(m), enter = new Array(m), exit = new Array(m), j = 0; j < m; ++j) {\n var parent = parents[j], group3 = groups2[j], groupLength = group3.length, data = arraylike(value.call(parent, parent && parent.__data__, j, parents)), dataLength = data.length, enterGroup = enter[j] = new Array(dataLength), updateGroup = update2[j] = new Array(dataLength), exitGroup = exit[j] = new Array(groupLength);\n bind(parent, group3, enterGroup, updateGroup, exitGroup, data, key);\n for (var i0 = 0, i1 = 0, previous, next; i0 < dataLength; ++i0) {\n if (previous = enterGroup[i0]) {\n if (i0 >= i1) i1 = i0 + 1;\n while (!(next = updateGroup[i1]) && ++i1 < dataLength) ;\n previous._next = next || null;\n }\n }\n }\n update2 = new Selection2(update2, parents);\n update2._enter = enter;\n update2._exit = exit;\n return update2;\n}\nfunction arraylike(data) {\n return typeof data === \"object\" && \"length\" in data ? data : Array.from(data);\n}\n\n// ../../node_modules/d3-selection/src/selection/exit.js\nfunction exit_default() {\n return new Selection2(this._exit || this._groups.map(sparse_default), this._parents);\n}\n\n// ../../node_modules/d3-selection/src/selection/join.js\nfunction join_default(onenter, onupdate, onexit) {\n var enter = this.enter(), update2 = this, exit = this.exit();\n if (typeof onenter === \"function\") {\n enter = onenter(enter);\n if (enter) enter = enter.selection();\n } else {\n enter = enter.append(onenter + \"\");\n }\n if (onupdate != null) {\n update2 = onupdate(update2);\n if (update2) update2 = update2.selection();\n }\n if (onexit == null) exit.remove();\n else onexit(exit);\n return enter && update2 ? enter.merge(update2).order() : update2;\n}\n\n// ../../node_modules/d3-selection/src/selection/merge.js\nfunction merge_default(context) {\n var selection2 = context.selection ? context.selection() : context;\n for (var groups0 = this._groups, groups1 = selection2._groups, m0 = groups0.length, m1 = groups1.length, m = Math.min(m0, m1), merges = new Array(m0), j = 0; j < m; ++j) {\n for (var group0 = groups0[j], group1 = groups1[j], n = group0.length, merge2 = merges[j] = new Array(n), node, i = 0; i < n; ++i) {\n if (node = group0[i] || group1[i]) {\n merge2[i] = node;\n }\n }\n }\n for (; j < m0; ++j) {\n merges[j] = groups0[j];\n }\n return new Selection2(merges, this._parents);\n}\n\n// ../../node_modules/d3-selection/src/selection/order.js\nfunction order_default() {\n for (var groups2 = this._groups, j = -1, m = groups2.length; ++j < m; ) {\n for (var group3 = groups2[j], i = group3.length - 1, next = group3[i], node; --i >= 0; ) {\n if (node = group3[i]) {\n if (next && node.compareDocumentPosition(next) ^ 4) next.parentNode.insertBefore(node, next);\n next = node;\n }\n }\n }\n return this;\n}\n\n// ../../node_modules/d3-selection/src/selection/sort.js\nfunction sort_default(compare) {\n if (!compare) compare = ascending2;\n function compareNode(a2, b) {\n return a2 && b ? compare(a2.__data__, b.__data__) : !a2 - !b;\n }\n for (var groups2 = this._groups, m = groups2.length, sortgroups = new Array(m), j = 0; j < m; ++j) {\n for (var group3 = groups2[j], n = group3.length, sortgroup = sortgroups[j] = new Array(n), node, i = 0; i < n; ++i) {\n if (node = group3[i]) {\n sortgroup[i] = node;\n }\n }\n sortgroup.sort(compareNode);\n }\n return new Selection2(sortgroups, this._parents).order();\n}\nfunction ascending2(a2, b) {\n return a2 < b ? -1 : a2 > b ? 1 : a2 >= b ? 0 : NaN;\n}\n\n// ../../node_modules/d3-selection/src/selection/call.js\nfunction call_default() {\n var callback = arguments[0];\n arguments[0] = this;\n callback.apply(null, arguments);\n return this;\n}\n\n// ../../node_modules/d3-selection/src/selection/nodes.js\nfunction nodes_default() {\n return Array.from(this);\n}\n\n// ../../node_modules/d3-selection/src/selection/node.js\nfunction node_default() {\n for (var groups2 = this._groups, j = 0, m = groups2.length; j < m; ++j) {\n for (var group3 = groups2[j], i = 0, n = group3.length; i < n; ++i) {\n var node = group3[i];\n if (node) return node;\n }\n }\n return null;\n}\n\n// ../../node_modules/d3-selection/src/selection/size.js\nfunction size_default() {\n let size = 0;\n for (const node of this) ++size;\n return size;\n}\n\n// ../../node_modules/d3-selection/src/selection/empty.js\nfunction empty_default() {\n return !this.node();\n}\n\n// ../../node_modules/d3-selection/src/selection/each.js\nfunction each_default(callback) {\n for (var groups2 = this._groups, j = 0, m = groups2.length; j < m; ++j) {\n for (var group3 = groups2[j], i = 0, n = group3.length, node; i < n; ++i) {\n if (node = group3[i]) callback.call(node, node.__data__, i, group3);\n }\n }\n return this;\n}\n\n// ../../node_modules/d3-selection/src/selection/attr.js\nfunction attrRemove(name2) {\n return function() {\n this.removeAttribute(name2);\n };\n}\nfunction attrRemoveNS(fullname) {\n return function() {\n this.removeAttributeNS(fullname.space, fullname.local);\n };\n}\nfunction attrConstant(name2, value) {\n return function() {\n this.setAttribute(name2, value);\n };\n}\nfunction attrConstantNS(fullname, value) {\n return function() {\n this.setAttributeNS(fullname.space, fullname.local, value);\n };\n}\nfunction attrFunction(name2, value) {\n return function() {\n var v2 = value.apply(this, arguments);\n if (v2 == null) this.removeAttribute(name2);\n else this.setAttribute(name2, v2);\n };\n}\nfunction attrFunctionNS(fullname, value) {\n return function() {\n var v2 = value.apply(this, arguments);\n if (v2 == null) this.removeAttributeNS(fullname.space, fullname.local);\n else this.setAttributeNS(fullname.space, fullname.local, v2);\n };\n}\nfunction attr_default(name2, value) {\n var fullname = namespace_default(name2);\n if (arguments.length < 2) {\n var node = this.node();\n return fullname.local ? node.getAttributeNS(fullname.space, fullname.local) : node.getAttribute(fullname);\n }\n return this.each((value == null ? fullname.local ? attrRemoveNS : attrRemove : typeof value === \"function\" ? fullname.local ? attrFunctionNS : attrFunction : fullname.local ? attrConstantNS : attrConstant)(fullname, value));\n}\n\n// ../../node_modules/d3-selection/src/window.js\nfunction window_default(node) {\n return node.ownerDocument && node.ownerDocument.defaultView || node.document && node || node.defaultView;\n}\n\n// ../../node_modules/d3-selection/src/selection/style.js\nfunction styleRemove(name2) {\n return function() {\n this.style.removeProperty(name2);\n };\n}\nfunction styleConstant(name2, value, priority) {\n return function() {\n this.style.setProperty(name2, value, priority);\n };\n}\nfunction styleFunction(name2, value, priority) {\n return function() {\n var v2 = value.apply(this, arguments);\n if (v2 == null) this.style.removeProperty(name2);\n else this.style.setProperty(name2, v2, priority);\n };\n}\nfunction style_default(name2, value, priority) {\n return arguments.length > 1 ? this.each((value == null ? styleRemove : typeof value === \"function\" ? styleFunction : styleConstant)(name2, value, priority == null ? \"\" : priority)) : styleValue(this.node(), name2);\n}\nfunction styleValue(node, name2) {\n return node.style.getPropertyValue(name2) || window_default(node).getComputedStyle(node, null).getPropertyValue(name2);\n}\n\n// ../../node_modules/d3-selection/src/selection/property.js\nfunction propertyRemove(name2) {\n return function() {\n delete this[name2];\n };\n}\nfunction propertyConstant(name2, value) {\n return function() {\n this[name2] = value;\n };\n}\nfunction propertyFunction(name2, value) {\n return function() {\n var v2 = value.apply(this, arguments);\n if (v2 == null) delete this[name2];\n else this[name2] = v2;\n };\n}\nfunction property_default(name2, value) {\n return arguments.length > 1 ? this.each((value == null ? propertyRemove : typeof value === \"function\" ? propertyFunction : propertyConstant)(name2, value)) : this.node()[name2];\n}\n\n// ../../node_modules/d3-selection/src/selection/classed.js\nfunction classArray(string2) {\n return string2.trim().split(/^|\\s+/);\n}\nfunction classList(node) {\n return node.classList || new ClassList(node);\n}\nfunction ClassList(node) {\n this._node = node;\n this._names = classArray(node.getAttribute(\"class\") || \"\");\n}\nClassList.prototype = {\n add: function(name2) {\n var i = this._names.indexOf(name2);\n if (i < 0) {\n this._names.push(name2);\n this._node.setAttribute(\"class\", this._names.join(\" \"));\n }\n },\n remove: function(name2) {\n var i = this._names.indexOf(name2);\n if (i >= 0) {\n this._names.splice(i, 1);\n this._node.setAttribute(\"class\", this._names.join(\" \"));\n }\n },\n contains: function(name2) {\n return this._names.indexOf(name2) >= 0;\n }\n};\nfunction classedAdd(node, names) {\n var list2 = classList(node), i = -1, n = names.length;\n while (++i < n) list2.add(names[i]);\n}\nfunction classedRemove(node, names) {\n var list2 = classList(node), i = -1, n = names.length;\n while (++i < n) list2.remove(names[i]);\n}\nfunction classedTrue(names) {\n return function() {\n classedAdd(this, names);\n };\n}\nfunction classedFalse(names) {\n return function() {\n classedRemove(this, names);\n };\n}\nfunction classedFunction(names, value) {\n return function() {\n (value.apply(this, arguments) ? classedAdd : classedRemove)(this, names);\n };\n}\nfunction classed_default(name2, value) {\n var names = classArray(name2 + \"\");\n if (arguments.length < 2) {\n var list2 = classList(this.node()), i = -1, n = names.length;\n while (++i < n) if (!list2.contains(names[i])) return false;\n return true;\n }\n return this.each((typeof value === \"function\" ? classedFunction : value ? classedTrue : classedFalse)(names, value));\n}\n\n// ../../node_modules/d3-selection/src/selection/text.js\nfunction textRemove() {\n this.textContent = \"\";\n}\nfunction textConstant(value) {\n return function() {\n this.textContent = value;\n };\n}\nfunction textFunction(value) {\n return function() {\n var v2 = value.apply(this, arguments);\n this.textContent = v2 == null ? \"\" : v2;\n };\n}\nfunction text_default(value) {\n return arguments.length ? this.each(value == null ? textRemove : (typeof value === \"function\" ? textFunction : textConstant)(value)) : this.node().textContent;\n}\n\n// ../../node_modules/d3-selection/src/selection/html.js\nfunction htmlRemove() {\n this.innerHTML = \"\";\n}\nfunction htmlConstant(value) {\n return function() {\n this.innerHTML = value;\n };\n}\nfunction htmlFunction(value) {\n return function() {\n var v2 = value.apply(this, arguments);\n this.innerHTML = v2 == null ? \"\" : v2;\n };\n}\nfunction html_default(value) {\n return arguments.length ? this.each(value == null ? htmlRemove : (typeof value === \"function\" ? htmlFunction : htmlConstant)(value)) : this.node().innerHTML;\n}\n\n// ../../node_modules/d3-selection/src/selection/raise.js\nfunction raise() {\n if (this.nextSibling) this.parentNode.appendChild(this);\n}\nfunction raise_default() {\n return this.each(raise);\n}\n\n// ../../node_modules/d3-selection/src/selection/lower.js\nfunction lower2() {\n if (this.previousSibling) this.parentNode.insertBefore(this, this.parentNode.firstChild);\n}\nfunction lower_default() {\n return this.each(lower2);\n}\n\n// ../../node_modules/d3-selection/src/selection/append.js\nfunction append_default(name2) {\n var create5 = typeof name2 === \"function\" ? name2 : creator_default(name2);\n return this.select(function() {\n return this.appendChild(create5.apply(this, arguments));\n });\n}\n\n// ../../node_modules/d3-selection/src/selection/insert.js\nfunction constantNull() {\n return null;\n}\nfunction insert_default(name2, before) {\n var create5 = typeof name2 === \"function\" ? name2 : creator_default(name2), select2 = before == null ? constantNull : typeof before === \"function\" ? before : selector_default(before);\n return this.select(function() {\n return this.insertBefore(create5.apply(this, arguments), select2.apply(this, arguments) || null);\n });\n}\n\n// ../../node_modules/d3-selection/src/selection/remove.js\nfunction remove() {\n var parent = this.parentNode;\n if (parent) parent.removeChild(this);\n}\nfunction remove_default() {\n return this.each(remove);\n}\n\n// ../../node_modules/d3-selection/src/selection/clone.js\nfunction selection_cloneShallow() {\n var clone = this.cloneNode(false), parent = this.parentNode;\n return parent ? parent.insertBefore(clone, this.nextSibling) : clone;\n}\nfunction selection_cloneDeep() {\n var clone = this.cloneNode(true), parent = this.parentNode;\n return parent ? parent.insertBefore(clone, this.nextSibling) : clone;\n}\nfunction clone_default(deep) {\n return this.select(deep ? selection_cloneDeep : selection_cloneShallow);\n}\n\n// ../../node_modules/d3-selection/src/selection/datum.js\nfunction datum_default(value) {\n return arguments.length ? this.property(\"__data__\", value) : this.node().__data__;\n}\n\n// ../../node_modules/d3-selection/src/selection/on.js\nfunction contextListener(listener) {\n return function(event) {\n listener.call(this, event, this.__data__);\n };\n}\nfunction parseTypenames2(typenames) {\n return typenames.trim().split(/^|\\s+/).map(function(t) {\n var name2 = \"\", i = t.indexOf(\".\");\n if (i >= 0) name2 = t.slice(i + 1), t = t.slice(0, i);\n return { type: t, name: name2 };\n });\n}\nfunction onRemove(typename) {\n return function() {\n var on = this.__on;\n if (!on) return;\n for (var j = 0, i = -1, m = on.length, o; j < m; ++j) {\n if (o = on[j], (!typename.type || o.type === typename.type) && o.name === typename.name) {\n this.removeEventListener(o.type, o.listener, o.options);\n } else {\n on[++i] = o;\n }\n }\n if (++i) on.length = i;\n else delete this.__on;\n };\n}\nfunction onAdd(typename, value, options) {\n return function() {\n var on = this.__on, o, listener = contextListener(value);\n if (on) for (var j = 0, m = on.length; j < m; ++j) {\n if ((o = on[j]).type === typename.type && o.name === typename.name) {\n this.removeEventListener(o.type, o.listener, o.options);\n this.addEventListener(o.type, o.listener = listener, o.options = options);\n o.value = value;\n return;\n }\n }\n this.addEventListener(typename.type, listener, options);\n o = { type: typename.type, name: typename.name, value, listener, options };\n if (!on) this.__on = [o];\n else on.push(o);\n };\n}\nfunction on_default(typename, value, options) {\n var typenames = parseTypenames2(typename + \"\"), i, n = typenames.length, t;\n if (arguments.length < 2) {\n var on = this.node().__on;\n if (on) for (var j = 0, m = on.length, o; j < m; ++j) {\n for (i = 0, o = on[j]; i < n; ++i) {\n if ((t = typenames[i]).type === o.type && t.name === o.name) {\n return o.value;\n }\n }\n }\n return;\n }\n on = value ? onAdd : onRemove;\n for (i = 0; i < n; ++i) this.each(on(typenames[i], value, options));\n return this;\n}\n\n// ../../node_modules/d3-selection/src/selection/dispatch.js\nfunction dispatchEvent(node, type2, params) {\n var window3 = window_default(node), event = window3.CustomEvent;\n if (typeof event === \"function\") {\n event = new event(type2, params);\n } else {\n event = window3.document.createEvent(\"Event\");\n if (params) event.initEvent(type2, params.bubbles, params.cancelable), event.detail = params.detail;\n else event.initEvent(type2, false, false);\n }\n node.dispatchEvent(event);\n}\nfunction dispatchConstant(type2, params) {\n return function() {\n return dispatchEvent(this, type2, params);\n };\n}\nfunction dispatchFunction(type2, params) {\n return function() {\n return dispatchEvent(this, type2, params.apply(this, arguments));\n };\n}\nfunction dispatch_default2(type2, params) {\n return this.each((typeof params === \"function\" ? dispatchFunction : dispatchConstant)(type2, params));\n}\n\n// ../../node_modules/d3-selection/src/selection/iterator.js\nfunction* iterator_default() {\n for (var groups2 = this._groups, j = 0, m = groups2.length; j < m; ++j) {\n for (var group3 = groups2[j], i = 0, n = group3.length, node; i < n; ++i) {\n if (node = group3[i]) yield node;\n }\n }\n}\n\n// ../../node_modules/d3-selection/src/selection/index.js\nvar root = [null];\nfunction Selection2(groups2, parents) {\n this._groups = groups2;\n this._parents = parents;\n}\nfunction selection() {\n return new Selection2([[document.documentElement]], root);\n}\nfunction selection_selection() {\n return this;\n}\nSelection2.prototype = selection.prototype = {\n constructor: Selection2,\n select: select_default,\n selectAll: selectAll_default,\n selectChild: selectChild_default,\n selectChildren: selectChildren_default,\n filter: filter_default,\n data: data_default,\n enter: enter_default,\n exit: exit_default,\n join: join_default,\n merge: merge_default,\n selection: selection_selection,\n order: order_default,\n sort: sort_default,\n call: call_default,\n nodes: nodes_default,\n node: node_default,\n size: size_default,\n empty: empty_default,\n each: each_default,\n attr: attr_default,\n style: style_default,\n property: property_default,\n classed: classed_default,\n text: text_default,\n html: html_default,\n raise: raise_default,\n lower: lower_default,\n append: append_default,\n insert: insert_default,\n remove: remove_default,\n clone: clone_default,\n datum: datum_default,\n on: on_default,\n dispatch: dispatch_default2,\n [Symbol.iterator]: iterator_default\n};\nvar selection_default = selection;\n\n// ../../node_modules/d3-selection/src/select.js\nfunction select_default2(selector) {\n return typeof selector === \"string\" ? new Selection2([[document.querySelector(selector)]], [document.documentElement]) : new Selection2([[selector]], root);\n}\n\n// ../../node_modules/d3-selection/src/sourceEvent.js\nfunction sourceEvent_default(event) {\n let sourceEvent;\n while (sourceEvent = event.sourceEvent) event = sourceEvent;\n return event;\n}\n\n// ../../node_modules/d3-selection/src/pointer.js\nfunction pointer_default(event, node) {\n event = sourceEvent_default(event);\n if (node === void 0) node = event.currentTarget;\n if (node) {\n var svg = node.ownerSVGElement || node;\n if (svg.createSVGPoint) {\n var point6 = svg.createSVGPoint();\n point6.x = event.clientX, point6.y = event.clientY;\n point6 = point6.matrixTransform(node.getScreenCTM().inverse());\n return [point6.x, point6.y];\n }\n if (node.getBoundingClientRect) {\n var rect3 = node.getBoundingClientRect();\n return [event.clientX - rect3.left - node.clientLeft, event.clientY - rect3.top - node.clientTop];\n }\n }\n return [event.pageX, event.pageY];\n}\n\n// ../../node_modules/d3-drag/src/noevent.js\nvar nonpassivecapture = { capture: true, passive: false };\nfunction noevent_default(event) {\n event.preventDefault();\n event.stopImmediatePropagation();\n}\n\n// ../../node_modules/d3-drag/src/nodrag.js\nfunction nodrag_default(view) {\n var root2 = view.document.documentElement, selection2 = select_default2(view).on(\"dragstart.drag\", noevent_default, nonpassivecapture);\n if (\"onselectstart\" in root2) {\n selection2.on(\"selectstart.drag\", noevent_default, nonpassivecapture);\n } else {\n root2.__noselect = root2.style.MozUserSelect;\n root2.style.MozUserSelect = \"none\";\n }\n}\nfunction yesdrag(view, noclick) {\n var root2 = view.document.documentElement, selection2 = select_default2(view).on(\"dragstart.drag\", null);\n if (noclick) {\n selection2.on(\"click.drag\", noevent_default, nonpassivecapture);\n setTimeout(function() {\n selection2.on(\"click.drag\", null);\n }, 0);\n }\n if (\"onselectstart\" in root2) {\n selection2.on(\"selectstart.drag\", null);\n } else {\n root2.style.MozUserSelect = root2.__noselect;\n delete root2.__noselect;\n }\n}\n\n// ../../node_modules/d3-color/src/define.js\nfunction define_default(constructor, factory, prototype) {\n constructor.prototype = factory.prototype = prototype;\n prototype.constructor = constructor;\n}\nfunction extend(parent, definition) {\n var prototype = Object.create(parent.prototype);\n for (var key in definition) prototype[key] = definition[key];\n return prototype;\n}\n\n// ../../node_modules/d3-color/src/color.js\nfunction Color() {\n}\nvar darker = 0.7;\nvar brighter = 1 / darker;\nvar reI = \"\\\\s*([+-]?\\\\d+)\\\\s*\";\nvar reN = \"\\\\s*([+-]?(?:\\\\d*\\\\.)?\\\\d+(?:[eE][+-]?\\\\d+)?)\\\\s*\";\nvar reP = \"\\\\s*([+-]?(?:\\\\d*\\\\.)?\\\\d+(?:[eE][+-]?\\\\d+)?)%\\\\s*\";\nvar reHex = /^#([0-9a-f]{3,8})$/;\nvar reRgbInteger = new RegExp(`^rgb\\\\(${reI},${reI},${reI}\\\\)$`);\nvar reRgbPercent = new RegExp(`^rgb\\\\(${reP},${reP},${reP}\\\\)$`);\nvar reRgbaInteger = new RegExp(`^rgba\\\\(${reI},${reI},${reI},${reN}\\\\)$`);\nvar reRgbaPercent = new RegExp(`^rgba\\\\(${reP},${reP},${reP},${reN}\\\\)$`);\nvar reHslPercent = new RegExp(`^hsl\\\\(${reN},${reP},${reP}\\\\)$`);\nvar reHslaPercent = new RegExp(`^hsla\\\\(${reN},${reP},${reP},${reN}\\\\)$`);\nvar named = {\n aliceblue: 15792383,\n antiquewhite: 16444375,\n aqua: 65535,\n aquamarine: 8388564,\n azure: 15794175,\n beige: 16119260,\n bisque: 16770244,\n black: 0,\n blanchedalmond: 16772045,\n blue: 255,\n blueviolet: 9055202,\n brown: 10824234,\n burlywood: 14596231,\n cadetblue: 6266528,\n chartreuse: 8388352,\n chocolate: 13789470,\n coral: 16744272,\n cornflowerblue: 6591981,\n cornsilk: 16775388,\n crimson: 14423100,\n cyan: 65535,\n darkblue: 139,\n darkcyan: 35723,\n darkgoldenrod: 12092939,\n darkgray: 11119017,\n darkgreen: 25600,\n darkgrey: 11119017,\n darkkhaki: 12433259,\n darkmagenta: 9109643,\n darkolivegreen: 5597999,\n darkorange: 16747520,\n darkorchid: 10040012,\n darkred: 9109504,\n darksalmon: 15308410,\n darkseagreen: 9419919,\n darkslateblue: 4734347,\n darkslategray: 3100495,\n darkslategrey: 3100495,\n darkturquoise: 52945,\n darkviolet: 9699539,\n deeppink: 16716947,\n deepskyblue: 49151,\n dimgray: 6908265,\n dimgrey: 6908265,\n dodgerblue: 2003199,\n firebrick: 11674146,\n floralwhite: 16775920,\n forestgreen: 2263842,\n fuchsia: 16711935,\n gainsboro: 14474460,\n ghostwhite: 16316671,\n gold: 16766720,\n goldenrod: 14329120,\n gray: 8421504,\n green: 32768,\n greenyellow: 11403055,\n grey: 8421504,\n honeydew: 15794160,\n hotpink: 16738740,\n indianred: 13458524,\n indigo: 4915330,\n ivory: 16777200,\n khaki: 15787660,\n lavender: 15132410,\n lavenderblush: 16773365,\n lawngreen: 8190976,\n lemonchiffon: 16775885,\n lightblue: 11393254,\n lightcoral: 15761536,\n lightcyan: 14745599,\n lightgoldenrodyellow: 16448210,\n lightgray: 13882323,\n lightgreen: 9498256,\n lightgrey: 13882323,\n lightpink: 16758465,\n lightsalmon: 16752762,\n lightseagreen: 2142890,\n lightskyblue: 8900346,\n lightslategray: 7833753,\n lightslategrey: 7833753,\n lightsteelblue: 11584734,\n lightyellow: 16777184,\n lime: 65280,\n limegreen: 3329330,\n linen: 16445670,\n magenta: 16711935,\n maroon: 8388608,\n mediumaquamarine: 6737322,\n mediumblue: 205,\n mediumorchid: 12211667,\n mediumpurple: 9662683,\n mediumseagreen: 3978097,\n mediumslateblue: 8087790,\n mediumspringgreen: 64154,\n mediumturquoise: 4772300,\n mediumvioletred: 13047173,\n midnightblue: 1644912,\n mintcream: 16121850,\n mistyrose: 16770273,\n moccasin: 16770229,\n navajowhite: 16768685,\n navy: 128,\n oldlace: 16643558,\n olive: 8421376,\n olivedrab: 7048739,\n orange: 16753920,\n orangered: 16729344,\n orchid: 14315734,\n palegoldenrod: 15657130,\n palegreen: 10025880,\n paleturquoise: 11529966,\n palevioletred: 14381203,\n papayawhip: 16773077,\n peachpuff: 16767673,\n peru: 13468991,\n pink: 16761035,\n plum: 14524637,\n powderblue: 11591910,\n purple: 8388736,\n rebeccapurple: 6697881,\n red: 16711680,\n rosybrown: 12357519,\n royalblue: 4286945,\n saddlebrown: 9127187,\n salmon: 16416882,\n sandybrown: 16032864,\n seagreen: 3050327,\n seashell: 16774638,\n sienna: 10506797,\n silver: 12632256,\n skyblue: 8900331,\n slateblue: 6970061,\n slategray: 7372944,\n slategrey: 7372944,\n snow: 16775930,\n springgreen: 65407,\n steelblue: 4620980,\n tan: 13808780,\n teal: 32896,\n thistle: 14204888,\n tomato: 16737095,\n turquoise: 4251856,\n violet: 15631086,\n wheat: 16113331,\n white: 16777215,\n whitesmoke: 16119285,\n yellow: 16776960,\n yellowgreen: 10145074\n};\ndefine_default(Color, color, {\n copy(channels) {\n return Object.assign(new this.constructor(), this, channels);\n },\n displayable() {\n return this.rgb().displayable();\n },\n hex: color_formatHex,\n // Deprecated! Use color.formatHex.\n formatHex: color_formatHex,\n formatHex8: color_formatHex8,\n formatHsl: color_formatHsl,\n formatRgb: color_formatRgb,\n toString: color_formatRgb\n});\nfunction color_formatHex() {\n return this.rgb().formatHex();\n}\nfunction color_formatHex8() {\n return this.rgb().formatHex8();\n}\nfunction color_formatHsl() {\n return hslConvert(this).formatHsl();\n}\nfunction color_formatRgb() {\n return this.rgb().formatRgb();\n}\nfunction color(format3) {\n var m, l;\n format3 = (format3 + \"\").trim().toLowerCase();\n return (m = reHex.exec(format3)) ? (l = m[1].length, m = parseInt(m[1], 16), l === 6 ? rgbn(m) : l === 3 ? new Rgb(m >> 8 & 15 | m >> 4 & 240, m >> 4 & 15 | m & 240, (m & 15) << 4 | m & 15, 1) : l === 8 ? rgba(m >> 24 & 255, m >> 16 & 255, m >> 8 & 255, (m & 255) / 255) : l === 4 ? rgba(m >> 12 & 15 | m >> 8 & 240, m >> 8 & 15 | m >> 4 & 240, m >> 4 & 15 | m & 240, ((m & 15) << 4 | m & 15) / 255) : null) : (m = reRgbInteger.exec(format3)) ? new Rgb(m[1], m[2], m[3], 1) : (m = reRgbPercent.exec(format3)) ? new Rgb(m[1] * 255 / 100, m[2] * 255 / 100, m[3] * 255 / 100, 1) : (m = reRgbaInteger.exec(format3)) ? rgba(m[1], m[2], m[3], m[4]) : (m = reRgbaPercent.exec(format3)) ? rgba(m[1] * 255 / 100, m[2] * 255 / 100, m[3] * 255 / 100, m[4]) : (m = reHslPercent.exec(format3)) ? hsla(m[1], m[2] / 100, m[3] / 100, 1) : (m = reHslaPercent.exec(format3)) ? hsla(m[1], m[2] / 100, m[3] / 100, m[4]) : named.hasOwnProperty(format3) ? rgbn(named[format3]) : format3 === \"transparent\" ? new Rgb(NaN, NaN, NaN, 0) : null;\n}\nfunction rgbn(n) {\n return new Rgb(n >> 16 & 255, n >> 8 & 255, n & 255, 1);\n}\nfunction rgba(r, g, b, a2) {\n if (a2 <= 0) r = g = b = NaN;\n return new Rgb(r, g, b, a2);\n}\nfunction rgbConvert(o) {\n if (!(o instanceof Color)) o = color(o);\n if (!o) return new Rgb();\n o = o.rgb();\n return new Rgb(o.r, o.g, o.b, o.opacity);\n}\nfunction rgb(r, g, b, opacity2) {\n return arguments.length === 1 ? rgbConvert(r) : new Rgb(r, g, b, opacity2 == null ? 1 : opacity2);\n}\nfunction Rgb(r, g, b, opacity2) {\n this.r = +r;\n this.g = +g;\n this.b = +b;\n this.opacity = +opacity2;\n}\ndefine_default(Rgb, rgb, extend(Color, {\n brighter(k2) {\n k2 = k2 == null ? brighter : Math.pow(brighter, k2);\n return new Rgb(this.r * k2, this.g * k2, this.b * k2, this.opacity);\n },\n darker(k2) {\n k2 = k2 == null ? darker : Math.pow(darker, k2);\n return new Rgb(this.r * k2, this.g * k2, this.b * k2, this.opacity);\n },\n rgb() {\n return this;\n },\n clamp() {\n return new Rgb(clampi(this.r), clampi(this.g), clampi(this.b), clampa(this.opacity));\n },\n displayable() {\n return -0.5 <= this.r && this.r < 255.5 && (-0.5 <= this.g && this.g < 255.5) && (-0.5 <= this.b && this.b < 255.5) && (0 <= this.opacity && this.opacity <= 1);\n },\n hex: rgb_formatHex,\n // Deprecated! Use color.formatHex.\n formatHex: rgb_formatHex,\n formatHex8: rgb_formatHex8,\n formatRgb: rgb_formatRgb,\n toString: rgb_formatRgb\n}));\nfunction rgb_formatHex() {\n return `#${hex(this.r)}${hex(this.g)}${hex(this.b)}`;\n}\nfunction rgb_formatHex8() {\n return `#${hex(this.r)}${hex(this.g)}${hex(this.b)}${hex((isNaN(this.opacity) ? 1 : this.opacity) * 255)}`;\n}\nfunction rgb_formatRgb() {\n const a2 = clampa(this.opacity);\n return `${a2 === 1 ? \"rgb(\" : \"rgba(\"}${clampi(this.r)}, ${clampi(this.g)}, ${clampi(this.b)}${a2 === 1 ? \")\" : `, ${a2})`}`;\n}\nfunction clampa(opacity2) {\n return isNaN(opacity2) ? 1 : Math.max(0, Math.min(1, opacity2));\n}\nfunction clampi(value) {\n return Math.max(0, Math.min(255, Math.round(value) || 0));\n}\nfunction hex(value) {\n value = clampi(value);\n return (value < 16 ? \"0\" : \"\") + value.toString(16);\n}\nfunction hsla(h, s2, l, a2) {\n if (a2 <= 0) h = s2 = l = NaN;\n else if (l <= 0 || l >= 1) h = s2 = NaN;\n else if (s2 <= 0) h = NaN;\n return new Hsl(h, s2, l, a2);\n}\nfunction hslConvert(o) {\n if (o instanceof Hsl) return new Hsl(o.h, o.s, o.l, o.opacity);\n if (!(o instanceof Color)) o = color(o);\n if (!o) return new Hsl();\n if (o instanceof Hsl) return o;\n o = o.rgb();\n var r = o.r / 255, g = o.g / 255, b = o.b / 255, min5 = Math.min(r, g, b), max4 = Math.max(r, g, b), h = NaN, s2 = max4 - min5, l = (max4 + min5) / 2;\n if (s2) {\n if (r === max4) h = (g - b) / s2 + (g < b) * 6;\n else if (g === max4) h = (b - r) / s2 + 2;\n else h = (r - g) / s2 + 4;\n s2 /= l < 0.5 ? max4 + min5 : 2 - max4 - min5;\n h *= 60;\n } else {\n s2 = l > 0 && l < 1 ? 0 : h;\n }\n return new Hsl(h, s2, l, o.opacity);\n}\nfunction hsl(h, s2, l, opacity2) {\n return arguments.length === 1 ? hslConvert(h) : new Hsl(h, s2, l, opacity2 == null ? 1 : opacity2);\n}\nfunction Hsl(h, s2, l, opacity2) {\n this.h = +h;\n this.s = +s2;\n this.l = +l;\n this.opacity = +opacity2;\n}\ndefine_default(Hsl, hsl, extend(Color, {\n brighter(k2) {\n k2 = k2 == null ? brighter : Math.pow(brighter, k2);\n return new Hsl(this.h, this.s, this.l * k2, this.opacity);\n },\n darker(k2) {\n k2 = k2 == null ? darker : Math.pow(darker, k2);\n return new Hsl(this.h, this.s, this.l * k2, this.opacity);\n },\n rgb() {\n var h = this.h % 360 + (this.h < 0) * 360, s2 = isNaN(h) || isNaN(this.s) ? 0 : this.s, l = this.l, m2 = l + (l < 0.5 ? l : 1 - l) * s2, m1 = 2 * l - m2;\n return new Rgb(\n hsl2rgb(h >= 240 ? h - 240 : h + 120, m1, m2),\n hsl2rgb(h, m1, m2),\n hsl2rgb(h < 120 ? h + 240 : h - 120, m1, m2),\n this.opacity\n );\n },\n clamp() {\n return new Hsl(clamph(this.h), clampt(this.s), clampt(this.l), clampa(this.opacity));\n },\n displayable() {\n return (0 <= this.s && this.s <= 1 || isNaN(this.s)) && (0 <= this.l && this.l <= 1) && (0 <= this.opacity && this.opacity <= 1);\n },\n formatHsl() {\n const a2 = clampa(this.opacity);\n return `${a2 === 1 ? \"hsl(\" : \"hsla(\"}${clamph(this.h)}, ${clampt(this.s) * 100}%, ${clampt(this.l) * 100}%${a2 === 1 ? \")\" : `, ${a2})`}`;\n }\n}));\nfunction clamph(value) {\n value = (value || 0) % 360;\n return value < 0 ? value + 360 : value;\n}\nfunction clampt(value) {\n return Math.max(0, Math.min(1, value || 0));\n}\nfunction hsl2rgb(h, m1, m2) {\n return (h < 60 ? m1 + (m2 - m1) * h / 60 : h < 180 ? m2 : h < 240 ? m1 + (m2 - m1) * (240 - h) / 60 : m1) * 255;\n}\n\n// ../../node_modules/d3-color/src/math.js\nvar radians = Math.PI / 180;\nvar degrees = 180 / Math.PI;\n\n// ../../node_modules/d3-color/src/lab.js\nvar K = 18;\nvar Xn = 0.96422;\nvar Yn = 1;\nvar Zn = 0.82521;\nvar t0 = 4 / 29;\nvar t1 = 6 / 29;\nvar t2 = 3 * t1 * t1;\nvar t3 = t1 * t1 * t1;\nfunction labConvert(o) {\n if (o instanceof Lab) return new Lab(o.l, o.a, o.b, o.opacity);\n if (o instanceof Hcl) return hcl2lab(o);\n if (!(o instanceof Rgb)) o = rgbConvert(o);\n var r = rgb2lrgb(o.r), g = rgb2lrgb(o.g), b = rgb2lrgb(o.b), y3 = xyz2lab((0.2225045 * r + 0.7168786 * g + 0.0606169 * b) / Yn), x3, z;\n if (r === g && g === b) x3 = z = y3;\n else {\n x3 = xyz2lab((0.4360747 * r + 0.3850649 * g + 0.1430804 * b) / Xn);\n z = xyz2lab((0.0139322 * r + 0.0971045 * g + 0.7141733 * b) / Zn);\n }\n return new Lab(116 * y3 - 16, 500 * (x3 - y3), 200 * (y3 - z), o.opacity);\n}\nfunction lab(l, a2, b, opacity2) {\n return arguments.length === 1 ? labConvert(l) : new Lab(l, a2, b, opacity2 == null ? 1 : opacity2);\n}\nfunction Lab(l, a2, b, opacity2) {\n this.l = +l;\n this.a = +a2;\n this.b = +b;\n this.opacity = +opacity2;\n}\ndefine_default(Lab, lab, extend(Color, {\n brighter(k2) {\n return new Lab(this.l + K * (k2 == null ? 1 : k2), this.a, this.b, this.opacity);\n },\n darker(k2) {\n return new Lab(this.l - K * (k2 == null ? 1 : k2), this.a, this.b, this.opacity);\n },\n rgb() {\n var y3 = (this.l + 16) / 116, x3 = isNaN(this.a) ? y3 : y3 + this.a / 500, z = isNaN(this.b) ? y3 : y3 - this.b / 200;\n x3 = Xn * lab2xyz(x3);\n y3 = Yn * lab2xyz(y3);\n z = Zn * lab2xyz(z);\n return new Rgb(\n lrgb2rgb(3.1338561 * x3 - 1.6168667 * y3 - 0.4906146 * z),\n lrgb2rgb(-0.9787684 * x3 + 1.9161415 * y3 + 0.033454 * z),\n lrgb2rgb(0.0719453 * x3 - 0.2289914 * y3 + 1.4052427 * z),\n this.opacity\n );\n }\n}));\nfunction xyz2lab(t) {\n return t > t3 ? Math.pow(t, 1 / 3) : t / t2 + t0;\n}\nfunction lab2xyz(t) {\n return t > t1 ? t * t * t : t2 * (t - t0);\n}\nfunction lrgb2rgb(x3) {\n return 255 * (x3 <= 31308e-7 ? 12.92 * x3 : 1.055 * Math.pow(x3, 1 / 2.4) - 0.055);\n}\nfunction rgb2lrgb(x3) {\n return (x3 /= 255) <= 0.04045 ? x3 / 12.92 : Math.pow((x3 + 0.055) / 1.055, 2.4);\n}\nfunction hclConvert(o) {\n if (o instanceof Hcl) return new Hcl(o.h, o.c, o.l, o.opacity);\n if (!(o instanceof Lab)) o = labConvert(o);\n if (o.a === 0 && o.b === 0) return new Hcl(NaN, 0 < o.l && o.l < 100 ? 0 : NaN, o.l, o.opacity);\n var h = Math.atan2(o.b, o.a) * degrees;\n return new Hcl(h < 0 ? h + 360 : h, Math.sqrt(o.a * o.a + o.b * o.b), o.l, o.opacity);\n}\nfunction hcl(h, c4, l, opacity2) {\n return arguments.length === 1 ? hclConvert(h) : new Hcl(h, c4, l, opacity2 == null ? 1 : opacity2);\n}\nfunction Hcl(h, c4, l, opacity2) {\n this.h = +h;\n this.c = +c4;\n this.l = +l;\n this.opacity = +opacity2;\n}\nfunction hcl2lab(o) {\n if (isNaN(o.h)) return new Lab(o.l, 0, 0, o.opacity);\n var h = o.h * radians;\n return new Lab(o.l, Math.cos(h) * o.c, Math.sin(h) * o.c, o.opacity);\n}\ndefine_default(Hcl, hcl, extend(Color, {\n brighter(k2) {\n return new Hcl(this.h, this.c, this.l + K * (k2 == null ? 1 : k2), this.opacity);\n },\n darker(k2) {\n return new Hcl(this.h, this.c, this.l - K * (k2 == null ? 1 : k2), this.opacity);\n },\n rgb() {\n return hcl2lab(this).rgb();\n }\n}));\n\n// ../../node_modules/d3-color/src/cubehelix.js\nvar A = -0.14861;\nvar B = 1.78277;\nvar C = -0.29227;\nvar D = -0.90649;\nvar E = 1.97294;\nvar ED = E * D;\nvar EB = E * B;\nvar BC_DA = B * C - D * A;\nfunction cubehelixConvert(o) {\n if (o instanceof Cubehelix) return new Cubehelix(o.h, o.s, o.l, o.opacity);\n if (!(o instanceof Rgb)) o = rgbConvert(o);\n var r = o.r / 255, g = o.g / 255, b = o.b / 255, l = (BC_DA * b + ED * r - EB * g) / (BC_DA + ED - EB), bl = b - l, k2 = (E * (g - l) - C * bl) / D, s2 = Math.sqrt(k2 * k2 + bl * bl) / (E * l * (1 - l)), h = s2 ? Math.atan2(k2, bl) * degrees - 120 : NaN;\n return new Cubehelix(h < 0 ? h + 360 : h, s2, l, o.opacity);\n}\nfunction cubehelix(h, s2, l, opacity2) {\n return arguments.length === 1 ? cubehelixConvert(h) : new Cubehelix(h, s2, l, opacity2 == null ? 1 : opacity2);\n}\nfunction Cubehelix(h, s2, l, opacity2) {\n this.h = +h;\n this.s = +s2;\n this.l = +l;\n this.opacity = +opacity2;\n}\ndefine_default(Cubehelix, cubehelix, extend(Color, {\n brighter(k2) {\n k2 = k2 == null ? brighter : Math.pow(brighter, k2);\n return new Cubehelix(this.h, this.s, this.l * k2, this.opacity);\n },\n darker(k2) {\n k2 = k2 == null ? darker : Math.pow(darker, k2);\n return new Cubehelix(this.h, this.s, this.l * k2, this.opacity);\n },\n rgb() {\n var h = isNaN(this.h) ? 0 : (this.h + 120) * radians, l = +this.l, a2 = isNaN(this.s) ? 0 : this.s * l * (1 - l), cosh2 = Math.cos(h), sinh2 = Math.sin(h);\n return new Rgb(\n 255 * (l + a2 * (A * cosh2 + B * sinh2)),\n 255 * (l + a2 * (C * cosh2 + D * sinh2)),\n 255 * (l + a2 * (E * cosh2)),\n this.opacity\n );\n }\n}));\n\n// ../../node_modules/d3-interpolate/src/basis.js\nfunction basis(t13, v0, v1, v2, v3) {\n var t22 = t13 * t13, t32 = t22 * t13;\n return ((1 - 3 * t13 + 3 * t22 - t32) * v0 + (4 - 6 * t22 + 3 * t32) * v1 + (1 + 3 * t13 + 3 * t22 - 3 * t32) * v2 + t32 * v3) / 6;\n}\nfunction basis_default(values2) {\n var n = values2.length - 1;\n return function(t) {\n var i = t <= 0 ? t = 0 : t >= 1 ? (t = 1, n - 1) : Math.floor(t * n), v1 = values2[i], v2 = values2[i + 1], v0 = i > 0 ? values2[i - 1] : 2 * v1 - v2, v3 = i < n - 1 ? values2[i + 2] : 2 * v2 - v1;\n return basis((t - i / n) * n, v0, v1, v2, v3);\n };\n}\n\n// ../../node_modules/d3-interpolate/src/basisClosed.js\nfunction basisClosed_default(values2) {\n var n = values2.length;\n return function(t) {\n var i = Math.floor(((t %= 1) < 0 ? ++t : t) * n), v0 = values2[(i + n - 1) % n], v1 = values2[i % n], v2 = values2[(i + 1) % n], v3 = values2[(i + 2) % n];\n return basis((t - i / n) * n, v0, v1, v2, v3);\n };\n}\n\n// ../../node_modules/d3-interpolate/src/constant.js\nvar constant_default2 = (x3) => () => x3;\n\n// ../../node_modules/d3-interpolate/src/color.js\nfunction linear(a2, d) {\n return function(t) {\n return a2 + t * d;\n };\n}\nfunction exponential(a2, b, y3) {\n return a2 = Math.pow(a2, y3), b = Math.pow(b, y3) - a2, y3 = 1 / y3, function(t) {\n return Math.pow(a2 + t * b, y3);\n };\n}\nfunction hue(a2, b) {\n var d = b - a2;\n return d ? linear(a2, d > 180 || d < -180 ? d - 360 * Math.round(d / 360) : d) : constant_default2(isNaN(a2) ? b : a2);\n}\nfunction gamma(y3) {\n return (y3 = +y3) === 1 ? nogamma : function(a2, b) {\n return b - a2 ? exponential(a2, b, y3) : constant_default2(isNaN(a2) ? b : a2);\n };\n}\nfunction nogamma(a2, b) {\n var d = b - a2;\n return d ? linear(a2, d) : constant_default2(isNaN(a2) ? b : a2);\n}\n\n// ../../node_modules/d3-interpolate/src/rgb.js\nvar rgb_default = function rgbGamma(y3) {\n var color3 = gamma(y3);\n function rgb2(start2, end) {\n var r = color3((start2 = rgb(start2)).r, (end = rgb(end)).r), g = color3(start2.g, end.g), b = color3(start2.b, end.b), opacity2 = nogamma(start2.opacity, end.opacity);\n return function(t) {\n start2.r = r(t);\n start2.g = g(t);\n start2.b = b(t);\n start2.opacity = opacity2(t);\n return start2 + \"\";\n };\n }\n rgb2.gamma = rgbGamma;\n return rgb2;\n}(1);\nfunction rgbSpline(spline) {\n return function(colors) {\n var n = colors.length, r = new Array(n), g = new Array(n), b = new Array(n), i, color3;\n for (i = 0; i < n; ++i) {\n color3 = rgb(colors[i]);\n r[i] = color3.r || 0;\n g[i] = color3.g || 0;\n b[i] = color3.b || 0;\n }\n r = spline(r);\n g = spline(g);\n b = spline(b);\n color3.opacity = 1;\n return function(t) {\n color3.r = r(t);\n color3.g = g(t);\n color3.b = b(t);\n return color3 + \"\";\n };\n };\n}\nvar rgbBasis = rgbSpline(basis_default);\nvar rgbBasisClosed = rgbSpline(basisClosed_default);\n\n// ../../node_modules/d3-interpolate/src/numberArray.js\nfunction numberArray_default(a2, b) {\n if (!b) b = [];\n var n = a2 ? Math.min(b.length, a2.length) : 0, c4 = b.slice(), i;\n return function(t) {\n for (i = 0; i < n; ++i) c4[i] = a2[i] * (1 - t) + b[i] * t;\n return c4;\n };\n}\nfunction isNumberArray(x3) {\n return ArrayBuffer.isView(x3) && !(x3 instanceof DataView);\n}\n\n// ../../node_modules/d3-interpolate/src/array.js\nfunction genericArray(a2, b) {\n var nb = b ? b.length : 0, na = a2 ? Math.min(nb, a2.length) : 0, x3 = new Array(na), c4 = new Array(nb), i;\n for (i = 0; i < na; ++i) x3[i] = value_default(a2[i], b[i]);\n for (; i < nb; ++i) c4[i] = b[i];\n return function(t) {\n for (i = 0; i < na; ++i) c4[i] = x3[i](t);\n return c4;\n };\n}\n\n// ../../node_modules/d3-interpolate/src/date.js\nfunction date_default(a2, b) {\n var d = /* @__PURE__ */ new Date();\n return a2 = +a2, b = +b, function(t) {\n return d.setTime(a2 * (1 - t) + b * t), d;\n };\n}\n\n// ../../node_modules/d3-interpolate/src/number.js\nfunction number_default(a2, b) {\n return a2 = +a2, b = +b, function(t) {\n return a2 * (1 - t) + b * t;\n };\n}\n\n// ../../node_modules/d3-interpolate/src/object.js\nfunction object_default(a2, b) {\n var i = {}, c4 = {}, k2;\n if (a2 === null || typeof a2 !== \"object\") a2 = {};\n if (b === null || typeof b !== \"object\") b = {};\n for (k2 in b) {\n if (k2 in a2) {\n i[k2] = value_default(a2[k2], b[k2]);\n } else {\n c4[k2] = b[k2];\n }\n }\n return function(t) {\n for (k2 in i) c4[k2] = i[k2](t);\n return c4;\n };\n}\n\n// ../../node_modules/d3-interpolate/src/string.js\nvar reA = /[-+]?(?:\\d+\\.?\\d*|\\.?\\d+)(?:[eE][-+]?\\d+)?/g;\nvar reB = new RegExp(reA.source, \"g\");\nfunction zero2(b) {\n return function() {\n return b;\n };\n}\nfunction one(b) {\n return function(t) {\n return b(t) + \"\";\n };\n}\nfunction string_default(a2, b) {\n var bi = reA.lastIndex = reB.lastIndex = 0, am, bm, bs, i = -1, s2 = [], q = [];\n a2 = a2 + \"\", b = b + \"\";\n while ((am = reA.exec(a2)) && (bm = reB.exec(b))) {\n if ((bs = bm.index) > bi) {\n bs = b.slice(bi, bs);\n if (s2[i]) s2[i] += bs;\n else s2[++i] = bs;\n }\n if ((am = am[0]) === (bm = bm[0])) {\n if (s2[i]) s2[i] += bm;\n else s2[++i] = bm;\n } else {\n s2[++i] = null;\n q.push({ i, x: number_default(am, bm) });\n }\n bi = reB.lastIndex;\n }\n if (bi < b.length) {\n bs = b.slice(bi);\n if (s2[i]) s2[i] += bs;\n else s2[++i] = bs;\n }\n return s2.length < 2 ? q[0] ? one(q[0].x) : zero2(b) : (b = q.length, function(t) {\n for (var i2 = 0, o; i2 < b; ++i2) s2[(o = q[i2]).i] = o.x(t);\n return s2.join(\"\");\n });\n}\n\n// ../../node_modules/d3-interpolate/src/value.js\nfunction value_default(a2, b) {\n var t = typeof b, c4;\n return b == null || t === \"boolean\" ? constant_default2(b) : (t === \"number\" ? number_default : t === \"string\" ? (c4 = color(b)) ? (b = c4, rgb_default) : string_default : b instanceof color ? rgb_default : b instanceof Date ? date_default : isNumberArray(b) ? numberArray_default : Array.isArray(b) ? genericArray : typeof b.valueOf !== \"function\" && typeof b.toString !== \"function\" || isNaN(b) ? object_default : number_default)(a2, b);\n}\n\n// ../../node_modules/d3-interpolate/src/round.js\nfunction round_default(a2, b) {\n return a2 = +a2, b = +b, function(t) {\n return Math.round(a2 * (1 - t) + b * t);\n };\n}\n\n// ../../node_modules/d3-interpolate/src/transform/decompose.js\nvar degrees2 = 180 / Math.PI;\nvar identity3 = {\n translateX: 0,\n translateY: 0,\n rotate: 0,\n skewX: 0,\n scaleX: 1,\n scaleY: 1\n};\nfunction decompose_default(a2, b, c4, d, e, f) {\n var scaleX, scaleY, skewX;\n if (scaleX = Math.sqrt(a2 * a2 + b * b)) a2 /= scaleX, b /= scaleX;\n if (skewX = a2 * c4 + b * d) c4 -= a2 * skewX, d -= b * skewX;\n if (scaleY = Math.sqrt(c4 * c4 + d * d)) c4 /= scaleY, d /= scaleY, skewX /= scaleY;\n if (a2 * d < b * c4) a2 = -a2, b = -b, skewX = -skewX, scaleX = -scaleX;\n return {\n translateX: e,\n translateY: f,\n rotate: Math.atan2(b, a2) * degrees2,\n skewX: Math.atan(skewX) * degrees2,\n scaleX,\n scaleY\n };\n}\n\n// ../../node_modules/d3-interpolate/src/transform/parse.js\nvar svgNode;\nfunction parseCss(value) {\n const m = new (typeof DOMMatrix === \"function\" ? DOMMatrix : WebKitCSSMatrix)(value + \"\");\n return m.isIdentity ? identity3 : decompose_default(m.a, m.b, m.c, m.d, m.e, m.f);\n}\nfunction parseSvg(value) {\n if (value == null) return identity3;\n if (!svgNode) svgNode = document.createElementNS(\"http://www.w3.org/2000/svg\", \"g\");\n svgNode.setAttribute(\"transform\", value);\n if (!(value = svgNode.transform.baseVal.consolidate())) return identity3;\n value = value.matrix;\n return decompose_default(value.a, value.b, value.c, value.d, value.e, value.f);\n}\n\n// ../../node_modules/d3-interpolate/src/transform/index.js\nfunction interpolateTransform(parse2, pxComma, pxParen, degParen) {\n function pop(s2) {\n return s2.length ? s2.pop() + \" \" : \"\";\n }\n function translate(xa, ya, xb, yb, s2, q) {\n if (xa !== xb || ya !== yb) {\n var i = s2.push(\"translate(\", null, pxComma, null, pxParen);\n q.push({ i: i - 4, x: number_default(xa, xb) }, { i: i - 2, x: number_default(ya, yb) });\n } else if (xb || yb) {\n s2.push(\"translate(\" + xb + pxComma + yb + pxParen);\n }\n }\n function rotate(a2, b, s2, q) {\n if (a2 !== b) {\n if (a2 - b > 180) b += 360;\n else if (b - a2 > 180) a2 += 360;\n q.push({ i: s2.push(pop(s2) + \"rotate(\", null, degParen) - 2, x: number_default(a2, b) });\n } else if (b) {\n s2.push(pop(s2) + \"rotate(\" + b + degParen);\n }\n }\n function skewX(a2, b, s2, q) {\n if (a2 !== b) {\n q.push({ i: s2.push(pop(s2) + \"skewX(\", null, degParen) - 2, x: number_default(a2, b) });\n } else if (b) {\n s2.push(pop(s2) + \"skewX(\" + b + degParen);\n }\n }\n function scale3(xa, ya, xb, yb, s2, q) {\n if (xa !== xb || ya !== yb) {\n var i = s2.push(pop(s2) + \"scale(\", null, \",\", null, \")\");\n q.push({ i: i - 4, x: number_default(xa, xb) }, { i: i - 2, x: number_default(ya, yb) });\n } else if (xb !== 1 || yb !== 1) {\n s2.push(pop(s2) + \"scale(\" + xb + \",\" + yb + \")\");\n }\n }\n return function(a2, b) {\n var s2 = [], q = [];\n a2 = parse2(a2), b = parse2(b);\n translate(a2.translateX, a2.translateY, b.translateX, b.translateY, s2, q);\n rotate(a2.rotate, b.rotate, s2, q);\n skewX(a2.skewX, b.skewX, s2, q);\n scale3(a2.scaleX, a2.scaleY, b.scaleX, b.scaleY, s2, q);\n a2 = b = null;\n return function(t) {\n var i = -1, n = q.length, o;\n while (++i < n) s2[(o = q[i]).i] = o.x(t);\n return s2.join(\"\");\n };\n };\n}\nvar interpolateTransformCss = interpolateTransform(parseCss, \"px, \", \"px)\", \"deg)\");\nvar interpolateTransformSvg = interpolateTransform(parseSvg, \", \", \")\", \")\");\n\n// ../../node_modules/d3-interpolate/src/zoom.js\nvar epsilon2 = 1e-12;\nfunction cosh(x3) {\n return ((x3 = Math.exp(x3)) + 1 / x3) / 2;\n}\nfunction sinh(x3) {\n return ((x3 = Math.exp(x3)) - 1 / x3) / 2;\n}\nfunction tanh(x3) {\n return ((x3 = Math.exp(2 * x3)) - 1) / (x3 + 1);\n}\nvar zoom_default = function zoomRho(rho, rho2, rho4) {\n function zoom2(p0, p1) {\n var ux0 = p0[0], uy0 = p0[1], w0 = p0[2], ux1 = p1[0], uy1 = p1[1], w1 = p1[2], dx = ux1 - ux0, dy = uy1 - uy0, d2 = dx * dx + dy * dy, i, S;\n if (d2 < epsilon2) {\n S = Math.log(w1 / w0) / rho;\n i = function(t) {\n return [\n ux0 + t * dx,\n uy0 + t * dy,\n w0 * Math.exp(rho * t * S)\n ];\n };\n } else {\n var d1 = Math.sqrt(d2), b0 = (w1 * w1 - w0 * w0 + rho4 * d2) / (2 * w0 * rho2 * d1), b1 = (w1 * w1 - w0 * w0 - rho4 * d2) / (2 * w1 * rho2 * d1), r0 = Math.log(Math.sqrt(b0 * b0 + 1) - b0), r1 = Math.log(Math.sqrt(b1 * b1 + 1) - b1);\n S = (r1 - r0) / rho;\n i = function(t) {\n var s2 = t * S, coshr0 = cosh(r0), u4 = w0 / (rho2 * d1) * (coshr0 * tanh(rho * s2 + r0) - sinh(r0));\n return [\n ux0 + u4 * dx,\n uy0 + u4 * dy,\n w0 * coshr0 / cosh(rho * s2 + r0)\n ];\n };\n }\n i.duration = S * 1e3 * rho / Math.SQRT2;\n return i;\n }\n zoom2.rho = function(_) {\n var _1 = Math.max(1e-3, +_), _2 = _1 * _1, _4 = _2 * _2;\n return zoomRho(_1, _2, _4);\n };\n return zoom2;\n}(Math.SQRT2, 2, 4);\n\n// ../../node_modules/d3-interpolate/src/hsl.js\nfunction hsl2(hue2) {\n return function(start2, end) {\n var h = hue2((start2 = hsl(start2)).h, (end = hsl(end)).h), s2 = nogamma(start2.s, end.s), l = nogamma(start2.l, end.l), opacity2 = nogamma(start2.opacity, end.opacity);\n return function(t) {\n start2.h = h(t);\n start2.s = s2(t);\n start2.l = l(t);\n start2.opacity = opacity2(t);\n return start2 + \"\";\n };\n };\n}\nvar hsl_default = hsl2(hue);\nvar hslLong = hsl2(nogamma);\n\n// ../../node_modules/d3-interpolate/src/lab.js\nfunction lab2(start2, end) {\n var l = nogamma((start2 = lab(start2)).l, (end = lab(end)).l), a2 = nogamma(start2.a, end.a), b = nogamma(start2.b, end.b), opacity2 = nogamma(start2.opacity, end.opacity);\n return function(t) {\n start2.l = l(t);\n start2.a = a2(t);\n start2.b = b(t);\n start2.opacity = opacity2(t);\n return start2 + \"\";\n };\n}\n\n// ../../node_modules/d3-interpolate/src/hcl.js\nfunction hcl2(hue2) {\n return function(start2, end) {\n var h = hue2((start2 = hcl(start2)).h, (end = hcl(end)).h), c4 = nogamma(start2.c, end.c), l = nogamma(start2.l, end.l), opacity2 = nogamma(start2.opacity, end.opacity);\n return function(t) {\n start2.h = h(t);\n start2.c = c4(t);\n start2.l = l(t);\n start2.opacity = opacity2(t);\n return start2 + \"\";\n };\n };\n}\nvar hcl_default = hcl2(hue);\nvar hclLong = hcl2(nogamma);\n\n// ../../node_modules/d3-interpolate/src/cubehelix.js\nfunction cubehelix2(hue2) {\n return function cubehelixGamma(y3) {\n y3 = +y3;\n function cubehelix3(start2, end) {\n var h = hue2((start2 = cubehelix(start2)).h, (end = cubehelix(end)).h), s2 = nogamma(start2.s, end.s), l = nogamma(start2.l, end.l), opacity2 = nogamma(start2.opacity, end.opacity);\n return function(t) {\n start2.h = h(t);\n start2.s = s2(t);\n start2.l = l(Math.pow(t, y3));\n start2.opacity = opacity2(t);\n return start2 + \"\";\n };\n }\n cubehelix3.gamma = cubehelixGamma;\n return cubehelix3;\n }(1);\n}\nvar cubehelix_default = cubehelix2(hue);\nvar cubehelixLong = cubehelix2(nogamma);\n\n// ../../node_modules/d3-interpolate/src/piecewise.js\nfunction piecewise(interpolate, values2) {\n if (values2 === void 0) values2 = interpolate, interpolate = value_default;\n var i = 0, n = values2.length - 1, v2 = values2[0], I = new Array(n < 0 ? 0 : n);\n while (i < n) I[i] = interpolate(v2, v2 = values2[++i]);\n return function(t) {\n var i2 = Math.max(0, Math.min(n - 1, Math.floor(t *= n)));\n return I[i2](t - i2);\n };\n}\n\n// ../../node_modules/d3-interpolate/src/quantize.js\nfunction quantize_default(interpolator, n) {\n var samples = new Array(n);\n for (var i = 0; i < n; ++i) samples[i] = interpolator(i / (n - 1));\n return samples;\n}\n\n// ../../node_modules/d3-timer/src/timer.js\nvar frame = 0;\nvar timeout = 0;\nvar interval2 = 0;\nvar pokeDelay = 1e3;\nvar taskHead;\nvar taskTail;\nvar clockLast = 0;\nvar clockNow = 0;\nvar clockSkew = 0;\nvar clock = typeof performance === \"object\" && performance.now ? performance : Date;\nvar setFrame = typeof window === \"object\" && window.requestAnimationFrame ? window.requestAnimationFrame.bind(window) : function(f) {\n setTimeout(f, 17);\n};\nfunction now() {\n return clockNow || (setFrame(clearNow), clockNow = clock.now() + clockSkew);\n}\nfunction clearNow() {\n clockNow = 0;\n}\nfunction Timer() {\n this._call = this._time = this._next = null;\n}\nTimer.prototype = timer.prototype = {\n constructor: Timer,\n restart: function(callback, delay, time3) {\n if (typeof callback !== \"function\") throw new TypeError(\"callback is not a function\");\n time3 = (time3 == null ? now() : +time3) + (delay == null ? 0 : +delay);\n if (!this._next && taskTail !== this) {\n if (taskTail) taskTail._next = this;\n else taskHead = this;\n taskTail = this;\n }\n this._call = callback;\n this._time = time3;\n sleep();\n },\n stop: function() {\n if (this._call) {\n this._call = null;\n this._time = Infinity;\n sleep();\n }\n }\n};\nfunction timer(callback, delay, time3) {\n var t = new Timer();\n t.restart(callback, delay, time3);\n return t;\n}\nfunction timerFlush() {\n now();\n ++frame;\n var t = taskHead, e;\n while (t) {\n if ((e = clockNow - t._time) >= 0) t._call.call(void 0, e);\n t = t._next;\n }\n --frame;\n}\nfunction wake() {\n clockNow = (clockLast = clock.now()) + clockSkew;\n frame = timeout = 0;\n try {\n timerFlush();\n } finally {\n frame = 0;\n nap();\n clockNow = 0;\n }\n}\nfunction poke() {\n var now2 = clock.now(), delay = now2 - clockLast;\n if (delay > pokeDelay) clockSkew -= delay, clockLast = now2;\n}\nfunction nap() {\n var t03, t13 = taskHead, t22, time3 = Infinity;\n while (t13) {\n if (t13._call) {\n if (time3 > t13._time) time3 = t13._time;\n t03 = t13, t13 = t13._next;\n } else {\n t22 = t13._next, t13._next = null;\n t13 = t03 ? t03._next = t22 : taskHead = t22;\n }\n }\n taskTail = t03;\n sleep(time3);\n}\nfunction sleep(time3) {\n if (frame) return;\n if (timeout) timeout = clearTimeout(timeout);\n var delay = time3 - clockNow;\n if (delay > 24) {\n if (time3 < Infinity) timeout = setTimeout(wake, time3 - clock.now() - clockSkew);\n if (interval2) interval2 = clearInterval(interval2);\n } else {\n if (!interval2) clockLast = clock.now(), interval2 = setInterval(poke, pokeDelay);\n frame = 1, setFrame(wake);\n }\n}\n\n// ../../node_modules/d3-timer/src/timeout.js\nfunction timeout_default(callback, delay, time3) {\n var t = new Timer();\n delay = delay == null ? 0 : +delay;\n t.restart((elapsed) => {\n t.stop();\n callback(elapsed + delay);\n }, delay, time3);\n return t;\n}\n\n// ../../node_modules/d3-transition/src/transition/schedule.js\nvar emptyOn = dispatch_default(\"start\", \"end\", \"cancel\", \"interrupt\");\nvar emptyTween = [];\nvar CREATED = 0;\nvar SCHEDULED = 1;\nvar STARTING = 2;\nvar STARTED = 3;\nvar RUNNING = 4;\nvar ENDING = 5;\nvar ENDED = 6;\nfunction schedule_default(node, name2, id2, index2, group3, timing) {\n var schedules = node.__transition;\n if (!schedules) node.__transition = {};\n else if (id2 in schedules) return;\n create3(node, id2, {\n name: name2,\n index: index2,\n // For context during callback.\n group: group3,\n // For context during callback.\n on: emptyOn,\n tween: emptyTween,\n time: timing.time,\n delay: timing.delay,\n duration: timing.duration,\n ease: timing.ease,\n timer: null,\n state: CREATED\n });\n}\nfunction init(node, id2) {\n var schedule = get2(node, id2);\n if (schedule.state > CREATED) throw new Error(\"too late; already scheduled\");\n return schedule;\n}\nfunction set2(node, id2) {\n var schedule = get2(node, id2);\n if (schedule.state > STARTED) throw new Error(\"too late; already running\");\n return schedule;\n}\nfunction get2(node, id2) {\n var schedule = node.__transition;\n if (!schedule || !(schedule = schedule[id2])) throw new Error(\"transition not found\");\n return schedule;\n}\nfunction create3(node, id2, self) {\n var schedules = node.__transition, tween;\n schedules[id2] = self;\n self.timer = timer(schedule, 0, self.time);\n function schedule(elapsed) {\n self.state = SCHEDULED;\n self.timer.restart(start2, self.delay, self.time);\n if (self.delay <= elapsed) start2(elapsed - self.delay);\n }\n function start2(elapsed) {\n var i, j, n, o;\n if (self.state !== SCHEDULED) return stop();\n for (i in schedules) {\n o = schedules[i];\n if (o.name !== self.name) continue;\n if (o.state === STARTED) return timeout_default(start2);\n if (o.state === RUNNING) {\n o.state = ENDED;\n o.timer.stop();\n o.on.call(\"interrupt\", node, node.__data__, o.index, o.group);\n delete schedules[i];\n } else if (+i < id2) {\n o.state = ENDED;\n o.timer.stop();\n o.on.call(\"cancel\", node, node.__data__, o.index, o.group);\n delete schedules[i];\n }\n }\n timeout_default(function() {\n if (self.state === STARTED) {\n self.state = RUNNING;\n self.timer.restart(tick, self.delay, self.time);\n tick(elapsed);\n }\n });\n self.state = STARTING;\n self.on.call(\"start\", node, node.__data__, self.index, self.group);\n if (self.state !== STARTING) return;\n self.state = STARTED;\n tween = new Array(n = self.tween.length);\n for (i = 0, j = -1; i < n; ++i) {\n if (o = self.tween[i].value.call(node, node.__data__, self.index, self.group)) {\n tween[++j] = o;\n }\n }\n tween.length = j + 1;\n }\n function tick(elapsed) {\n var t = elapsed < self.duration ? self.ease.call(null, elapsed / self.duration) : (self.timer.restart(stop), self.state = ENDING, 1), i = -1, n = tween.length;\n while (++i < n) {\n tween[i].call(node, t);\n }\n if (self.state === ENDING) {\n self.on.call(\"end\", node, node.__data__, self.index, self.group);\n stop();\n }\n }\n function stop() {\n self.state = ENDED;\n self.timer.stop();\n delete schedules[id2];\n for (var i in schedules) return;\n delete node.__transition;\n }\n}\n\n// ../../node_modules/d3-transition/src/interrupt.js\nfunction interrupt_default(node, name2) {\n var schedules = node.__transition, schedule, active, empty4 = true, i;\n if (!schedules) return;\n name2 = name2 == null ? null : name2 + \"\";\n for (i in schedules) {\n if ((schedule = schedules[i]).name !== name2) {\n empty4 = false;\n continue;\n }\n active = schedule.state > STARTING && schedule.state < ENDING;\n schedule.state = ENDED;\n schedule.timer.stop();\n schedule.on.call(active ? \"interrupt\" : \"cancel\", node, node.__data__, schedule.index, schedule.group);\n delete schedules[i];\n }\n if (empty4) delete node.__transition;\n}\n\n// ../../node_modules/d3-transition/src/selection/interrupt.js\nfunction interrupt_default2(name2) {\n return this.each(function() {\n interrupt_default(this, name2);\n });\n}\n\n// ../../node_modules/d3-transition/src/transition/tween.js\nfunction tweenRemove(id2, name2) {\n var tween0, tween1;\n return function() {\n var schedule = set2(this, id2), tween = schedule.tween;\n if (tween !== tween0) {\n tween1 = tween0 = tween;\n for (var i = 0, n = tween1.length; i < n; ++i) {\n if (tween1[i].name === name2) {\n tween1 = tween1.slice();\n tween1.splice(i, 1);\n break;\n }\n }\n }\n schedule.tween = tween1;\n };\n}\nfunction tweenFunction(id2, name2, value) {\n var tween0, tween1;\n if (typeof value !== \"function\") throw new Error();\n return function() {\n var schedule = set2(this, id2), tween = schedule.tween;\n if (tween !== tween0) {\n tween1 = (tween0 = tween).slice();\n for (var t = { name: name2, value }, i = 0, n = tween1.length; i < n; ++i) {\n if (tween1[i].name === name2) {\n tween1[i] = t;\n break;\n }\n }\n if (i === n) tween1.push(t);\n }\n schedule.tween = tween1;\n };\n}\nfunction tween_default(name2, value) {\n var id2 = this._id;\n name2 += \"\";\n if (arguments.length < 2) {\n var tween = get2(this.node(), id2).tween;\n for (var i = 0, n = tween.length, t; i < n; ++i) {\n if ((t = tween[i]).name === name2) {\n return t.value;\n }\n }\n return null;\n }\n return this.each((value == null ? tweenRemove : tweenFunction)(id2, name2, value));\n}\nfunction tweenValue(transition2, name2, value) {\n var id2 = transition2._id;\n transition2.each(function() {\n var schedule = set2(this, id2);\n (schedule.value || (schedule.value = {}))[name2] = value.apply(this, arguments);\n });\n return function(node) {\n return get2(node, id2).value[name2];\n };\n}\n\n// ../../node_modules/d3-transition/src/transition/interpolate.js\nfunction interpolate_default(a2, b) {\n var c4;\n return (typeof b === \"number\" ? number_default : b instanceof color ? rgb_default : (c4 = color(b)) ? (b = c4, rgb_default) : string_default)(a2, b);\n}\n\n// ../../node_modules/d3-transition/src/transition/attr.js\nfunction attrRemove2(name2) {\n return function() {\n this.removeAttribute(name2);\n };\n}\nfunction attrRemoveNS2(fullname) {\n return function() {\n this.removeAttributeNS(fullname.space, fullname.local);\n };\n}\nfunction attrConstant2(name2, interpolate, value1) {\n var string00, string1 = value1 + \"\", interpolate0;\n return function() {\n var string0 = this.getAttribute(name2);\n return string0 === string1 ? null : string0 === string00 ? interpolate0 : interpolate0 = interpolate(string00 = string0, value1);\n };\n}\nfunction attrConstantNS2(fullname, interpolate, value1) {\n var string00, string1 = value1 + \"\", interpolate0;\n return function() {\n var string0 = this.getAttributeNS(fullname.space, fullname.local);\n return string0 === string1 ? null : string0 === string00 ? interpolate0 : interpolate0 = interpolate(string00 = string0, value1);\n };\n}\nfunction attrFunction2(name2, interpolate, value) {\n var string00, string10, interpolate0;\n return function() {\n var string0, value1 = value(this), string1;\n if (value1 == null) return void this.removeAttribute(name2);\n string0 = this.getAttribute(name2);\n string1 = value1 + \"\";\n return string0 === string1 ? null : string0 === string00 && string1 === string10 ? interpolate0 : (string10 = string1, interpolate0 = interpolate(string00 = string0, value1));\n };\n}\nfunction attrFunctionNS2(fullname, interpolate, value) {\n var string00, string10, interpolate0;\n return function() {\n var string0, value1 = value(this), string1;\n if (value1 == null) return void this.removeAttributeNS(fullname.space, fullname.local);\n string0 = this.getAttributeNS(fullname.space, fullname.local);\n string1 = value1 + \"\";\n return string0 === string1 ? null : string0 === string00 && string1 === string10 ? interpolate0 : (string10 = string1, interpolate0 = interpolate(string00 = string0, value1));\n };\n}\nfunction attr_default2(name2, value) {\n var fullname = namespace_default(name2), i = fullname === \"transform\" ? interpolateTransformSvg : interpolate_default;\n return this.attrTween(name2, typeof value === \"function\" ? (fullname.local ? attrFunctionNS2 : attrFunction2)(fullname, i, tweenValue(this, \"attr.\" + name2, value)) : value == null ? (fullname.local ? attrRemoveNS2 : attrRemove2)(fullname) : (fullname.local ? attrConstantNS2 : attrConstant2)(fullname, i, value));\n}\n\n// ../../node_modules/d3-transition/src/transition/attrTween.js\nfunction attrInterpolate(name2, i) {\n return function(t) {\n this.setAttribute(name2, i.call(this, t));\n };\n}\nfunction attrInterpolateNS(fullname, i) {\n return function(t) {\n this.setAttributeNS(fullname.space, fullname.local, i.call(this, t));\n };\n}\nfunction attrTweenNS(fullname, value) {\n var t03, i0;\n function tween() {\n var i = value.apply(this, arguments);\n if (i !== i0) t03 = (i0 = i) && attrInterpolateNS(fullname, i);\n return t03;\n }\n tween._value = value;\n return tween;\n}\nfunction attrTween(name2, value) {\n var t03, i0;\n function tween() {\n var i = value.apply(this, arguments);\n if (i !== i0) t03 = (i0 = i) && attrInterpolate(name2, i);\n return t03;\n }\n tween._value = value;\n return tween;\n}\nfunction attrTween_default(name2, value) {\n var key = \"attr.\" + name2;\n if (arguments.length < 2) return (key = this.tween(key)) && key._value;\n if (value == null) return this.tween(key, null);\n if (typeof value !== \"function\") throw new Error();\n var fullname = namespace_default(name2);\n return this.tween(key, (fullname.local ? attrTweenNS : attrTween)(fullname, value));\n}\n\n// ../../node_modules/d3-transition/src/transition/delay.js\nfunction delayFunction(id2, value) {\n return function() {\n init(this, id2).delay = +value.apply(this, arguments);\n };\n}\nfunction delayConstant(id2, value) {\n return value = +value, function() {\n init(this, id2).delay = value;\n };\n}\nfunction delay_default(value) {\n var id2 = this._id;\n return arguments.length ? this.each((typeof value === \"function\" ? delayFunction : delayConstant)(id2, value)) : get2(this.node(), id2).delay;\n}\n\n// ../../node_modules/d3-transition/src/transition/duration.js\nfunction durationFunction(id2, value) {\n return function() {\n set2(this, id2).duration = +value.apply(this, arguments);\n };\n}\nfunction durationConstant(id2, value) {\n return value = +value, function() {\n set2(this, id2).duration = value;\n };\n}\nfunction duration_default(value) {\n var id2 = this._id;\n return arguments.length ? this.each((typeof value === \"function\" ? durationFunction : durationConstant)(id2, value)) : get2(this.node(), id2).duration;\n}\n\n// ../../node_modules/d3-transition/src/transition/ease.js\nfunction easeConstant(id2, value) {\n if (typeof value !== \"function\") throw new Error();\n return function() {\n set2(this, id2).ease = value;\n };\n}\nfunction ease_default(value) {\n var id2 = this._id;\n return arguments.length ? this.each(easeConstant(id2, value)) : get2(this.node(), id2).ease;\n}\n\n// ../../node_modules/d3-transition/src/transition/easeVarying.js\nfunction easeVarying(id2, value) {\n return function() {\n var v2 = value.apply(this, arguments);\n if (typeof v2 !== \"function\") throw new Error();\n set2(this, id2).ease = v2;\n };\n}\nfunction easeVarying_default(value) {\n if (typeof value !== \"function\") throw new Error();\n return this.each(easeVarying(this._id, value));\n}\n\n// ../../node_modules/d3-transition/src/transition/filter.js\nfunction filter_default2(match) {\n if (typeof match !== \"function\") match = matcher_default(match);\n for (var groups2 = this._groups, m = groups2.length, subgroups = new Array(m), j = 0; j < m; ++j) {\n for (var group3 = groups2[j], n = group3.length, subgroup = subgroups[j] = [], node, i = 0; i < n; ++i) {\n if ((node = group3[i]) && match.call(node, node.__data__, i, group3)) {\n subgroup.push(node);\n }\n }\n }\n return new Transition(subgroups, this._parents, this._name, this._id);\n}\n\n// ../../node_modules/d3-transition/src/transition/merge.js\nfunction merge_default2(transition2) {\n if (transition2._id !== this._id) throw new Error();\n for (var groups0 = this._groups, groups1 = transition2._groups, m0 = groups0.length, m1 = groups1.length, m = Math.min(m0, m1), merges = new Array(m0), j = 0; j < m; ++j) {\n for (var group0 = groups0[j], group1 = groups1[j], n = group0.length, merge2 = merges[j] = new Array(n), node, i = 0; i < n; ++i) {\n if (node = group0[i] || group1[i]) {\n merge2[i] = node;\n }\n }\n }\n for (; j < m0; ++j) {\n merges[j] = groups0[j];\n }\n return new Transition(merges, this._parents, this._name, this._id);\n}\n\n// ../../node_modules/d3-transition/src/transition/on.js\nfunction start(name2) {\n return (name2 + \"\").trim().split(/^|\\s+/).every(function(t) {\n var i = t.indexOf(\".\");\n if (i >= 0) t = t.slice(0, i);\n return !t || t === \"start\";\n });\n}\nfunction onFunction(id2, name2, listener) {\n var on0, on1, sit = start(name2) ? init : set2;\n return function() {\n var schedule = sit(this, id2), on = schedule.on;\n if (on !== on0) (on1 = (on0 = on).copy()).on(name2, listener);\n schedule.on = on1;\n };\n}\nfunction on_default2(name2, listener) {\n var id2 = this._id;\n return arguments.length < 2 ? get2(this.node(), id2).on.on(name2) : this.each(onFunction(id2, name2, listener));\n}\n\n// ../../node_modules/d3-transition/src/transition/remove.js\nfunction removeFunction(id2) {\n return function() {\n var parent = this.parentNode;\n for (var i in this.__transition) if (+i !== id2) return;\n if (parent) parent.removeChild(this);\n };\n}\nfunction remove_default2() {\n return this.on(\"end.remove\", removeFunction(this._id));\n}\n\n// ../../node_modules/d3-transition/src/transition/select.js\nfunction select_default3(select2) {\n var name2 = this._name, id2 = this._id;\n if (typeof select2 !== \"function\") select2 = selector_default(select2);\n for (var groups2 = this._groups, m = groups2.length, subgroups = new Array(m), j = 0; j < m; ++j) {\n for (var group3 = groups2[j], n = group3.length, subgroup = subgroups[j] = new Array(n), node, subnode, i = 0; i < n; ++i) {\n if ((node = group3[i]) && (subnode = select2.call(node, node.__data__, i, group3))) {\n if (\"__data__\" in node) subnode.__data__ = node.__data__;\n subgroup[i] = subnode;\n schedule_default(subgroup[i], name2, id2, i, subgroup, get2(node, id2));\n }\n }\n }\n return new Transition(subgroups, this._parents, name2, id2);\n}\n\n// ../../node_modules/d3-transition/src/transition/selectAll.js\nfunction selectAll_default2(select2) {\n var name2 = this._name, id2 = this._id;\n if (typeof select2 !== \"function\") select2 = selectorAll_default(select2);\n for (var groups2 = this._groups, m = groups2.length, subgroups = [], parents = [], j = 0; j < m; ++j) {\n for (var group3 = groups2[j], n = group3.length, node, i = 0; i < n; ++i) {\n if (node = group3[i]) {\n for (var children2 = select2.call(node, node.__data__, i, group3), child, inherit3 = get2(node, id2), k2 = 0, l = children2.length; k2 < l; ++k2) {\n if (child = children2[k2]) {\n schedule_default(child, name2, id2, k2, children2, inherit3);\n }\n }\n subgroups.push(children2);\n parents.push(node);\n }\n }\n }\n return new Transition(subgroups, parents, name2, id2);\n}\n\n// ../../node_modules/d3-transition/src/transition/selection.js\nvar Selection3 = selection_default.prototype.constructor;\nfunction selection_default2() {\n return new Selection3(this._groups, this._parents);\n}\n\n// ../../node_modules/d3-transition/src/transition/style.js\nfunction styleNull(name2, interpolate) {\n var string00, string10, interpolate0;\n return function() {\n var string0 = styleValue(this, name2), string1 = (this.style.removeProperty(name2), styleValue(this, name2));\n return string0 === string1 ? null : string0 === string00 && string1 === string10 ? interpolate0 : interpolate0 = interpolate(string00 = string0, string10 = string1);\n };\n}\nfunction styleRemove2(name2) {\n return function() {\n this.style.removeProperty(name2);\n };\n}\nfunction styleConstant2(name2, interpolate, value1) {\n var string00, string1 = value1 + \"\", interpolate0;\n return function() {\n var string0 = styleValue(this, name2);\n return string0 === string1 ? null : string0 === string00 ? interpolate0 : interpolate0 = interpolate(string00 = string0, value1);\n };\n}\nfunction styleFunction2(name2, interpolate, value) {\n var string00, string10, interpolate0;\n return function() {\n var string0 = styleValue(this, name2), value1 = value(this), string1 = value1 + \"\";\n if (value1 == null) string1 = value1 = (this.style.removeProperty(name2), styleValue(this, name2));\n return string0 === string1 ? null : string0 === string00 && string1 === string10 ? interpolate0 : (string10 = string1, interpolate0 = interpolate(string00 = string0, value1));\n };\n}\nfunction styleMaybeRemove(id2, name2) {\n var on0, on1, listener0, key = \"style.\" + name2, event = \"end.\" + key, remove2;\n return function() {\n var schedule = set2(this, id2), on = schedule.on, listener = schedule.value[key] == null ? remove2 || (remove2 = styleRemove2(name2)) : void 0;\n if (on !== on0 || listener0 !== listener) (on1 = (on0 = on).copy()).on(event, listener0 = listener);\n schedule.on = on1;\n };\n}\nfunction style_default2(name2, value, priority) {\n var i = (name2 += \"\") === \"transform\" ? interpolateTransformCss : interpolate_default;\n return value == null ? this.styleTween(name2, styleNull(name2, i)).on(\"end.style.\" + name2, styleRemove2(name2)) : typeof value === \"function\" ? this.styleTween(name2, styleFunction2(name2, i, tweenValue(this, \"style.\" + name2, value))).each(styleMaybeRemove(this._id, name2)) : this.styleTween(name2, styleConstant2(name2, i, value), priority).on(\"end.style.\" + name2, null);\n}\n\n// ../../node_modules/d3-transition/src/transition/styleTween.js\nfunction styleInterpolate(name2, i, priority) {\n return function(t) {\n this.style.setProperty(name2, i.call(this, t), priority);\n };\n}\nfunction styleTween(name2, value, priority) {\n var t, i0;\n function tween() {\n var i = value.apply(this, arguments);\n if (i !== i0) t = (i0 = i) && styleInterpolate(name2, i, priority);\n return t;\n }\n tween._value = value;\n return tween;\n}\nfunction styleTween_default(name2, value, priority) {\n var key = \"style.\" + (name2 += \"\");\n if (arguments.length < 2) return (key = this.tween(key)) && key._value;\n if (value == null) return this.tween(key, null);\n if (typeof value !== \"function\") throw new Error();\n return this.tween(key, styleTween(name2, value, priority == null ? \"\" : priority));\n}\n\n// ../../node_modules/d3-transition/src/transition/text.js\nfunction textConstant2(value) {\n return function() {\n this.textContent = value;\n };\n}\nfunction textFunction2(value) {\n return function() {\n var value1 = value(this);\n this.textContent = value1 == null ? \"\" : value1;\n };\n}\nfunction text_default2(value) {\n return this.tween(\"text\", typeof value === \"function\" ? textFunction2(tweenValue(this, \"text\", value)) : textConstant2(value == null ? \"\" : value + \"\"));\n}\n\n// ../../node_modules/d3-transition/src/transition/textTween.js\nfunction textInterpolate(i) {\n return function(t) {\n this.textContent = i.call(this, t);\n };\n}\nfunction textTween(value) {\n var t03, i0;\n function tween() {\n var i = value.apply(this, arguments);\n if (i !== i0) t03 = (i0 = i) && textInterpolate(i);\n return t03;\n }\n tween._value = value;\n return tween;\n}\nfunction textTween_default(value) {\n var key = \"text\";\n if (arguments.length < 1) return (key = this.tween(key)) && key._value;\n if (value == null) return this.tween(key, null);\n if (typeof value !== \"function\") throw new Error();\n return this.tween(key, textTween(value));\n}\n\n// ../../node_modules/d3-transition/src/transition/transition.js\nfunction transition_default() {\n var name2 = this._name, id0 = this._id, id1 = newId();\n for (var groups2 = this._groups, m = groups2.length, j = 0; j < m; ++j) {\n for (var group3 = groups2[j], n = group3.length, node, i = 0; i < n; ++i) {\n if (node = group3[i]) {\n var inherit3 = get2(node, id0);\n schedule_default(node, name2, id1, i, group3, {\n time: inherit3.time + inherit3.delay + inherit3.duration,\n delay: 0,\n duration: inherit3.duration,\n ease: inherit3.ease\n });\n }\n }\n }\n return new Transition(groups2, this._parents, name2, id1);\n}\n\n// ../../node_modules/d3-transition/src/transition/end.js\nfunction end_default() {\n var on0, on1, that = this, id2 = that._id, size = that.size();\n return new Promise(function(resolve, reject) {\n var cancel = { value: reject }, end = { value: function() {\n if (--size === 0) resolve();\n } };\n that.each(function() {\n var schedule = set2(this, id2), on = schedule.on;\n if (on !== on0) {\n on1 = (on0 = on).copy();\n on1._.cancel.push(cancel);\n on1._.interrupt.push(cancel);\n on1._.end.push(end);\n }\n schedule.on = on1;\n });\n if (size === 0) resolve();\n });\n}\n\n// ../../node_modules/d3-transition/src/transition/index.js\nvar id = 0;\nfunction Transition(groups2, parents, name2, id2) {\n this._groups = groups2;\n this._parents = parents;\n this._name = name2;\n this._id = id2;\n}\nfunction transition(name2) {\n return selection_default().transition(name2);\n}\nfunction newId() {\n return ++id;\n}\nvar selection_prototype = selection_default.prototype;\nTransition.prototype = transition.prototype = {\n constructor: Transition,\n select: select_default3,\n selectAll: selectAll_default2,\n selectChild: selection_prototype.selectChild,\n selectChildren: selection_prototype.selectChildren,\n filter: filter_default2,\n merge: merge_default2,\n selection: selection_default2,\n transition: transition_default,\n call: selection_prototype.call,\n nodes: selection_prototype.nodes,\n node: selection_prototype.node,\n size: selection_prototype.size,\n empty: selection_prototype.empty,\n each: selection_prototype.each,\n on: on_default2,\n attr: attr_default2,\n attrTween: attrTween_default,\n style: style_default2,\n styleTween: styleTween_default,\n text: text_default2,\n textTween: textTween_default,\n remove: remove_default2,\n tween: tween_default,\n delay: delay_default,\n duration: duration_default,\n ease: ease_default,\n easeVarying: easeVarying_default,\n end: end_default,\n [Symbol.iterator]: selection_prototype[Symbol.iterator]\n};\n\n// ../../node_modules/d3-ease/src/cubic.js\nfunction cubicInOut(t) {\n return ((t *= 2) <= 1 ? t * t * t : (t -= 2) * t * t + 2) / 2;\n}\n\n// ../../node_modules/d3-transition/src/selection/transition.js\nvar defaultTiming = {\n time: null,\n // Set on use.\n delay: 0,\n duration: 250,\n ease: cubicInOut\n};\nfunction inherit(node, id2) {\n var timing;\n while (!(timing = node.__transition) || !(timing = timing[id2])) {\n if (!(node = node.parentNode)) {\n throw new Error(`transition ${id2} not found`);\n }\n }\n return timing;\n}\nfunction transition_default2(name2) {\n var id2, timing;\n if (name2 instanceof Transition) {\n id2 = name2._id, name2 = name2._name;\n } else {\n id2 = newId(), (timing = defaultTiming).time = now(), name2 = name2 == null ? null : name2 + \"\";\n }\n for (var groups2 = this._groups, m = groups2.length, j = 0; j < m; ++j) {\n for (var group3 = groups2[j], n = group3.length, node, i = 0; i < n; ++i) {\n if (node = group3[i]) {\n schedule_default(node, name2, id2, i, group3, timing || inherit(node, id2));\n }\n }\n }\n return new Transition(groups2, this._parents, name2, id2);\n}\n\n// ../../node_modules/d3-transition/src/selection/index.js\nselection_default.prototype.interrupt = interrupt_default2;\nselection_default.prototype.transition = transition_default2;\n\n// ../../node_modules/d3-brush/src/constant.js\nvar constant_default3 = (x3) => () => x3;\n\n// ../../node_modules/d3-brush/src/event.js\nfunction BrushEvent(type2, {\n sourceEvent,\n target,\n selection: selection2,\n mode: mode3,\n dispatch: dispatch2\n}) {\n Object.defineProperties(this, {\n type: { value: type2, enumerable: true, configurable: true },\n sourceEvent: { value: sourceEvent, enumerable: true, configurable: true },\n target: { value: target, enumerable: true, configurable: true },\n selection: { value: selection2, enumerable: true, configurable: true },\n mode: { value: mode3, enumerable: true, configurable: true },\n _: { value: dispatch2 }\n });\n}\n\n// ../../node_modules/d3-brush/src/noevent.js\nfunction nopropagation(event) {\n event.stopImmediatePropagation();\n}\nfunction noevent_default2(event) {\n event.preventDefault();\n event.stopImmediatePropagation();\n}\n\n// ../../node_modules/d3-brush/src/brush.js\nvar MODE_DRAG = { name: \"drag\" };\nvar MODE_SPACE = { name: \"space\" };\nvar MODE_HANDLE = { name: \"handle\" };\nvar MODE_CENTER = { name: \"center\" };\nvar { abs, max: max3, min: min3 } = Math;\nfunction number1(e) {\n return [+e[0], +e[1]];\n}\nfunction number22(e) {\n return [number1(e[0]), number1(e[1])];\n}\nvar X = {\n name: \"x\",\n handles: [\"w\", \"e\"].map(type),\n input: function(x3, e) {\n return x3 == null ? null : [[+x3[0], e[0][1]], [+x3[1], e[1][1]]];\n },\n output: function(xy) {\n return xy && [xy[0][0], xy[1][0]];\n }\n};\nvar Y = {\n name: \"y\",\n handles: [\"n\", \"s\"].map(type),\n input: function(y3, e) {\n return y3 == null ? null : [[e[0][0], +y3[0]], [e[1][0], +y3[1]]];\n },\n output: function(xy) {\n return xy && [xy[0][1], xy[1][1]];\n }\n};\nvar XY = {\n name: \"xy\",\n handles: [\"n\", \"w\", \"e\", \"s\", \"nw\", \"ne\", \"sw\", \"se\"].map(type),\n input: function(xy) {\n return xy == null ? null : number22(xy);\n },\n output: function(xy) {\n return xy;\n }\n};\nvar cursors = {\n overlay: \"crosshair\",\n selection: \"move\",\n n: \"ns-resize\",\n e: \"ew-resize\",\n s: \"ns-resize\",\n w: \"ew-resize\",\n nw: \"nwse-resize\",\n ne: \"nesw-resize\",\n se: \"nwse-resize\",\n sw: \"nesw-resize\"\n};\nvar flipX = {\n e: \"w\",\n w: \"e\",\n nw: \"ne\",\n ne: \"nw\",\n se: \"sw\",\n sw: \"se\"\n};\nvar flipY = {\n n: \"s\",\n s: \"n\",\n nw: \"sw\",\n ne: \"se\",\n se: \"ne\",\n sw: \"nw\"\n};\nvar signsX = {\n overlay: 1,\n selection: 1,\n n: null,\n e: 1,\n s: null,\n w: -1,\n nw: -1,\n ne: 1,\n se: 1,\n sw: -1\n};\nvar signsY = {\n overlay: 1,\n selection: 1,\n n: -1,\n e: null,\n s: 1,\n w: null,\n nw: -1,\n ne: -1,\n se: 1,\n sw: 1\n};\nfunction type(t) {\n return { type: t };\n}\nfunction defaultFilter(event) {\n return !event.ctrlKey && !event.button;\n}\nfunction defaultExtent() {\n var svg = this.ownerSVGElement || this;\n if (svg.hasAttribute(\"viewBox\")) {\n svg = svg.viewBox.baseVal;\n return [[svg.x, svg.y], [svg.x + svg.width, svg.y + svg.height]];\n }\n return [[0, 0], [svg.width.baseVal.value, svg.height.baseVal.value]];\n}\nfunction defaultTouchable() {\n return navigator.maxTouchPoints || \"ontouchstart\" in this;\n}\nfunction local(node) {\n while (!node.__brush) if (!(node = node.parentNode)) return;\n return node.__brush;\n}\nfunction empty3(extent4) {\n return extent4[0][0] === extent4[1][0] || extent4[0][1] === extent4[1][1];\n}\nfunction brushX() {\n return brush(X);\n}\nfunction brushY() {\n return brush(Y);\n}\nfunction brush_default() {\n return brush(XY);\n}\nfunction brush(dim) {\n var extent4 = defaultExtent, filter3 = defaultFilter, touchable = defaultTouchable, keys = true, listeners = dispatch_default(\"start\", \"brush\", \"end\"), handleSize = 6, touchending;\n function brush3(group3) {\n var overlay = group3.property(\"__brush\", initialize).selectAll(\".overlay\").data([type(\"overlay\")]);\n overlay.enter().append(\"rect\").attr(\"class\", \"overlay\").attr(\"pointer-events\", \"all\").attr(\"cursor\", cursors.overlay).merge(overlay).each(function() {\n var extent5 = local(this).extent;\n select_default2(this).attr(\"x\", extent5[0][0]).attr(\"y\", extent5[0][1]).attr(\"width\", extent5[1][0] - extent5[0][0]).attr(\"height\", extent5[1][1] - extent5[0][1]);\n });\n group3.selectAll(\".selection\").data([type(\"selection\")]).enter().append(\"rect\").attr(\"class\", \"selection\").attr(\"cursor\", cursors.selection).attr(\"fill\", \"#777\").attr(\"fill-opacity\", 0.3).attr(\"stroke\", \"#fff\").attr(\"shape-rendering\", \"crispEdges\");\n var handle = group3.selectAll(\".handle\").data(dim.handles, function(d) {\n return d.type;\n });\n handle.exit().remove();\n handle.enter().append(\"rect\").attr(\"class\", function(d) {\n return \"handle handle--\" + d.type;\n }).attr(\"cursor\", function(d) {\n return cursors[d.type];\n });\n group3.each(redraw).attr(\"fill\", \"none\").attr(\"pointer-events\", \"all\").on(\"mousedown.brush\", started).filter(touchable).on(\"touchstart.brush\", started).on(\"touchmove.brush\", touchmoved).on(\"touchend.brush touchcancel.brush\", touchended).style(\"touch-action\", \"none\").style(\"-webkit-tap-highlight-color\", \"rgba(0,0,0,0)\");\n }\n brush3.move = function(group3, selection2, event) {\n if (group3.tween) {\n group3.on(\"start.brush\", function(event2) {\n emitter(this, arguments).beforestart().start(event2);\n }).on(\"interrupt.brush end.brush\", function(event2) {\n emitter(this, arguments).end(event2);\n }).tween(\"brush\", function() {\n var that = this, state = that.__brush, emit = emitter(that, arguments), selection0 = state.selection, selection1 = dim.input(typeof selection2 === \"function\" ? selection2.apply(this, arguments) : selection2, state.extent), i = value_default(selection0, selection1);\n function tween(t) {\n state.selection = t === 1 && selection1 === null ? null : i(t);\n redraw.call(that);\n emit.brush();\n }\n return selection0 !== null && selection1 !== null ? tween : tween(1);\n });\n } else {\n group3.each(function() {\n var that = this, args = arguments, state = that.__brush, selection1 = dim.input(typeof selection2 === \"function\" ? selection2.apply(that, args) : selection2, state.extent), emit = emitter(that, args).beforestart();\n interrupt_default(that);\n state.selection = selection1 === null ? null : selection1;\n redraw.call(that);\n emit.start(event).brush(event).end(event);\n });\n }\n };\n brush3.clear = function(group3, event) {\n brush3.move(group3, null, event);\n };\n function redraw() {\n var group3 = select_default2(this), selection2 = local(this).selection;\n if (selection2) {\n group3.selectAll(\".selection\").style(\"display\", null).attr(\"x\", selection2[0][0]).attr(\"y\", selection2[0][1]).attr(\"width\", selection2[1][0] - selection2[0][0]).attr(\"height\", selection2[1][1] - selection2[0][1]);\n group3.selectAll(\".handle\").style(\"display\", null).attr(\"x\", function(d) {\n return d.type[d.type.length - 1] === \"e\" ? selection2[1][0] - handleSize / 2 : selection2[0][0] - handleSize / 2;\n }).attr(\"y\", function(d) {\n return d.type[0] === \"s\" ? selection2[1][1] - handleSize / 2 : selection2[0][1] - handleSize / 2;\n }).attr(\"width\", function(d) {\n return d.type === \"n\" || d.type === \"s\" ? selection2[1][0] - selection2[0][0] + handleSize : handleSize;\n }).attr(\"height\", function(d) {\n return d.type === \"e\" || d.type === \"w\" ? selection2[1][1] - selection2[0][1] + handleSize : handleSize;\n });\n } else {\n group3.selectAll(\".selection,.handle\").style(\"display\", \"none\").attr(\"x\", null).attr(\"y\", null).attr(\"width\", null).attr(\"height\", null);\n }\n }\n function emitter(that, args, clean) {\n var emit = that.__brush.emitter;\n return emit && (!clean || !emit.clean) ? emit : new Emitter(that, args, clean);\n }\n function Emitter(that, args, clean) {\n this.that = that;\n this.args = args;\n this.state = that.__brush;\n this.active = 0;\n this.clean = clean;\n }\n Emitter.prototype = {\n beforestart: function() {\n if (++this.active === 1) this.state.emitter = this, this.starting = true;\n return this;\n },\n start: function(event, mode3) {\n if (this.starting) this.starting = false, this.emit(\"start\", event, mode3);\n else this.emit(\"brush\", event);\n return this;\n },\n brush: function(event, mode3) {\n this.emit(\"brush\", event, mode3);\n return this;\n },\n end: function(event, mode3) {\n if (--this.active === 0) delete this.state.emitter, this.emit(\"end\", event, mode3);\n return this;\n },\n emit: function(type2, event, mode3) {\n var d = select_default2(this.that).datum();\n listeners.call(\n type2,\n this.that,\n new BrushEvent(type2, {\n sourceEvent: event,\n target: brush3,\n selection: dim.output(this.state.selection),\n mode: mode3,\n dispatch: listeners\n }),\n d\n );\n }\n };\n function started(event) {\n if (touchending && !event.touches) return;\n if (!filter3.apply(this, arguments)) return;\n var that = this, type2 = event.target.__data__.type, mode3 = (keys && event.metaKey ? type2 = \"overlay\" : type2) === \"selection\" ? MODE_DRAG : keys && event.altKey ? MODE_CENTER : MODE_HANDLE, signX = dim === Y ? null : signsX[type2], signY = dim === X ? null : signsY[type2], state = local(that), extent5 = state.extent, selection2 = state.selection, W = extent5[0][0], w0, w1, N = extent5[0][1], n0, n1, E2 = extent5[1][0], e0, e1, S = extent5[1][1], s0, s1, dx = 0, dy = 0, moving, shifting = signX && signY && keys && event.shiftKey, lockX, lockY, points2 = Array.from(event.touches || [event], (t) => {\n const i = t.identifier;\n t = pointer_default(t, that);\n t.point0 = t.slice();\n t.identifier = i;\n return t;\n });\n interrupt_default(that);\n var emit = emitter(that, arguments, true).beforestart();\n if (type2 === \"overlay\") {\n if (selection2) moving = true;\n const pts = [points2[0], points2[1] || points2[0]];\n state.selection = selection2 = [[\n w0 = dim === Y ? W : min3(pts[0][0], pts[1][0]),\n n0 = dim === X ? N : min3(pts[0][1], pts[1][1])\n ], [\n e0 = dim === Y ? E2 : max3(pts[0][0], pts[1][0]),\n s0 = dim === X ? S : max3(pts[0][1], pts[1][1])\n ]];\n if (points2.length > 1) move(event);\n } else {\n w0 = selection2[0][0];\n n0 = selection2[0][1];\n e0 = selection2[1][0];\n s0 = selection2[1][1];\n }\n w1 = w0;\n n1 = n0;\n e1 = e0;\n s1 = s0;\n var group3 = select_default2(that).attr(\"pointer-events\", \"none\");\n var overlay = group3.selectAll(\".overlay\").attr(\"cursor\", cursors[type2]);\n if (event.touches) {\n emit.moved = moved;\n emit.ended = ended;\n } else {\n var view = select_default2(event.view).on(\"mousemove.brush\", moved, true).on(\"mouseup.brush\", ended, true);\n if (keys) view.on(\"keydown.brush\", keydowned, true).on(\"keyup.brush\", keyupped, true);\n nodrag_default(event.view);\n }\n redraw.call(that);\n emit.start(event, mode3.name);\n function moved(event2) {\n for (const p of event2.changedTouches || [event2]) {\n for (const d of points2)\n if (d.identifier === p.identifier) d.cur = pointer_default(p, that);\n }\n if (shifting && !lockX && !lockY && points2.length === 1) {\n const point6 = points2[0];\n if (abs(point6.cur[0] - point6[0]) > abs(point6.cur[1] - point6[1]))\n lockY = true;\n else\n lockX = true;\n }\n for (const point6 of points2)\n if (point6.cur) point6[0] = point6.cur[0], point6[1] = point6.cur[1];\n moving = true;\n noevent_default2(event2);\n move(event2);\n }\n function move(event2) {\n const point6 = points2[0], point0 = point6.point0;\n var t;\n dx = point6[0] - point0[0];\n dy = point6[1] - point0[1];\n switch (mode3) {\n case MODE_SPACE:\n case MODE_DRAG: {\n if (signX) dx = max3(W - w0, min3(E2 - e0, dx)), w1 = w0 + dx, e1 = e0 + dx;\n if (signY) dy = max3(N - n0, min3(S - s0, dy)), n1 = n0 + dy, s1 = s0 + dy;\n break;\n }\n case MODE_HANDLE: {\n if (points2[1]) {\n if (signX) w1 = max3(W, min3(E2, points2[0][0])), e1 = max3(W, min3(E2, points2[1][0])), signX = 1;\n if (signY) n1 = max3(N, min3(S, points2[0][1])), s1 = max3(N, min3(S, points2[1][1])), signY = 1;\n } else {\n if (signX < 0) dx = max3(W - w0, min3(E2 - w0, dx)), w1 = w0 + dx, e1 = e0;\n else if (signX > 0) dx = max3(W - e0, min3(E2 - e0, dx)), w1 = w0, e1 = e0 + dx;\n if (signY < 0) dy = max3(N - n0, min3(S - n0, dy)), n1 = n0 + dy, s1 = s0;\n else if (signY > 0) dy = max3(N - s0, min3(S - s0, dy)), n1 = n0, s1 = s0 + dy;\n }\n break;\n }\n case MODE_CENTER: {\n if (signX) w1 = max3(W, min3(E2, w0 - dx * signX)), e1 = max3(W, min3(E2, e0 + dx * signX));\n if (signY) n1 = max3(N, min3(S, n0 - dy * signY)), s1 = max3(N, min3(S, s0 + dy * signY));\n break;\n }\n }\n if (e1 < w1) {\n signX *= -1;\n t = w0, w0 = e0, e0 = t;\n t = w1, w1 = e1, e1 = t;\n if (type2 in flipX) overlay.attr(\"cursor\", cursors[type2 = flipX[type2]]);\n }\n if (s1 < n1) {\n signY *= -1;\n t = n0, n0 = s0, s0 = t;\n t = n1, n1 = s1, s1 = t;\n if (type2 in flipY) overlay.attr(\"cursor\", cursors[type2 = flipY[type2]]);\n }\n if (state.selection) selection2 = state.selection;\n if (lockX) w1 = selection2[0][0], e1 = selection2[1][0];\n if (lockY) n1 = selection2[0][1], s1 = selection2[1][1];\n if (selection2[0][0] !== w1 || selection2[0][1] !== n1 || selection2[1][0] !== e1 || selection2[1][1] !== s1) {\n state.selection = [[w1, n1], [e1, s1]];\n redraw.call(that);\n emit.brush(event2, mode3.name);\n }\n }\n function ended(event2) {\n nopropagation(event2);\n if (event2.touches) {\n if (event2.touches.length) return;\n if (touchending) clearTimeout(touchending);\n touchending = setTimeout(function() {\n touchending = null;\n }, 500);\n } else {\n yesdrag(event2.view, moving);\n view.on(\"keydown.brush keyup.brush mousemove.brush mouseup.brush\", null);\n }\n group3.attr(\"pointer-events\", \"all\");\n overlay.attr(\"cursor\", cursors.overlay);\n if (state.selection) selection2 = state.selection;\n if (empty3(selection2)) state.selection = null, redraw.call(that);\n emit.end(event2, mode3.name);\n }\n function keydowned(event2) {\n switch (event2.keyCode) {\n case 16: {\n shifting = signX && signY;\n break;\n }\n case 18: {\n if (mode3 === MODE_HANDLE) {\n if (signX) e0 = e1 - dx * signX, w0 = w1 + dx * signX;\n if (signY) s0 = s1 - dy * signY, n0 = n1 + dy * signY;\n mode3 = MODE_CENTER;\n move(event2);\n }\n break;\n }\n case 32: {\n if (mode3 === MODE_HANDLE || mode3 === MODE_CENTER) {\n if (signX < 0) e0 = e1 - dx;\n else if (signX > 0) w0 = w1 - dx;\n if (signY < 0) s0 = s1 - dy;\n else if (signY > 0) n0 = n1 - dy;\n mode3 = MODE_SPACE;\n overlay.attr(\"cursor\", cursors.selection);\n move(event2);\n }\n break;\n }\n default:\n return;\n }\n noevent_default2(event2);\n }\n function keyupped(event2) {\n switch (event2.keyCode) {\n case 16: {\n if (shifting) {\n lockX = lockY = shifting = false;\n move(event2);\n }\n break;\n }\n case 18: {\n if (mode3 === MODE_CENTER) {\n if (signX < 0) e0 = e1;\n else if (signX > 0) w0 = w1;\n if (signY < 0) s0 = s1;\n else if (signY > 0) n0 = n1;\n mode3 = MODE_HANDLE;\n move(event2);\n }\n break;\n }\n case 32: {\n if (mode3 === MODE_SPACE) {\n if (event2.altKey) {\n if (signX) e0 = e1 - dx * signX, w0 = w1 + dx * signX;\n if (signY) s0 = s1 - dy * signY, n0 = n1 + dy * signY;\n mode3 = MODE_CENTER;\n } else {\n if (signX < 0) e0 = e1;\n else if (signX > 0) w0 = w1;\n if (signY < 0) s0 = s1;\n else if (signY > 0) n0 = n1;\n mode3 = MODE_HANDLE;\n }\n overlay.attr(\"cursor\", cursors[type2]);\n move(event2);\n }\n break;\n }\n default:\n return;\n }\n noevent_default2(event2);\n }\n }\n function touchmoved(event) {\n emitter(this, arguments).moved(event);\n }\n function touchended(event) {\n emitter(this, arguments).ended(event);\n }\n function initialize() {\n var state = this.__brush || { selection: null };\n state.extent = number22(extent4.apply(this, arguments));\n state.dim = dim;\n return state;\n }\n brush3.extent = function(_) {\n return arguments.length ? (extent4 = typeof _ === \"function\" ? _ : constant_default3(number22(_)), brush3) : extent4;\n };\n brush3.filter = function(_) {\n return arguments.length ? (filter3 = typeof _ === \"function\" ? _ : constant_default3(!!_), brush3) : filter3;\n };\n brush3.touchable = function(_) {\n return arguments.length ? (touchable = typeof _ === \"function\" ? _ : constant_default3(!!_), brush3) : touchable;\n };\n brush3.handleSize = function(_) {\n return arguments.length ? (handleSize = +_, brush3) : handleSize;\n };\n brush3.keyModifiers = function(_) {\n return arguments.length ? (keys = !!_, brush3) : keys;\n };\n brush3.on = function() {\n var value = listeners.on.apply(listeners, arguments);\n return value === listeners ? brush3 : value;\n };\n return brush3;\n}\n\n// ../../node_modules/d3-path/src/path.js\nvar pi = Math.PI;\nvar tau = 2 * pi;\nvar epsilon3 = 1e-6;\nvar tauEpsilon = tau - epsilon3;\nfunction append(strings) {\n this._ += strings[0];\n for (let i = 1, n = strings.length; i < n; ++i) {\n this._ += arguments[i] + strings[i];\n }\n}\nfunction appendRound(digits) {\n let d = Math.floor(digits);\n if (!(d >= 0)) throw new Error(`invalid digits: ${digits}`);\n if (d > 15) return append;\n const k2 = 10 ** d;\n return function(strings) {\n this._ += strings[0];\n for (let i = 1, n = strings.length; i < n; ++i) {\n this._ += Math.round(arguments[i] * k2) / k2 + strings[i];\n }\n };\n}\nvar Path = class {\n constructor(digits) {\n this._x0 = this._y0 = // start of current subpath\n this._x1 = this._y1 = null;\n this._ = \"\";\n this._append = digits == null ? append : appendRound(digits);\n }\n moveTo(x3, y3) {\n this._append`M${this._x0 = this._x1 = +x3},${this._y0 = this._y1 = +y3}`;\n }\n closePath() {\n if (this._x1 !== null) {\n this._x1 = this._x0, this._y1 = this._y0;\n this._append`Z`;\n }\n }\n lineTo(x3, y3) {\n this._append`L${this._x1 = +x3},${this._y1 = +y3}`;\n }\n quadraticCurveTo(x12, y12, x3, y3) {\n this._append`Q${+x12},${+y12},${this._x1 = +x3},${this._y1 = +y3}`;\n }\n bezierCurveTo(x12, y12, x22, y22, x3, y3) {\n this._append`C${+x12},${+y12},${+x22},${+y22},${this._x1 = +x3},${this._y1 = +y3}`;\n }\n arcTo(x12, y12, x22, y22, r) {\n x12 = +x12, y12 = +y12, x22 = +x22, y22 = +y22, r = +r;\n if (r < 0) throw new Error(`negative radius: ${r}`);\n let x06 = this._x1, y06 = this._y1, x21 = x22 - x12, y21 = y22 - y12, x01 = x06 - x12, y01 = y06 - y12, l01_2 = x01 * x01 + y01 * y01;\n if (this._x1 === null) {\n this._append`M${this._x1 = x12},${this._y1 = y12}`;\n } else if (!(l01_2 > epsilon3)) ;\n else if (!(Math.abs(y01 * x21 - y21 * x01) > epsilon3) || !r) {\n this._append`L${this._x1 = x12},${this._y1 = y12}`;\n } else {\n let x20 = x22 - x06, y20 = y22 - y06, l21_2 = x21 * x21 + y21 * y21, l20_2 = x20 * x20 + y20 * y20, l21 = Math.sqrt(l21_2), l01 = Math.sqrt(l01_2), l = r * Math.tan((pi - Math.acos((l21_2 + l01_2 - l20_2) / (2 * l21 * l01))) / 2), t01 = l / l01, t21 = l / l21;\n if (Math.abs(t01 - 1) > epsilon3) {\n this._append`L${x12 + t01 * x01},${y12 + t01 * y01}`;\n }\n this._append`A${r},${r},0,0,${+(y01 * x20 > x01 * y20)},${this._x1 = x12 + t21 * x21},${this._y1 = y12 + t21 * y21}`;\n }\n }\n arc(x3, y3, r, a0, a1, ccw) {\n x3 = +x3, y3 = +y3, r = +r, ccw = !!ccw;\n if (r < 0) throw new Error(`negative radius: ${r}`);\n let dx = r * Math.cos(a0), dy = r * Math.sin(a0), x06 = x3 + dx, y06 = y3 + dy, cw = 1 ^ ccw, da2 = ccw ? a0 - a1 : a1 - a0;\n if (this._x1 === null) {\n this._append`M${x06},${y06}`;\n } else if (Math.abs(this._x1 - x06) > epsilon3 || Math.abs(this._y1 - y06) > epsilon3) {\n this._append`L${x06},${y06}`;\n }\n if (!r) return;\n if (da2 < 0) da2 = da2 % tau + tau;\n if (da2 > tauEpsilon) {\n this._append`A${r},${r},0,1,${cw},${x3 - dx},${y3 - dy}A${r},${r},0,1,${cw},${this._x1 = x06},${this._y1 = y06}`;\n } else if (da2 > epsilon3) {\n this._append`A${r},${r},0,${+(da2 >= pi)},${cw},${this._x1 = x3 + r * Math.cos(a1)},${this._y1 = y3 + r * Math.sin(a1)}`;\n }\n }\n rect(x3, y3, w, h) {\n this._append`M${this._x0 = this._x1 = +x3},${this._y0 = this._y1 = +y3}h${w = +w}v${+h}h${-w}Z`;\n }\n toString() {\n return this._;\n }\n};\nfunction path() {\n return new Path();\n}\npath.prototype = Path.prototype;\nfunction pathRound(digits = 3) {\n return new Path(+digits);\n}\n\n// ../../node_modules/d3-contour/src/array.js\nvar array2 = Array.prototype;\nvar slice = array2.slice;\n\n// ../../node_modules/d3-contour/src/ascending.js\nfunction ascending_default(a2, b) {\n return a2 - b;\n}\n\n// ../../node_modules/d3-contour/src/area.js\nfunction area_default(ring) {\n var i = 0, n = ring.length, area3 = ring[n - 1][1] * ring[0][0] - ring[n - 1][0] * ring[0][1];\n while (++i < n) area3 += ring[i - 1][1] * ring[i][0] - ring[i - 1][0] * ring[i][1];\n return area3;\n}\n\n// ../../node_modules/d3-contour/src/constant.js\nvar constant_default4 = (x3) => () => x3;\n\n// ../../node_modules/d3-contour/src/contains.js\nfunction contains_default(ring, hole) {\n var i = -1, n = hole.length, c4;\n while (++i < n) if (c4 = ringContains(ring, hole[i])) return c4;\n return 0;\n}\nfunction ringContains(ring, point6) {\n var x3 = point6[0], y3 = point6[1], contains2 = -1;\n for (var i = 0, n = ring.length, j = n - 1; i < n; j = i++) {\n var pi5 = ring[i], xi = pi5[0], yi = pi5[1], pj = ring[j], xj = pj[0], yj = pj[1];\n if (segmentContains(pi5, pj, point6)) return 0;\n if (yi > y3 !== yj > y3 && x3 < (xj - xi) * (y3 - yi) / (yj - yi) + xi) contains2 = -contains2;\n }\n return contains2;\n}\nfunction segmentContains(a2, b, c4) {\n var i;\n return collinear(a2, b, c4) && within(a2[i = +(a2[0] === b[0])], c4[i], b[i]);\n}\nfunction collinear(a2, b, c4) {\n return (b[0] - a2[0]) * (c4[1] - a2[1]) === (c4[0] - a2[0]) * (b[1] - a2[1]);\n}\nfunction within(p, q, r) {\n return p <= q && q <= r || r <= q && q <= p;\n}\n\n// ../../node_modules/d3-contour/src/noop.js\nfunction noop_default() {\n}\n\n// ../../node_modules/d3-contour/src/contours.js\nvar cases = [\n [],\n [[[1, 1.5], [0.5, 1]]],\n [[[1.5, 1], [1, 1.5]]],\n [[[1.5, 1], [0.5, 1]]],\n [[[1, 0.5], [1.5, 1]]],\n [[[1, 1.5], [0.5, 1]], [[1, 0.5], [1.5, 1]]],\n [[[1, 0.5], [1, 1.5]]],\n [[[1, 0.5], [0.5, 1]]],\n [[[0.5, 1], [1, 0.5]]],\n [[[1, 1.5], [1, 0.5]]],\n [[[0.5, 1], [1, 0.5]], [[1.5, 1], [1, 1.5]]],\n [[[1.5, 1], [1, 0.5]]],\n [[[0.5, 1], [1.5, 1]]],\n [[[1, 1.5], [1.5, 1]]],\n [[[0.5, 1], [1, 1.5]]],\n []\n];\nfunction contours_default() {\n var dx = 1, dy = 1, threshold2 = thresholdSturges, smooth = smoothLinear;\n function contours(values2) {\n var tz = threshold2(values2);\n if (!Array.isArray(tz)) {\n const e = extent(values2, finite);\n tz = ticks(...nice(e[0], e[1], tz), tz);\n while (tz[tz.length - 1] >= e[1]) tz.pop();\n while (tz[1] < e[0]) tz.shift();\n } else {\n tz = tz.slice().sort(ascending_default);\n }\n return tz.map((value) => contour3(values2, value));\n }\n function contour3(values2, value) {\n const v2 = value == null ? NaN : +value;\n if (isNaN(v2)) throw new Error(`invalid value: ${value}`);\n var polygons = [], holes = [];\n isorings(values2, v2, function(ring) {\n smooth(ring, values2, v2);\n if (area_default(ring) > 0) polygons.push([ring]);\n else holes.push(ring);\n });\n holes.forEach(function(hole) {\n for (var i = 0, n = polygons.length, polygon; i < n; ++i) {\n if (contains_default((polygon = polygons[i])[0], hole) !== -1) {\n polygon.push(hole);\n return;\n }\n }\n });\n return {\n type: \"MultiPolygon\",\n value,\n coordinates: polygons\n };\n }\n function isorings(values2, value, callback) {\n var fragmentByStart = new Array(), fragmentByEnd = new Array(), x3, y3, t03, t13, t22, t32;\n x3 = y3 = -1;\n t13 = above(values2[0], value);\n cases[t13 << 1].forEach(stitch);\n while (++x3 < dx - 1) {\n t03 = t13, t13 = above(values2[x3 + 1], value);\n cases[t03 | t13 << 1].forEach(stitch);\n }\n cases[t13 << 0].forEach(stitch);\n while (++y3 < dy - 1) {\n x3 = -1;\n t13 = above(values2[y3 * dx + dx], value);\n t22 = above(values2[y3 * dx], value);\n cases[t13 << 1 | t22 << 2].forEach(stitch);\n while (++x3 < dx - 1) {\n t03 = t13, t13 = above(values2[y3 * dx + dx + x3 + 1], value);\n t32 = t22, t22 = above(values2[y3 * dx + x3 + 1], value);\n cases[t03 | t13 << 1 | t22 << 2 | t32 << 3].forEach(stitch);\n }\n cases[t13 | t22 << 3].forEach(stitch);\n }\n x3 = -1;\n t22 = values2[y3 * dx] >= value;\n cases[t22 << 2].forEach(stitch);\n while (++x3 < dx - 1) {\n t32 = t22, t22 = above(values2[y3 * dx + x3 + 1], value);\n cases[t22 << 2 | t32 << 3].forEach(stitch);\n }\n cases[t22 << 3].forEach(stitch);\n function stitch(line3) {\n var start2 = [line3[0][0] + x3, line3[0][1] + y3], end = [line3[1][0] + x3, line3[1][1] + y3], startIndex = index2(start2), endIndex = index2(end), f, g;\n if (f = fragmentByEnd[startIndex]) {\n if (g = fragmentByStart[endIndex]) {\n delete fragmentByEnd[f.end];\n delete fragmentByStart[g.start];\n if (f === g) {\n f.ring.push(end);\n callback(f.ring);\n } else {\n fragmentByStart[f.start] = fragmentByEnd[g.end] = { start: f.start, end: g.end, ring: f.ring.concat(g.ring) };\n }\n } else {\n delete fragmentByEnd[f.end];\n f.ring.push(end);\n fragmentByEnd[f.end = endIndex] = f;\n }\n } else if (f = fragmentByStart[endIndex]) {\n if (g = fragmentByEnd[startIndex]) {\n delete fragmentByStart[f.start];\n delete fragmentByEnd[g.end];\n if (f === g) {\n f.ring.push(end);\n callback(f.ring);\n } else {\n fragmentByStart[g.start] = fragmentByEnd[f.end] = { start: g.start, end: f.end, ring: g.ring.concat(f.ring) };\n }\n } else {\n delete fragmentByStart[f.start];\n f.ring.unshift(start2);\n fragmentByStart[f.start = startIndex] = f;\n }\n } else {\n fragmentByStart[startIndex] = fragmentByEnd[endIndex] = { start: startIndex, end: endIndex, ring: [start2, end] };\n }\n }\n }\n function index2(point6) {\n return point6[0] * 2 + point6[1] * (dx + 1) * 4;\n }\n function smoothLinear(ring, values2, value) {\n ring.forEach(function(point6) {\n var x3 = point6[0], y3 = point6[1], xt = x3 | 0, yt = y3 | 0, v1 = valid(values2[yt * dx + xt]);\n if (x3 > 0 && x3 < dx && xt === x3) {\n point6[0] = smooth1(x3, valid(values2[yt * dx + xt - 1]), v1, value);\n }\n if (y3 > 0 && y3 < dy && yt === y3) {\n point6[1] = smooth1(y3, valid(values2[(yt - 1) * dx + xt]), v1, value);\n }\n });\n }\n contours.contour = contour3;\n contours.size = function(_) {\n if (!arguments.length) return [dx, dy];\n var _0 = Math.floor(_[0]), _1 = Math.floor(_[1]);\n if (!(_0 >= 0 && _1 >= 0)) throw new Error(\"invalid size\");\n return dx = _0, dy = _1, contours;\n };\n contours.thresholds = function(_) {\n return arguments.length ? (threshold2 = typeof _ === \"function\" ? _ : Array.isArray(_) ? constant_default4(slice.call(_)) : constant_default4(_), contours) : threshold2;\n };\n contours.smooth = function(_) {\n return arguments.length ? (smooth = _ ? smoothLinear : noop_default, contours) : smooth === smoothLinear;\n };\n return contours;\n}\nfunction finite(x3) {\n return isFinite(x3) ? x3 : NaN;\n}\nfunction above(x3, value) {\n return x3 == null ? false : +x3 >= value;\n}\nfunction valid(v2) {\n return v2 == null || isNaN(v2 = +v2) ? -Infinity : v2;\n}\nfunction smooth1(x3, v0, v1, value) {\n const a2 = value - v0;\n const b = v1 - v0;\n const d = isFinite(a2) || isFinite(b) ? a2 / b : Math.sign(a2) / Math.sign(b);\n return isNaN(d) ? x3 : x3 + d - 0.5;\n}\n\n// ../../node_modules/d3-contour/src/density.js\nfunction defaultX(d) {\n return d[0];\n}\nfunction defaultY(d) {\n return d[1];\n}\nfunction defaultWeight() {\n return 1;\n}\nfunction density_default() {\n var x3 = defaultX, y3 = defaultY, weight = defaultWeight, dx = 960, dy = 500, r = 20, k2 = 2, o = r * 3, n = dx + o * 2 >> k2, m = dy + o * 2 >> k2, threshold2 = constant_default4(20);\n function grid2(data) {\n var values2 = new Float32Array(n * m), pow2k = Math.pow(2, -k2), i = -1;\n for (const d of data) {\n var xi = (x3(d, ++i, data) + o) * pow2k, yi = (y3(d, i, data) + o) * pow2k, wi = +weight(d, i, data);\n if (wi && xi >= 0 && xi < n && yi >= 0 && yi < m) {\n var x06 = Math.floor(xi), y06 = Math.floor(yi), xt = xi - x06 - 0.5, yt = yi - y06 - 0.5;\n values2[x06 + y06 * n] += (1 - xt) * (1 - yt) * wi;\n values2[x06 + 1 + y06 * n] += xt * (1 - yt) * wi;\n values2[x06 + 1 + (y06 + 1) * n] += xt * yt * wi;\n values2[x06 + (y06 + 1) * n] += (1 - xt) * yt * wi;\n }\n }\n blur2({ data: values2, width: n, height: m }, r * pow2k);\n return values2;\n }\n function density3(data) {\n var values2 = grid2(data), tz = threshold2(values2), pow4k = Math.pow(2, 2 * k2);\n if (!Array.isArray(tz)) {\n tz = ticks(Number.MIN_VALUE, max2(values2) / pow4k, tz);\n }\n return contours_default().size([n, m]).thresholds(tz.map((d) => d * pow4k))(values2).map((c4, i) => (c4.value = +tz[i], transform3(c4)));\n }\n density3.contours = function(data) {\n var values2 = grid2(data), contours = contours_default().size([n, m]), pow4k = Math.pow(2, 2 * k2), contour3 = (value) => {\n value = +value;\n var c4 = transform3(contours.contour(values2, value * pow4k));\n c4.value = value;\n return c4;\n };\n Object.defineProperty(contour3, \"max\", { get: () => max2(values2) / pow4k });\n return contour3;\n };\n function transform3(geometry) {\n geometry.coordinates.forEach(transformPolygon);\n return geometry;\n }\n function transformPolygon(coordinates) {\n coordinates.forEach(transformRing);\n }\n function transformRing(coordinates) {\n coordinates.forEach(transformPoint);\n }\n function transformPoint(coordinates) {\n coordinates[0] = coordinates[0] * Math.pow(2, k2) - o;\n coordinates[1] = coordinates[1] * Math.pow(2, k2) - o;\n }\n function resize() {\n o = r * 3;\n n = dx + o * 2 >> k2;\n m = dy + o * 2 >> k2;\n return density3;\n }\n density3.x = function(_) {\n return arguments.length ? (x3 = typeof _ === \"function\" ? _ : constant_default4(+_), density3) : x3;\n };\n density3.y = function(_) {\n return arguments.length ? (y3 = typeof _ === \"function\" ? _ : constant_default4(+_), density3) : y3;\n };\n density3.weight = function(_) {\n return arguments.length ? (weight = typeof _ === \"function\" ? _ : constant_default4(+_), density3) : weight;\n };\n density3.size = function(_) {\n if (!arguments.length) return [dx, dy];\n var _0 = +_[0], _1 = +_[1];\n if (!(_0 >= 0 && _1 >= 0)) throw new Error(\"invalid size\");\n return dx = _0, dy = _1, resize();\n };\n density3.cellSize = function(_) {\n if (!arguments.length) return 1 << k2;\n if (!((_ = +_) >= 1)) throw new Error(\"invalid cell size\");\n return k2 = Math.floor(Math.log(_) / Math.LN2), resize();\n };\n density3.thresholds = function(_) {\n return arguments.length ? (threshold2 = typeof _ === \"function\" ? _ : Array.isArray(_) ? constant_default4(slice.call(_)) : constant_default4(_), density3) : threshold2;\n };\n density3.bandwidth = function(_) {\n if (!arguments.length) return Math.sqrt(r * (r + 1));\n if (!((_ = +_) >= 0)) throw new Error(\"invalid bandwidth\");\n return r = (Math.sqrt(4 * _ * _ + 1) - 1) / 2, resize();\n };\n return density3;\n}\n\n// ../../node_modules/robust-predicates/esm/util.js\nvar epsilon4 = 11102230246251565e-32;\nvar splitter = 134217729;\nvar resulterrbound = (3 + 8 * epsilon4) * epsilon4;\nfunction sum3(elen, e, flen, f, h) {\n let Q, Qnew, hh, bvirt;\n let enow = e[0];\n let fnow = f[0];\n let eindex = 0;\n let findex = 0;\n if (fnow > enow === fnow > -enow) {\n Q = enow;\n enow = e[++eindex];\n } else {\n Q = fnow;\n fnow = f[++findex];\n }\n let hindex = 0;\n if (eindex < elen && findex < flen) {\n if (fnow > enow === fnow > -enow) {\n Qnew = enow + Q;\n hh = Q - (Qnew - enow);\n enow = e[++eindex];\n } else {\n Qnew = fnow + Q;\n hh = Q - (Qnew - fnow);\n fnow = f[++findex];\n }\n Q = Qnew;\n if (hh !== 0) {\n h[hindex++] = hh;\n }\n while (eindex < elen && findex < flen) {\n if (fnow > enow === fnow > -enow) {\n Qnew = Q + enow;\n bvirt = Qnew - Q;\n hh = Q - (Qnew - bvirt) + (enow - bvirt);\n enow = e[++eindex];\n } else {\n Qnew = Q + fnow;\n bvirt = Qnew - Q;\n hh = Q - (Qnew - bvirt) + (fnow - bvirt);\n fnow = f[++findex];\n }\n Q = Qnew;\n if (hh !== 0) {\n h[hindex++] = hh;\n }\n }\n }\n while (eindex < elen) {\n Qnew = Q + enow;\n bvirt = Qnew - Q;\n hh = Q - (Qnew - bvirt) + (enow - bvirt);\n enow = e[++eindex];\n Q = Qnew;\n if (hh !== 0) {\n h[hindex++] = hh;\n }\n }\n while (findex < flen) {\n Qnew = Q + fnow;\n bvirt = Qnew - Q;\n hh = Q - (Qnew - bvirt) + (fnow - bvirt);\n fnow = f[++findex];\n Q = Qnew;\n if (hh !== 0) {\n h[hindex++] = hh;\n }\n }\n if (Q !== 0 || hindex === 0) {\n h[hindex++] = Q;\n }\n return hindex;\n}\nfunction estimate(elen, e) {\n let Q = e[0];\n for (let i = 1; i < elen; i++) Q += e[i];\n return Q;\n}\nfunction vec(n) {\n return new Float64Array(n);\n}\n\n// ../../node_modules/robust-predicates/esm/orient2d.js\nvar ccwerrboundA = (3 + 16 * epsilon4) * epsilon4;\nvar ccwerrboundB = (2 + 12 * epsilon4) * epsilon4;\nvar ccwerrboundC = (9 + 64 * epsilon4) * epsilon4 * epsilon4;\nvar B2 = vec(4);\nvar C1 = vec(8);\nvar C2 = vec(12);\nvar D2 = vec(16);\nvar u = vec(4);\nfunction orient2dadapt(ax, ay, bx, by, cx, cy, detsum) {\n let acxtail, acytail, bcxtail, bcytail;\n let bvirt, c4, ahi, alo, bhi, blo, _i, _j, _0, s1, s0, t13, t03, u33;\n const acx = ax - cx;\n const bcx = bx - cx;\n const acy = ay - cy;\n const bcy = by - cy;\n s1 = acx * bcy;\n c4 = splitter * acx;\n ahi = c4 - (c4 - acx);\n alo = acx - ahi;\n c4 = splitter * bcy;\n bhi = c4 - (c4 - bcy);\n blo = bcy - bhi;\n s0 = alo * blo - (s1 - ahi * bhi - alo * bhi - ahi * blo);\n t13 = acy * bcx;\n c4 = splitter * acy;\n ahi = c4 - (c4 - acy);\n alo = acy - ahi;\n c4 = splitter * bcx;\n bhi = c4 - (c4 - bcx);\n blo = bcx - bhi;\n t03 = alo * blo - (t13 - ahi * bhi - alo * bhi - ahi * blo);\n _i = s0 - t03;\n bvirt = s0 - _i;\n B2[0] = s0 - (_i + bvirt) + (bvirt - t03);\n _j = s1 + _i;\n bvirt = _j - s1;\n _0 = s1 - (_j - bvirt) + (_i - bvirt);\n _i = _0 - t13;\n bvirt = _0 - _i;\n B2[1] = _0 - (_i + bvirt) + (bvirt - t13);\n u33 = _j + _i;\n bvirt = u33 - _j;\n B2[2] = _j - (u33 - bvirt) + (_i - bvirt);\n B2[3] = u33;\n let det = estimate(4, B2);\n let errbound = ccwerrboundB * detsum;\n if (det >= errbound || -det >= errbound) {\n return det;\n }\n bvirt = ax - acx;\n acxtail = ax - (acx + bvirt) + (bvirt - cx);\n bvirt = bx - bcx;\n bcxtail = bx - (bcx + bvirt) + (bvirt - cx);\n bvirt = ay - acy;\n acytail = ay - (acy + bvirt) + (bvirt - cy);\n bvirt = by - bcy;\n bcytail = by - (bcy + bvirt) + (bvirt - cy);\n if (acxtail === 0 && acytail === 0 && bcxtail === 0 && bcytail === 0) {\n return det;\n }\n errbound = ccwerrboundC * detsum + resulterrbound * Math.abs(det);\n det += acx * bcytail + bcy * acxtail - (acy * bcxtail + bcx * acytail);\n if (det >= errbound || -det >= errbound) return det;\n s1 = acxtail * bcy;\n c4 = splitter * acxtail;\n ahi = c4 - (c4 - acxtail);\n alo = acxtail - ahi;\n c4 = splitter * bcy;\n bhi = c4 - (c4 - bcy);\n blo = bcy - bhi;\n s0 = alo * blo - (s1 - ahi * bhi - alo * bhi - ahi * blo);\n t13 = acytail * bcx;\n c4 = splitter * acytail;\n ahi = c4 - (c4 - acytail);\n alo = acytail - ahi;\n c4 = splitter * bcx;\n bhi = c4 - (c4 - bcx);\n blo = bcx - bhi;\n t03 = alo * blo - (t13 - ahi * bhi - alo * bhi - ahi * blo);\n _i = s0 - t03;\n bvirt = s0 - _i;\n u[0] = s0 - (_i + bvirt) + (bvirt - t03);\n _j = s1 + _i;\n bvirt = _j - s1;\n _0 = s1 - (_j - bvirt) + (_i - bvirt);\n _i = _0 - t13;\n bvirt = _0 - _i;\n u[1] = _0 - (_i + bvirt) + (bvirt - t13);\n u33 = _j + _i;\n bvirt = u33 - _j;\n u[2] = _j - (u33 - bvirt) + (_i - bvirt);\n u[3] = u33;\n const C1len = sum3(4, B2, 4, u, C1);\n s1 = acx * bcytail;\n c4 = splitter * acx;\n ahi = c4 - (c4 - acx);\n alo = acx - ahi;\n c4 = splitter * bcytail;\n bhi = c4 - (c4 - bcytail);\n blo = bcytail - bhi;\n s0 = alo * blo - (s1 - ahi * bhi - alo * bhi - ahi * blo);\n t13 = acy * bcxtail;\n c4 = splitter * acy;\n ahi = c4 - (c4 - acy);\n alo = acy - ahi;\n c4 = splitter * bcxtail;\n bhi = c4 - (c4 - bcxtail);\n blo = bcxtail - bhi;\n t03 = alo * blo - (t13 - ahi * bhi - alo * bhi - ahi * blo);\n _i = s0 - t03;\n bvirt = s0 - _i;\n u[0] = s0 - (_i + bvirt) + (bvirt - t03);\n _j = s1 + _i;\n bvirt = _j - s1;\n _0 = s1 - (_j - bvirt) + (_i - bvirt);\n _i = _0 - t13;\n bvirt = _0 - _i;\n u[1] = _0 - (_i + bvirt) + (bvirt - t13);\n u33 = _j + _i;\n bvirt = u33 - _j;\n u[2] = _j - (u33 - bvirt) + (_i - bvirt);\n u[3] = u33;\n const C2len = sum3(C1len, C1, 4, u, C2);\n s1 = acxtail * bcytail;\n c4 = splitter * acxtail;\n ahi = c4 - (c4 - acxtail);\n alo = acxtail - ahi;\n c4 = splitter * bcytail;\n bhi = c4 - (c4 - bcytail);\n blo = bcytail - bhi;\n s0 = alo * blo - (s1 - ahi * bhi - alo * bhi - ahi * blo);\n t13 = acytail * bcxtail;\n c4 = splitter * acytail;\n ahi = c4 - (c4 - acytail);\n alo = acytail - ahi;\n c4 = splitter * bcxtail;\n bhi = c4 - (c4 - bcxtail);\n blo = bcxtail - bhi;\n t03 = alo * blo - (t13 - ahi * bhi - alo * bhi - ahi * blo);\n _i = s0 - t03;\n bvirt = s0 - _i;\n u[0] = s0 - (_i + bvirt) + (bvirt - t03);\n _j = s1 + _i;\n bvirt = _j - s1;\n _0 = s1 - (_j - bvirt) + (_i - bvirt);\n _i = _0 - t13;\n bvirt = _0 - _i;\n u[1] = _0 - (_i + bvirt) + (bvirt - t13);\n u33 = _j + _i;\n bvirt = u33 - _j;\n u[2] = _j - (u33 - bvirt) + (_i - bvirt);\n u[3] = u33;\n const Dlen = sum3(C2len, C2, 4, u, D2);\n return D2[Dlen - 1];\n}\nfunction orient2d(ax, ay, bx, by, cx, cy) {\n const detleft = (ay - cy) * (bx - cx);\n const detright = (ax - cx) * (by - cy);\n const det = detleft - detright;\n const detsum = Math.abs(detleft + detright);\n if (Math.abs(det) >= ccwerrboundA * detsum) return det;\n return -orient2dadapt(ax, ay, bx, by, cx, cy, detsum);\n}\n\n// ../../node_modules/robust-predicates/esm/orient3d.js\nvar o3derrboundA = (7 + 56 * epsilon4) * epsilon4;\nvar o3derrboundB = (3 + 28 * epsilon4) * epsilon4;\nvar o3derrboundC = (26 + 288 * epsilon4) * epsilon4 * epsilon4;\nvar bc = vec(4);\nvar ca = vec(4);\nvar ab = vec(4);\nvar at_b = vec(4);\nvar at_c = vec(4);\nvar bt_c = vec(4);\nvar bt_a = vec(4);\nvar ct_a = vec(4);\nvar ct_b = vec(4);\nvar bct = vec(8);\nvar cat = vec(8);\nvar abt = vec(8);\nvar u2 = vec(4);\nvar _8 = vec(8);\nvar _8b = vec(8);\nvar _16 = vec(8);\nvar _12 = vec(12);\nvar fin = vec(192);\nvar fin2 = vec(192);\n\n// ../../node_modules/robust-predicates/esm/incircle.js\nvar iccerrboundA = (10 + 96 * epsilon4) * epsilon4;\nvar iccerrboundB = (4 + 48 * epsilon4) * epsilon4;\nvar iccerrboundC = (44 + 576 * epsilon4) * epsilon4 * epsilon4;\nvar bc2 = vec(4);\nvar ca2 = vec(4);\nvar ab2 = vec(4);\nvar aa = vec(4);\nvar bb = vec(4);\nvar cc = vec(4);\nvar u3 = vec(4);\nvar v = vec(4);\nvar axtbc = vec(8);\nvar aytbc = vec(8);\nvar bxtca = vec(8);\nvar bytca = vec(8);\nvar cxtab = vec(8);\nvar cytab = vec(8);\nvar abt2 = vec(8);\nvar bct2 = vec(8);\nvar cat2 = vec(8);\nvar abtt = vec(4);\nvar bctt = vec(4);\nvar catt = vec(4);\nvar _82 = vec(8);\nvar _162 = vec(16);\nvar _16b = vec(16);\nvar _16c = vec(16);\nvar _32 = vec(32);\nvar _32b = vec(32);\nvar _48 = vec(48);\nvar _64 = vec(64);\nvar fin3 = vec(1152);\nvar fin22 = vec(1152);\n\n// ../../node_modules/robust-predicates/esm/insphere.js\nvar isperrboundA = (16 + 224 * epsilon4) * epsilon4;\nvar isperrboundB = (5 + 72 * epsilon4) * epsilon4;\nvar isperrboundC = (71 + 1408 * epsilon4) * epsilon4 * epsilon4;\nvar ab3 = vec(4);\nvar bc3 = vec(4);\nvar cd = vec(4);\nvar de = vec(4);\nvar ea = vec(4);\nvar ac = vec(4);\nvar bd = vec(4);\nvar ce = vec(4);\nvar da = vec(4);\nvar eb = vec(4);\nvar abc = vec(24);\nvar bcd = vec(24);\nvar cde = vec(24);\nvar dea = vec(24);\nvar eab = vec(24);\nvar abd = vec(24);\nvar bce = vec(24);\nvar cda = vec(24);\nvar deb = vec(24);\nvar eac = vec(24);\nvar adet = vec(1152);\nvar bdet = vec(1152);\nvar cdet = vec(1152);\nvar ddet = vec(1152);\nvar edet = vec(1152);\nvar abdet = vec(2304);\nvar cddet = vec(2304);\nvar cdedet = vec(3456);\nvar deter = vec(5760);\nvar _83 = vec(8);\nvar _8b2 = vec(8);\nvar _8c = vec(8);\nvar _163 = vec(16);\nvar _24 = vec(24);\nvar _482 = vec(48);\nvar _48b = vec(48);\nvar _96 = vec(96);\nvar _192 = vec(192);\nvar _384x = vec(384);\nvar _384y = vec(384);\nvar _384z = vec(384);\nvar _768 = vec(768);\nvar xdet = vec(96);\nvar ydet = vec(96);\nvar zdet = vec(96);\nvar fin4 = vec(1152);\n\n// ../../node_modules/delaunator/index.js\nvar EPSILON = Math.pow(2, -52);\nvar EDGE_STACK = new Uint32Array(512);\nvar Delaunator = class _Delaunator {\n static from(points2, getX = defaultGetX, getY = defaultGetY) {\n const n = points2.length;\n const coords = new Float64Array(n * 2);\n for (let i = 0; i < n; i++) {\n const p = points2[i];\n coords[2 * i] = getX(p);\n coords[2 * i + 1] = getY(p);\n }\n return new _Delaunator(coords);\n }\n constructor(coords) {\n const n = coords.length >> 1;\n if (n > 0 && typeof coords[0] !== \"number\") throw new Error(\"Expected coords to contain numbers.\");\n this.coords = coords;\n const maxTriangles = Math.max(2 * n - 5, 0);\n this._triangles = new Uint32Array(maxTriangles * 3);\n this._halfedges = new Int32Array(maxTriangles * 3);\n this._hashSize = Math.ceil(Math.sqrt(n));\n this._hullPrev = new Uint32Array(n);\n this._hullNext = new Uint32Array(n);\n this._hullTri = new Uint32Array(n);\n this._hullHash = new Int32Array(this._hashSize);\n this._ids = new Uint32Array(n);\n this._dists = new Float64Array(n);\n this.update();\n }\n update() {\n const { coords, _hullPrev: hullPrev, _hullNext: hullNext, _hullTri: hullTri, _hullHash: hullHash } = this;\n const n = coords.length >> 1;\n let minX = Infinity;\n let minY = Infinity;\n let maxX = -Infinity;\n let maxY2 = -Infinity;\n for (let i = 0; i < n; i++) {\n const x3 = coords[2 * i];\n const y3 = coords[2 * i + 1];\n if (x3 < minX) minX = x3;\n if (y3 < minY) minY = y3;\n if (x3 > maxX) maxX = x3;\n if (y3 > maxY2) maxY2 = y3;\n this._ids[i] = i;\n }\n const cx = (minX + maxX) / 2;\n const cy = (minY + maxY2) / 2;\n let i0, i1, i2;\n for (let i = 0, minDist = Infinity; i < n; i++) {\n const d = dist(cx, cy, coords[2 * i], coords[2 * i + 1]);\n if (d < minDist) {\n i0 = i;\n minDist = d;\n }\n }\n const i0x = coords[2 * i0];\n const i0y = coords[2 * i0 + 1];\n for (let i = 0, minDist = Infinity; i < n; i++) {\n if (i === i0) continue;\n const d = dist(i0x, i0y, coords[2 * i], coords[2 * i + 1]);\n if (d < minDist && d > 0) {\n i1 = i;\n minDist = d;\n }\n }\n let i1x = coords[2 * i1];\n let i1y = coords[2 * i1 + 1];\n let minRadius = Infinity;\n for (let i = 0; i < n; i++) {\n if (i === i0 || i === i1) continue;\n const r = circumradius(i0x, i0y, i1x, i1y, coords[2 * i], coords[2 * i + 1]);\n if (r < minRadius) {\n i2 = i;\n minRadius = r;\n }\n }\n let i2x = coords[2 * i2];\n let i2y = coords[2 * i2 + 1];\n if (minRadius === Infinity) {\n for (let i = 0; i < n; i++) {\n this._dists[i] = coords[2 * i] - coords[0] || coords[2 * i + 1] - coords[1];\n }\n quicksort(this._ids, this._dists, 0, n - 1);\n const hull3 = new Uint32Array(n);\n let j = 0;\n for (let i = 0, d0 = -Infinity; i < n; i++) {\n const id2 = this._ids[i];\n const d = this._dists[id2];\n if (d > d0) {\n hull3[j++] = id2;\n d0 = d;\n }\n }\n this.hull = hull3.subarray(0, j);\n this.triangles = new Uint32Array(0);\n this.halfedges = new Uint32Array(0);\n return;\n }\n if (orient2d(i0x, i0y, i1x, i1y, i2x, i2y) < 0) {\n const i = i1;\n const x3 = i1x;\n const y3 = i1y;\n i1 = i2;\n i1x = i2x;\n i1y = i2y;\n i2 = i;\n i2x = x3;\n i2y = y3;\n }\n const center2 = circumcenter(i0x, i0y, i1x, i1y, i2x, i2y);\n this._cx = center2.x;\n this._cy = center2.y;\n for (let i = 0; i < n; i++) {\n this._dists[i] = dist(coords[2 * i], coords[2 * i + 1], center2.x, center2.y);\n }\n quicksort(this._ids, this._dists, 0, n - 1);\n this._hullStart = i0;\n let hullSize = 3;\n hullNext[i0] = hullPrev[i2] = i1;\n hullNext[i1] = hullPrev[i0] = i2;\n hullNext[i2] = hullPrev[i1] = i0;\n hullTri[i0] = 0;\n hullTri[i1] = 1;\n hullTri[i2] = 2;\n hullHash.fill(-1);\n hullHash[this._hashKey(i0x, i0y)] = i0;\n hullHash[this._hashKey(i1x, i1y)] = i1;\n hullHash[this._hashKey(i2x, i2y)] = i2;\n this.trianglesLen = 0;\n this._addTriangle(i0, i1, i2, -1, -1, -1);\n for (let k2 = 0, xp, yp; k2 < this._ids.length; k2++) {\n const i = this._ids[k2];\n const x3 = coords[2 * i];\n const y3 = coords[2 * i + 1];\n if (k2 > 0 && Math.abs(x3 - xp) <= EPSILON && Math.abs(y3 - yp) <= EPSILON) continue;\n xp = x3;\n yp = y3;\n if (i === i0 || i === i1 || i === i2) continue;\n let start2 = 0;\n for (let j = 0, key = this._hashKey(x3, y3); j < this._hashSize; j++) {\n start2 = hullHash[(key + j) % this._hashSize];\n if (start2 !== -1 && start2 !== hullNext[start2]) break;\n }\n start2 = hullPrev[start2];\n let e = start2, q;\n while (q = hullNext[e], orient2d(x3, y3, coords[2 * e], coords[2 * e + 1], coords[2 * q], coords[2 * q + 1]) >= 0) {\n e = q;\n if (e === start2) {\n e = -1;\n break;\n }\n }\n if (e === -1) continue;\n let t = this._addTriangle(e, i, hullNext[e], -1, -1, hullTri[e]);\n hullTri[i] = this._legalize(t + 2);\n hullTri[e] = t;\n hullSize++;\n let n2 = hullNext[e];\n while (q = hullNext[n2], orient2d(x3, y3, coords[2 * n2], coords[2 * n2 + 1], coords[2 * q], coords[2 * q + 1]) < 0) {\n t = this._addTriangle(n2, i, q, hullTri[i], -1, hullTri[n2]);\n hullTri[i] = this._legalize(t + 2);\n hullNext[n2] = n2;\n hullSize--;\n n2 = q;\n }\n if (e === start2) {\n while (q = hullPrev[e], orient2d(x3, y3, coords[2 * q], coords[2 * q + 1], coords[2 * e], coords[2 * e + 1]) < 0) {\n t = this._addTriangle(q, i, e, -1, hullTri[e], hullTri[q]);\n this._legalize(t + 2);\n hullTri[q] = t;\n hullNext[e] = e;\n hullSize--;\n e = q;\n }\n }\n this._hullStart = hullPrev[i] = e;\n hullNext[e] = hullPrev[n2] = i;\n hullNext[i] = n2;\n hullHash[this._hashKey(x3, y3)] = i;\n hullHash[this._hashKey(coords[2 * e], coords[2 * e + 1])] = e;\n }\n this.hull = new Uint32Array(hullSize);\n for (let i = 0, e = this._hullStart; i < hullSize; i++) {\n this.hull[i] = e;\n e = hullNext[e];\n }\n this.triangles = this._triangles.subarray(0, this.trianglesLen);\n this.halfedges = this._halfedges.subarray(0, this.trianglesLen);\n }\n _hashKey(x3, y3) {\n return Math.floor(pseudoAngle(x3 - this._cx, y3 - this._cy) * this._hashSize) % this._hashSize;\n }\n _legalize(a2) {\n const { _triangles: triangles, _halfedges: halfedges, coords } = this;\n let i = 0;\n let ar = 0;\n while (true) {\n const b = halfedges[a2];\n const a0 = a2 - a2 % 3;\n ar = a0 + (a2 + 2) % 3;\n if (b === -1) {\n if (i === 0) break;\n a2 = EDGE_STACK[--i];\n continue;\n }\n const b0 = b - b % 3;\n const al = a0 + (a2 + 1) % 3;\n const bl = b0 + (b + 2) % 3;\n const p0 = triangles[ar];\n const pr = triangles[a2];\n const pl = triangles[al];\n const p1 = triangles[bl];\n const illegal = inCircle(\n coords[2 * p0],\n coords[2 * p0 + 1],\n coords[2 * pr],\n coords[2 * pr + 1],\n coords[2 * pl],\n coords[2 * pl + 1],\n coords[2 * p1],\n coords[2 * p1 + 1]\n );\n if (illegal) {\n triangles[a2] = p1;\n triangles[b] = p0;\n const hbl = halfedges[bl];\n if (hbl === -1) {\n let e = this._hullStart;\n do {\n if (this._hullTri[e] === bl) {\n this._hullTri[e] = a2;\n break;\n }\n e = this._hullPrev[e];\n } while (e !== this._hullStart);\n }\n this._link(a2, hbl);\n this._link(b, halfedges[ar]);\n this._link(ar, bl);\n const br = b0 + (b + 1) % 3;\n if (i < EDGE_STACK.length) {\n EDGE_STACK[i++] = br;\n }\n } else {\n if (i === 0) break;\n a2 = EDGE_STACK[--i];\n }\n }\n return ar;\n }\n _link(a2, b) {\n this._halfedges[a2] = b;\n if (b !== -1) this._halfedges[b] = a2;\n }\n // add a new triangle given vertex indices and adjacent half-edge ids\n _addTriangle(i0, i1, i2, a2, b, c4) {\n const t = this.trianglesLen;\n this._triangles[t] = i0;\n this._triangles[t + 1] = i1;\n this._triangles[t + 2] = i2;\n this._link(t, a2);\n this._link(t + 1, b);\n this._link(t + 2, c4);\n this.trianglesLen += 3;\n return t;\n }\n};\nfunction pseudoAngle(dx, dy) {\n const p = dx / (Math.abs(dx) + Math.abs(dy));\n return (dy > 0 ? 3 - p : 1 + p) / 4;\n}\nfunction dist(ax, ay, bx, by) {\n const dx = ax - bx;\n const dy = ay - by;\n return dx * dx + dy * dy;\n}\nfunction inCircle(ax, ay, bx, by, cx, cy, px, py) {\n const dx = ax - px;\n const dy = ay - py;\n const ex = bx - px;\n const ey = by - py;\n const fx = cx - px;\n const fy = cy - py;\n const ap = dx * dx + dy * dy;\n const bp = ex * ex + ey * ey;\n const cp = fx * fx + fy * fy;\n return dx * (ey * cp - bp * fy) - dy * (ex * cp - bp * fx) + ap * (ex * fy - ey * fx) < 0;\n}\nfunction circumradius(ax, ay, bx, by, cx, cy) {\n const dx = bx - ax;\n const dy = by - ay;\n const ex = cx - ax;\n const ey = cy - ay;\n const bl = dx * dx + dy * dy;\n const cl = ex * ex + ey * ey;\n const d = 0.5 / (dx * ey - dy * ex);\n const x3 = (ey * bl - dy * cl) * d;\n const y3 = (dx * cl - ex * bl) * d;\n return x3 * x3 + y3 * y3;\n}\nfunction circumcenter(ax, ay, bx, by, cx, cy) {\n const dx = bx - ax;\n const dy = by - ay;\n const ex = cx - ax;\n const ey = cy - ay;\n const bl = dx * dx + dy * dy;\n const cl = ex * ex + ey * ey;\n const d = 0.5 / (dx * ey - dy * ex);\n const x3 = ax + (ey * bl - dy * cl) * d;\n const y3 = ay + (dx * cl - ex * bl) * d;\n return { x: x3, y: y3 };\n}\nfunction quicksort(ids, dists, left2, right2) {\n if (right2 - left2 <= 20) {\n for (let i = left2 + 1; i <= right2; i++) {\n const temp = ids[i];\n const tempDist = dists[temp];\n let j = i - 1;\n while (j >= left2 && dists[ids[j]] > tempDist) ids[j + 1] = ids[j--];\n ids[j + 1] = temp;\n }\n } else {\n const median3 = left2 + right2 >> 1;\n let i = left2 + 1;\n let j = right2;\n swap2(ids, median3, i);\n if (dists[ids[left2]] > dists[ids[right2]]) swap2(ids, left2, right2);\n if (dists[ids[i]] > dists[ids[right2]]) swap2(ids, i, right2);\n if (dists[ids[left2]] > dists[ids[i]]) swap2(ids, left2, i);\n const temp = ids[i];\n const tempDist = dists[temp];\n while (true) {\n do\n i++;\n while (dists[ids[i]] < tempDist);\n do\n j--;\n while (dists[ids[j]] > tempDist);\n if (j < i) break;\n swap2(ids, i, j);\n }\n ids[left2 + 1] = ids[j];\n ids[j] = temp;\n if (right2 - i + 1 >= j - left2) {\n quicksort(ids, dists, i, right2);\n quicksort(ids, dists, left2, j - 1);\n } else {\n quicksort(ids, dists, left2, j - 1);\n quicksort(ids, dists, i, right2);\n }\n }\n}\nfunction swap2(arr, i, j) {\n const tmp = arr[i];\n arr[i] = arr[j];\n arr[j] = tmp;\n}\nfunction defaultGetX(p) {\n return p[0];\n}\nfunction defaultGetY(p) {\n return p[1];\n}\n\n// ../../node_modules/d3-delaunay/src/path.js\nvar epsilon5 = 1e-6;\nvar Path2 = class {\n constructor() {\n this._x0 = this._y0 = // start of current subpath\n this._x1 = this._y1 = null;\n this._ = \"\";\n }\n moveTo(x3, y3) {\n this._ += `M${this._x0 = this._x1 = +x3},${this._y0 = this._y1 = +y3}`;\n }\n closePath() {\n if (this._x1 !== null) {\n this._x1 = this._x0, this._y1 = this._y0;\n this._ += \"Z\";\n }\n }\n lineTo(x3, y3) {\n this._ += `L${this._x1 = +x3},${this._y1 = +y3}`;\n }\n arc(x3, y3, r) {\n x3 = +x3, y3 = +y3, r = +r;\n const x06 = x3 + r;\n const y06 = y3;\n if (r < 0) throw new Error(\"negative radius\");\n if (this._x1 === null) this._ += `M${x06},${y06}`;\n else if (Math.abs(this._x1 - x06) > epsilon5 || Math.abs(this._y1 - y06) > epsilon5) this._ += \"L\" + x06 + \",\" + y06;\n if (!r) return;\n this._ += `A${r},${r},0,1,1,${x3 - r},${y3}A${r},${r},0,1,1,${this._x1 = x06},${this._y1 = y06}`;\n }\n rect(x3, y3, w, h) {\n this._ += `M${this._x0 = this._x1 = +x3},${this._y0 = this._y1 = +y3}h${+w}v${+h}h${-w}Z`;\n }\n value() {\n return this._ || null;\n }\n};\n\n// ../../node_modules/d3-delaunay/src/polygon.js\nvar Polygon = class {\n constructor() {\n this._ = [];\n }\n moveTo(x3, y3) {\n this._.push([x3, y3]);\n }\n closePath() {\n this._.push(this._[0].slice());\n }\n lineTo(x3, y3) {\n this._.push([x3, y3]);\n }\n value() {\n return this._.length ? this._ : null;\n }\n};\n\n// ../../node_modules/d3-delaunay/src/voronoi.js\nvar Voronoi = class {\n constructor(delaunay, [xmin, ymin, xmax, ymax] = [0, 0, 960, 500]) {\n if (!((xmax = +xmax) >= (xmin = +xmin)) || !((ymax = +ymax) >= (ymin = +ymin))) throw new Error(\"invalid bounds\");\n this.delaunay = delaunay;\n this._circumcenters = new Float64Array(delaunay.points.length * 2);\n this.vectors = new Float64Array(delaunay.points.length * 2);\n this.xmax = xmax, this.xmin = xmin;\n this.ymax = ymax, this.ymin = ymin;\n this._init();\n }\n update() {\n this.delaunay.update();\n this._init();\n return this;\n }\n _init() {\n const { delaunay: { points: points2, hull: hull3, triangles }, vectors } = this;\n let bx, by;\n const circumcenters = this.circumcenters = this._circumcenters.subarray(0, triangles.length / 3 * 2);\n for (let i = 0, j = 0, n = triangles.length, x3, y3; i < n; i += 3, j += 2) {\n const t13 = triangles[i] * 2;\n const t22 = triangles[i + 1] * 2;\n const t32 = triangles[i + 2] * 2;\n const x13 = points2[t13];\n const y13 = points2[t13 + 1];\n const x22 = points2[t22];\n const y22 = points2[t22 + 1];\n const x32 = points2[t32];\n const y32 = points2[t32 + 1];\n const dx = x22 - x13;\n const dy = y22 - y13;\n const ex = x32 - x13;\n const ey = y32 - y13;\n const ab4 = (dx * ey - dy * ex) * 2;\n if (Math.abs(ab4) < 1e-9) {\n if (bx === void 0) {\n bx = by = 0;\n for (const i2 of hull3) bx += points2[i2 * 2], by += points2[i2 * 2 + 1];\n bx /= hull3.length, by /= hull3.length;\n }\n const a2 = 1e9 * Math.sign((bx - x13) * ey - (by - y13) * ex);\n x3 = (x13 + x32) / 2 - a2 * ey;\n y3 = (y13 + y32) / 2 + a2 * ex;\n } else {\n const d = 1 / ab4;\n const bl = dx * dx + dy * dy;\n const cl = ex * ex + ey * ey;\n x3 = x13 + (ey * bl - dy * cl) * d;\n y3 = y13 + (dx * cl - ex * bl) * d;\n }\n circumcenters[j] = x3;\n circumcenters[j + 1] = y3;\n }\n let h = hull3[hull3.length - 1];\n let p0, p1 = h * 4;\n let x06, x12 = points2[2 * h];\n let y06, y12 = points2[2 * h + 1];\n vectors.fill(0);\n for (let i = 0; i < hull3.length; ++i) {\n h = hull3[i];\n p0 = p1, x06 = x12, y06 = y12;\n p1 = h * 4, x12 = points2[2 * h], y12 = points2[2 * h + 1];\n vectors[p0 + 2] = vectors[p1] = y06 - y12;\n vectors[p0 + 3] = vectors[p1 + 1] = x12 - x06;\n }\n }\n render(context) {\n const buffer2 = context == null ? context = new Path2() : void 0;\n const { delaunay: { halfedges, inedges, hull: hull3 }, circumcenters, vectors } = this;\n if (hull3.length <= 1) return null;\n for (let i = 0, n = halfedges.length; i < n; ++i) {\n const j = halfedges[i];\n if (j < i) continue;\n const ti = Math.floor(i / 3) * 2;\n const tj = Math.floor(j / 3) * 2;\n const xi = circumcenters[ti];\n const yi = circumcenters[ti + 1];\n const xj = circumcenters[tj];\n const yj = circumcenters[tj + 1];\n this._renderSegment(xi, yi, xj, yj, context);\n }\n let h0, h1 = hull3[hull3.length - 1];\n for (let i = 0; i < hull3.length; ++i) {\n h0 = h1, h1 = hull3[i];\n const t = Math.floor(inedges[h1] / 3) * 2;\n const x3 = circumcenters[t];\n const y3 = circumcenters[t + 1];\n const v2 = h0 * 4;\n const p = this._project(x3, y3, vectors[v2 + 2], vectors[v2 + 3]);\n if (p) this._renderSegment(x3, y3, p[0], p[1], context);\n }\n return buffer2 && buffer2.value();\n }\n renderBounds(context) {\n const buffer2 = context == null ? context = new Path2() : void 0;\n context.rect(this.xmin, this.ymin, this.xmax - this.xmin, this.ymax - this.ymin);\n return buffer2 && buffer2.value();\n }\n renderCell(i, context) {\n const buffer2 = context == null ? context = new Path2() : void 0;\n const points2 = this._clip(i);\n if (points2 === null || !points2.length) return;\n context.moveTo(points2[0], points2[1]);\n let n = points2.length;\n while (points2[0] === points2[n - 2] && points2[1] === points2[n - 1] && n > 1) n -= 2;\n for (let i2 = 2; i2 < n; i2 += 2) {\n if (points2[i2] !== points2[i2 - 2] || points2[i2 + 1] !== points2[i2 - 1])\n context.lineTo(points2[i2], points2[i2 + 1]);\n }\n context.closePath();\n return buffer2 && buffer2.value();\n }\n *cellPolygons() {\n const { delaunay: { points: points2 } } = this;\n for (let i = 0, n = points2.length / 2; i < n; ++i) {\n const cell3 = this.cellPolygon(i);\n if (cell3) cell3.index = i, yield cell3;\n }\n }\n cellPolygon(i) {\n const polygon = new Polygon();\n this.renderCell(i, polygon);\n return polygon.value();\n }\n _renderSegment(x06, y06, x12, y12, context) {\n let S;\n const c0 = this._regioncode(x06, y06);\n const c1 = this._regioncode(x12, y12);\n if (c0 === 0 && c1 === 0) {\n context.moveTo(x06, y06);\n context.lineTo(x12, y12);\n } else if (S = this._clipSegment(x06, y06, x12, y12, c0, c1)) {\n context.moveTo(S[0], S[1]);\n context.lineTo(S[2], S[3]);\n }\n }\n contains(i, x3, y3) {\n if ((x3 = +x3, x3 !== x3) || (y3 = +y3, y3 !== y3)) return false;\n return this.delaunay._step(i, x3, y3) === i;\n }\n *neighbors(i) {\n const ci = this._clip(i);\n if (ci) for (const j of this.delaunay.neighbors(i)) {\n const cj = this._clip(j);\n if (cj) loop: for (let ai = 0, li = ci.length; ai < li; ai += 2) {\n for (let aj = 0, lj = cj.length; aj < lj; aj += 2) {\n if (ci[ai] === cj[aj] && ci[ai + 1] === cj[aj + 1] && ci[(ai + 2) % li] === cj[(aj + lj - 2) % lj] && ci[(ai + 3) % li] === cj[(aj + lj - 1) % lj]) {\n yield j;\n break loop;\n }\n }\n }\n }\n }\n _cell(i) {\n const { circumcenters, delaunay: { inedges, halfedges, triangles } } = this;\n const e0 = inedges[i];\n if (e0 === -1) return null;\n const points2 = [];\n let e = e0;\n do {\n const t = Math.floor(e / 3);\n points2.push(circumcenters[t * 2], circumcenters[t * 2 + 1]);\n e = e % 3 === 2 ? e - 2 : e + 1;\n if (triangles[e] !== i) break;\n e = halfedges[e];\n } while (e !== e0 && e !== -1);\n return points2;\n }\n _clip(i) {\n if (i === 0 && this.delaunay.hull.length === 1) {\n return [this.xmax, this.ymin, this.xmax, this.ymax, this.xmin, this.ymax, this.xmin, this.ymin];\n }\n const points2 = this._cell(i);\n if (points2 === null) return null;\n const { vectors: V } = this;\n const v2 = i * 4;\n return this._simplify(V[v2] || V[v2 + 1] ? this._clipInfinite(i, points2, V[v2], V[v2 + 1], V[v2 + 2], V[v2 + 3]) : this._clipFinite(i, points2));\n }\n _clipFinite(i, points2) {\n const n = points2.length;\n let P = null;\n let x06, y06, x12 = points2[n - 2], y12 = points2[n - 1];\n let c0, c1 = this._regioncode(x12, y12);\n let e0, e1 = 0;\n for (let j = 0; j < n; j += 2) {\n x06 = x12, y06 = y12, x12 = points2[j], y12 = points2[j + 1];\n c0 = c1, c1 = this._regioncode(x12, y12);\n if (c0 === 0 && c1 === 0) {\n e0 = e1, e1 = 0;\n if (P) P.push(x12, y12);\n else P = [x12, y12];\n } else {\n let S, sx0, sy0, sx1, sy1;\n if (c0 === 0) {\n if ((S = this._clipSegment(x06, y06, x12, y12, c0, c1)) === null) continue;\n [sx0, sy0, sx1, sy1] = S;\n } else {\n if ((S = this._clipSegment(x12, y12, x06, y06, c1, c0)) === null) continue;\n [sx1, sy1, sx0, sy0] = S;\n e0 = e1, e1 = this._edgecode(sx0, sy0);\n if (e0 && e1) this._edge(i, e0, e1, P, P.length);\n if (P) P.push(sx0, sy0);\n else P = [sx0, sy0];\n }\n e0 = e1, e1 = this._edgecode(sx1, sy1);\n if (e0 && e1) this._edge(i, e0, e1, P, P.length);\n if (P) P.push(sx1, sy1);\n else P = [sx1, sy1];\n }\n }\n if (P) {\n e0 = e1, e1 = this._edgecode(P[0], P[1]);\n if (e0 && e1) this._edge(i, e0, e1, P, P.length);\n } else if (this.contains(i, (this.xmin + this.xmax) / 2, (this.ymin + this.ymax) / 2)) {\n return [this.xmax, this.ymin, this.xmax, this.ymax, this.xmin, this.ymax, this.xmin, this.ymin];\n }\n return P;\n }\n _clipSegment(x06, y06, x12, y12, c0, c1) {\n const flip2 = c0 < c1;\n if (flip2) [x06, y06, x12, y12, c0, c1] = [x12, y12, x06, y06, c1, c0];\n while (true) {\n if (c0 === 0 && c1 === 0) return flip2 ? [x12, y12, x06, y06] : [x06, y06, x12, y12];\n if (c0 & c1) return null;\n let x3, y3, c4 = c0 || c1;\n if (c4 & 8) x3 = x06 + (x12 - x06) * (this.ymax - y06) / (y12 - y06), y3 = this.ymax;\n else if (c4 & 4) x3 = x06 + (x12 - x06) * (this.ymin - y06) / (y12 - y06), y3 = this.ymin;\n else if (c4 & 2) y3 = y06 + (y12 - y06) * (this.xmax - x06) / (x12 - x06), x3 = this.xmax;\n else y3 = y06 + (y12 - y06) * (this.xmin - x06) / (x12 - x06), x3 = this.xmin;\n if (c0) x06 = x3, y06 = y3, c0 = this._regioncode(x06, y06);\n else x12 = x3, y12 = y3, c1 = this._regioncode(x12, y12);\n }\n }\n _clipInfinite(i, points2, vx0, vy0, vxn, vyn) {\n let P = Array.from(points2), p;\n if (p = this._project(P[0], P[1], vx0, vy0)) P.unshift(p[0], p[1]);\n if (p = this._project(P[P.length - 2], P[P.length - 1], vxn, vyn)) P.push(p[0], p[1]);\n if (P = this._clipFinite(i, P)) {\n for (let j = 0, n = P.length, c0, c1 = this._edgecode(P[n - 2], P[n - 1]); j < n; j += 2) {\n c0 = c1, c1 = this._edgecode(P[j], P[j + 1]);\n if (c0 && c1) j = this._edge(i, c0, c1, P, j), n = P.length;\n }\n } else if (this.contains(i, (this.xmin + this.xmax) / 2, (this.ymin + this.ymax) / 2)) {\n P = [this.xmin, this.ymin, this.xmax, this.ymin, this.xmax, this.ymax, this.xmin, this.ymax];\n }\n return P;\n }\n _edge(i, e0, e1, P, j) {\n while (e0 !== e1) {\n let x3, y3;\n switch (e0) {\n case 5:\n e0 = 4;\n continue;\n // top-left\n case 4:\n e0 = 6, x3 = this.xmax, y3 = this.ymin;\n break;\n // top\n case 6:\n e0 = 2;\n continue;\n // top-right\n case 2:\n e0 = 10, x3 = this.xmax, y3 = this.ymax;\n break;\n // right\n case 10:\n e0 = 8;\n continue;\n // bottom-right\n case 8:\n e0 = 9, x3 = this.xmin, y3 = this.ymax;\n break;\n // bottom\n case 9:\n e0 = 1;\n continue;\n // bottom-left\n case 1:\n e0 = 5, x3 = this.xmin, y3 = this.ymin;\n break;\n }\n if ((P[j] !== x3 || P[j + 1] !== y3) && this.contains(i, x3, y3)) {\n P.splice(j, 0, x3, y3), j += 2;\n }\n }\n return j;\n }\n _project(x06, y06, vx, vy) {\n let t = Infinity, c4, x3, y3;\n if (vy < 0) {\n if (y06 <= this.ymin) return null;\n if ((c4 = (this.ymin - y06) / vy) < t) y3 = this.ymin, x3 = x06 + (t = c4) * vx;\n } else if (vy > 0) {\n if (y06 >= this.ymax) return null;\n if ((c4 = (this.ymax - y06) / vy) < t) y3 = this.ymax, x3 = x06 + (t = c4) * vx;\n }\n if (vx > 0) {\n if (x06 >= this.xmax) return null;\n if ((c4 = (this.xmax - x06) / vx) < t) x3 = this.xmax, y3 = y06 + (t = c4) * vy;\n } else if (vx < 0) {\n if (x06 <= this.xmin) return null;\n if ((c4 = (this.xmin - x06) / vx) < t) x3 = this.xmin, y3 = y06 + (t = c4) * vy;\n }\n return [x3, y3];\n }\n _edgecode(x3, y3) {\n return (x3 === this.xmin ? 1 : x3 === this.xmax ? 2 : 0) | (y3 === this.ymin ? 4 : y3 === this.ymax ? 8 : 0);\n }\n _regioncode(x3, y3) {\n return (x3 < this.xmin ? 1 : x3 > this.xmax ? 2 : 0) | (y3 < this.ymin ? 4 : y3 > this.ymax ? 8 : 0);\n }\n _simplify(P) {\n if (P && P.length > 4) {\n for (let i = 0; i < P.length; i += 2) {\n const j = (i + 2) % P.length, k2 = (i + 4) % P.length;\n if (P[i] === P[j] && P[j] === P[k2] || P[i + 1] === P[j + 1] && P[j + 1] === P[k2 + 1]) {\n P.splice(j, 2), i -= 2;\n }\n }\n if (!P.length) P = null;\n }\n return P;\n }\n};\n\n// ../../node_modules/d3-delaunay/src/delaunay.js\nvar tau2 = 2 * Math.PI;\nvar pow = Math.pow;\nfunction pointX(p) {\n return p[0];\n}\nfunction pointY(p) {\n return p[1];\n}\nfunction collinear2(d) {\n const { triangles, coords } = d;\n for (let i = 0; i < triangles.length; i += 3) {\n const a2 = 2 * triangles[i], b = 2 * triangles[i + 1], c4 = 2 * triangles[i + 2], cross3 = (coords[c4] - coords[a2]) * (coords[b + 1] - coords[a2 + 1]) - (coords[b] - coords[a2]) * (coords[c4 + 1] - coords[a2 + 1]);\n if (cross3 > 1e-10) return false;\n }\n return true;\n}\nfunction jitter(x3, y3, r) {\n return [x3 + Math.sin(x3 + y3) * r, y3 + Math.cos(x3 - y3) * r];\n}\nvar Delaunay = class _Delaunay {\n static from(points2, fx = pointX, fy = pointY, that) {\n return new _Delaunay(\"length\" in points2 ? flatArray(points2, fx, fy, that) : Float64Array.from(flatIterable(points2, fx, fy, that)));\n }\n constructor(points2) {\n this._delaunator = new Delaunator(points2);\n this.inedges = new Int32Array(points2.length / 2);\n this._hullIndex = new Int32Array(points2.length / 2);\n this.points = this._delaunator.coords;\n this._init();\n }\n update() {\n this._delaunator.update();\n this._init();\n return this;\n }\n _init() {\n const d = this._delaunator, points2 = this.points;\n if (d.hull && d.hull.length > 2 && collinear2(d)) {\n this.collinear = Int32Array.from({ length: points2.length / 2 }, (_, i) => i).sort((i, j) => points2[2 * i] - points2[2 * j] || points2[2 * i + 1] - points2[2 * j + 1]);\n const e = this.collinear[0], f = this.collinear[this.collinear.length - 1], bounds = [points2[2 * e], points2[2 * e + 1], points2[2 * f], points2[2 * f + 1]], r = 1e-8 * Math.hypot(bounds[3] - bounds[1], bounds[2] - bounds[0]);\n for (let i = 0, n = points2.length / 2; i < n; ++i) {\n const p = jitter(points2[2 * i], points2[2 * i + 1], r);\n points2[2 * i] = p[0];\n points2[2 * i + 1] = p[1];\n }\n this._delaunator = new Delaunator(points2);\n } else {\n delete this.collinear;\n }\n const halfedges = this.halfedges = this._delaunator.halfedges;\n const hull3 = this.hull = this._delaunator.hull;\n const triangles = this.triangles = this._delaunator.triangles;\n const inedges = this.inedges.fill(-1);\n const hullIndex = this._hullIndex.fill(-1);\n for (let e = 0, n = halfedges.length; e < n; ++e) {\n const p = triangles[e % 3 === 2 ? e - 2 : e + 1];\n if (halfedges[e] === -1 || inedges[p] === -1) inedges[p] = e;\n }\n for (let i = 0, n = hull3.length; i < n; ++i) {\n hullIndex[hull3[i]] = i;\n }\n if (hull3.length <= 2 && hull3.length > 0) {\n this.triangles = new Int32Array(3).fill(-1);\n this.halfedges = new Int32Array(3).fill(-1);\n this.triangles[0] = hull3[0];\n inedges[hull3[0]] = 1;\n if (hull3.length === 2) {\n inedges[hull3[1]] = 0;\n this.triangles[1] = hull3[1];\n this.triangles[2] = hull3[1];\n }\n }\n }\n voronoi(bounds) {\n return new Voronoi(this, bounds);\n }\n *neighbors(i) {\n const { inedges, hull: hull3, _hullIndex, halfedges, triangles, collinear: collinear3 } = this;\n if (collinear3) {\n const l = collinear3.indexOf(i);\n if (l > 0) yield collinear3[l - 1];\n if (l < collinear3.length - 1) yield collinear3[l + 1];\n return;\n }\n const e0 = inedges[i];\n if (e0 === -1) return;\n let e = e0, p0 = -1;\n do {\n yield p0 = triangles[e];\n e = e % 3 === 2 ? e - 2 : e + 1;\n if (triangles[e] !== i) return;\n e = halfedges[e];\n if (e === -1) {\n const p = hull3[(_hullIndex[i] + 1) % hull3.length];\n if (p !== p0) yield p;\n return;\n }\n } while (e !== e0);\n }\n find(x3, y3, i = 0) {\n if ((x3 = +x3, x3 !== x3) || (y3 = +y3, y3 !== y3)) return -1;\n const i0 = i;\n let c4;\n while ((c4 = this._step(i, x3, y3)) >= 0 && c4 !== i && c4 !== i0) i = c4;\n return c4;\n }\n _step(i, x3, y3) {\n const { inedges, hull: hull3, _hullIndex, halfedges, triangles, points: points2 } = this;\n if (inedges[i] === -1 || !points2.length) return (i + 1) % (points2.length >> 1);\n let c4 = i;\n let dc = pow(x3 - points2[i * 2], 2) + pow(y3 - points2[i * 2 + 1], 2);\n const e0 = inedges[i];\n let e = e0;\n do {\n let t = triangles[e];\n const dt = pow(x3 - points2[t * 2], 2) + pow(y3 - points2[t * 2 + 1], 2);\n if (dt < dc) dc = dt, c4 = t;\n e = e % 3 === 2 ? e - 2 : e + 1;\n if (triangles[e] !== i) break;\n e = halfedges[e];\n if (e === -1) {\n e = hull3[(_hullIndex[i] + 1) % hull3.length];\n if (e !== t) {\n if (pow(x3 - points2[e * 2], 2) + pow(y3 - points2[e * 2 + 1], 2) < dc) return e;\n }\n break;\n }\n } while (e !== e0);\n return c4;\n }\n render(context) {\n const buffer2 = context == null ? context = new Path2() : void 0;\n const { points: points2, halfedges, triangles } = this;\n for (let i = 0, n = halfedges.length; i < n; ++i) {\n const j = halfedges[i];\n if (j < i) continue;\n const ti = triangles[i] * 2;\n const tj = triangles[j] * 2;\n context.moveTo(points2[ti], points2[ti + 1]);\n context.lineTo(points2[tj], points2[tj + 1]);\n }\n this.renderHull(context);\n return buffer2 && buffer2.value();\n }\n renderPoints(context, r) {\n if (r === void 0 && (!context || typeof context.moveTo !== \"function\")) r = context, context = null;\n r = r == void 0 ? 2 : +r;\n const buffer2 = context == null ? context = new Path2() : void 0;\n const { points: points2 } = this;\n for (let i = 0, n = points2.length; i < n; i += 2) {\n const x3 = points2[i], y3 = points2[i + 1];\n context.moveTo(x3 + r, y3);\n context.arc(x3, y3, r, 0, tau2);\n }\n return buffer2 && buffer2.value();\n }\n renderHull(context) {\n const buffer2 = context == null ? context = new Path2() : void 0;\n const { hull: hull3, points: points2 } = this;\n const h = hull3[0] * 2, n = hull3.length;\n context.moveTo(points2[h], points2[h + 1]);\n for (let i = 1; i < n; ++i) {\n const h2 = 2 * hull3[i];\n context.lineTo(points2[h2], points2[h2 + 1]);\n }\n context.closePath();\n return buffer2 && buffer2.value();\n }\n hullPolygon() {\n const polygon = new Polygon();\n this.renderHull(polygon);\n return polygon.value();\n }\n renderTriangle(i, context) {\n const buffer2 = context == null ? context = new Path2() : void 0;\n const { points: points2, triangles } = this;\n const t03 = triangles[i *= 3] * 2;\n const t13 = triangles[i + 1] * 2;\n const t22 = triangles[i + 2] * 2;\n context.moveTo(points2[t03], points2[t03 + 1]);\n context.lineTo(points2[t13], points2[t13 + 1]);\n context.lineTo(points2[t22], points2[t22 + 1]);\n context.closePath();\n return buffer2 && buffer2.value();\n }\n *trianglePolygons() {\n const { triangles } = this;\n for (let i = 0, n = triangles.length / 3; i < n; ++i) {\n yield this.trianglePolygon(i);\n }\n }\n trianglePolygon(i) {\n const polygon = new Polygon();\n this.renderTriangle(i, polygon);\n return polygon.value();\n }\n};\nfunction flatArray(points2, fx, fy, that) {\n const n = points2.length;\n const array4 = new Float64Array(n * 2);\n for (let i = 0; i < n; ++i) {\n const p = points2[i];\n array4[i * 2] = fx.call(that, p, i, points2);\n array4[i * 2 + 1] = fy.call(that, p, i, points2);\n }\n return array4;\n}\nfunction* flatIterable(points2, fx, fy, that) {\n let i = 0;\n for (const p of points2) {\n yield fx.call(that, p, i, points2);\n yield fy.call(that, p, i, points2);\n ++i;\n }\n}\n\n// ../../node_modules/d3-format/src/formatDecimal.js\nfunction formatDecimal_default(x3) {\n return Math.abs(x3 = Math.round(x3)) >= 1e21 ? x3.toLocaleString(\"en\").replace(/,/g, \"\") : x3.toString(10);\n}\nfunction formatDecimalParts(x3, p) {\n if ((i = (x3 = p ? x3.toExponential(p - 1) : x3.toExponential()).indexOf(\"e\")) < 0) return null;\n var i, coefficient = x3.slice(0, i);\n return [\n coefficient.length > 1 ? coefficient[0] + coefficient.slice(2) : coefficient,\n +x3.slice(i + 1)\n ];\n}\n\n// ../../node_modules/d3-format/src/exponent.js\nfunction exponent_default(x3) {\n return x3 = formatDecimalParts(Math.abs(x3)), x3 ? x3[1] : NaN;\n}\n\n// ../../node_modules/d3-format/src/formatGroup.js\nfunction formatGroup_default(grouping, thousands) {\n return function(value, width2) {\n var i = value.length, t = [], j = 0, g = grouping[0], length4 = 0;\n while (i > 0 && g > 0) {\n if (length4 + g + 1 > width2) g = Math.max(1, width2 - length4);\n t.push(value.substring(i -= g, i + g));\n if ((length4 += g + 1) > width2) break;\n g = grouping[j = (j + 1) % grouping.length];\n }\n return t.reverse().join(thousands);\n };\n}\n\n// ../../node_modules/d3-format/src/formatNumerals.js\nfunction formatNumerals_default(numerals) {\n return function(value) {\n return value.replace(/[0-9]/g, function(i) {\n return numerals[+i];\n });\n };\n}\n\n// ../../node_modules/d3-format/src/formatSpecifier.js\nvar re = /^(?:(.)?([<>=^]))?([+\\-( ])?([$#])?(0)?(\\d+)?(,)?(\\.\\d+)?(~)?([a-z%])?$/i;\nfunction formatSpecifier(specifier) {\n if (!(match = re.exec(specifier))) throw new Error(\"invalid format: \" + specifier);\n var match;\n return new FormatSpecifier({\n fill: match[1],\n align: match[2],\n sign: match[3],\n symbol: match[4],\n zero: match[5],\n width: match[6],\n comma: match[7],\n precision: match[8] && match[8].slice(1),\n trim: match[9],\n type: match[10]\n });\n}\nformatSpecifier.prototype = FormatSpecifier.prototype;\nfunction FormatSpecifier(specifier) {\n this.fill = specifier.fill === void 0 ? \" \" : specifier.fill + \"\";\n this.align = specifier.align === void 0 ? \">\" : specifier.align + \"\";\n this.sign = specifier.sign === void 0 ? \"-\" : specifier.sign + \"\";\n this.symbol = specifier.symbol === void 0 ? \"\" : specifier.symbol + \"\";\n this.zero = !!specifier.zero;\n this.width = specifier.width === void 0 ? void 0 : +specifier.width;\n this.comma = !!specifier.comma;\n this.precision = specifier.precision === void 0 ? void 0 : +specifier.precision;\n this.trim = !!specifier.trim;\n this.type = specifier.type === void 0 ? \"\" : specifier.type + \"\";\n}\nFormatSpecifier.prototype.toString = function() {\n return this.fill + this.align + this.sign + this.symbol + (this.zero ? \"0\" : \"\") + (this.width === void 0 ? \"\" : Math.max(1, this.width | 0)) + (this.comma ? \",\" : \"\") + (this.precision === void 0 ? \"\" : \".\" + Math.max(0, this.precision | 0)) + (this.trim ? \"~\" : \"\") + this.type;\n};\n\n// ../../node_modules/d3-format/src/formatTrim.js\nfunction formatTrim_default(s2) {\n out: for (var n = s2.length, i = 1, i0 = -1, i1; i < n; ++i) {\n switch (s2[i]) {\n case \".\":\n i0 = i1 = i;\n break;\n case \"0\":\n if (i0 === 0) i0 = i;\n i1 = i;\n break;\n default:\n if (!+s2[i]) break out;\n if (i0 > 0) i0 = 0;\n break;\n }\n }\n return i0 > 0 ? s2.slice(0, i0) + s2.slice(i1 + 1) : s2;\n}\n\n// ../../node_modules/d3-format/src/formatPrefixAuto.js\nvar prefixExponent;\nfunction formatPrefixAuto_default(x3, p) {\n var d = formatDecimalParts(x3, p);\n if (!d) return x3 + \"\";\n var coefficient = d[0], exponent = d[1], i = exponent - (prefixExponent = Math.max(-8, Math.min(8, Math.floor(exponent / 3))) * 3) + 1, n = coefficient.length;\n return i === n ? coefficient : i > n ? coefficient + new Array(i - n + 1).join(\"0\") : i > 0 ? coefficient.slice(0, i) + \".\" + coefficient.slice(i) : \"0.\" + new Array(1 - i).join(\"0\") + formatDecimalParts(x3, Math.max(0, p + i - 1))[0];\n}\n\n// ../../node_modules/d3-format/src/formatRounded.js\nfunction formatRounded_default(x3, p) {\n var d = formatDecimalParts(x3, p);\n if (!d) return x3 + \"\";\n var coefficient = d[0], exponent = d[1];\n return exponent < 0 ? \"0.\" + new Array(-exponent).join(\"0\") + coefficient : coefficient.length > exponent + 1 ? coefficient.slice(0, exponent + 1) + \".\" + coefficient.slice(exponent + 1) : coefficient + new Array(exponent - coefficient.length + 2).join(\"0\");\n}\n\n// ../../node_modules/d3-format/src/formatTypes.js\nvar formatTypes_default = {\n \"%\": (x3, p) => (x3 * 100).toFixed(p),\n \"b\": (x3) => Math.round(x3).toString(2),\n \"c\": (x3) => x3 + \"\",\n \"d\": formatDecimal_default,\n \"e\": (x3, p) => x3.toExponential(p),\n \"f\": (x3, p) => x3.toFixed(p),\n \"g\": (x3, p) => x3.toPrecision(p),\n \"o\": (x3) => Math.round(x3).toString(8),\n \"p\": (x3, p) => formatRounded_default(x3 * 100, p),\n \"r\": formatRounded_default,\n \"s\": formatPrefixAuto_default,\n \"X\": (x3) => Math.round(x3).toString(16).toUpperCase(),\n \"x\": (x3) => Math.round(x3).toString(16)\n};\n\n// ../../node_modules/d3-format/src/identity.js\nfunction identity_default2(x3) {\n return x3;\n}\n\n// ../../node_modules/d3-format/src/locale.js\nvar map2 = Array.prototype.map;\nvar prefixes = [\"y\", \"z\", \"a\", \"f\", \"p\", \"n\", \"\\xB5\", \"m\", \"\", \"k\", \"M\", \"G\", \"T\", \"P\", \"E\", \"Z\", \"Y\"];\nfunction locale_default(locale3) {\n var group3 = locale3.grouping === void 0 || locale3.thousands === void 0 ? identity_default2 : formatGroup_default(map2.call(locale3.grouping, Number), locale3.thousands + \"\"), currencyPrefix = locale3.currency === void 0 ? \"\" : locale3.currency[0] + \"\", currencySuffix = locale3.currency === void 0 ? \"\" : locale3.currency[1] + \"\", decimal2 = locale3.decimal === void 0 ? \".\" : locale3.decimal + \"\", numerals = locale3.numerals === void 0 ? identity_default2 : formatNumerals_default(map2.call(locale3.numerals, String)), percent = locale3.percent === void 0 ? \"%\" : locale3.percent + \"\", minus = locale3.minus === void 0 ? \"\\u2212\" : locale3.minus + \"\", nan = locale3.nan === void 0 ? \"NaN\" : locale3.nan + \"\";\n function newFormat(specifier) {\n specifier = formatSpecifier(specifier);\n var fill = specifier.fill, align3 = specifier.align, sign3 = specifier.sign, symbol2 = specifier.symbol, zero3 = specifier.zero, width2 = specifier.width, comma = specifier.comma, precision = specifier.precision, trim = specifier.trim, type2 = specifier.type;\n if (type2 === \"n\") comma = true, type2 = \"g\";\n else if (!formatTypes_default[type2]) precision === void 0 && (precision = 12), trim = true, type2 = \"g\";\n if (zero3 || fill === \"0\" && align3 === \"=\") zero3 = true, fill = \"0\", align3 = \"=\";\n var prefix2 = symbol2 === \"$\" ? currencyPrefix : symbol2 === \"#\" && /[boxX]/.test(type2) ? \"0\" + type2.toLowerCase() : \"\", suffix2 = symbol2 === \"$\" ? currencySuffix : /[%p]/.test(type2) ? percent : \"\";\n var formatType = formatTypes_default[type2], maybeSuffix = /[defgprs%]/.test(type2);\n precision = precision === void 0 ? 6 : /[gprs]/.test(type2) ? Math.max(1, Math.min(21, precision)) : Math.max(0, Math.min(20, precision));\n function format3(value) {\n var valuePrefix = prefix2, valueSuffix = suffix2, i, n, c4;\n if (type2 === \"c\") {\n valueSuffix = formatType(value) + valueSuffix;\n value = \"\";\n } else {\n value = +value;\n var valueNegative = value < 0 || 1 / value < 0;\n value = isNaN(value) ? nan : formatType(Math.abs(value), precision);\n if (trim) value = formatTrim_default(value);\n if (valueNegative && +value === 0 && sign3 !== \"+\") valueNegative = false;\n valuePrefix = (valueNegative ? sign3 === \"(\" ? sign3 : minus : sign3 === \"-\" || sign3 === \"(\" ? \"\" : sign3) + valuePrefix;\n valueSuffix = (type2 === \"s\" ? prefixes[8 + prefixExponent / 3] : \"\") + valueSuffix + (valueNegative && sign3 === \"(\" ? \")\" : \"\");\n if (maybeSuffix) {\n i = -1, n = value.length;\n while (++i < n) {\n if (c4 = value.charCodeAt(i), 48 > c4 || c4 > 57) {\n valueSuffix = (c4 === 46 ? decimal2 + value.slice(i + 1) : value.slice(i)) + valueSuffix;\n value = value.slice(0, i);\n break;\n }\n }\n }\n }\n if (comma && !zero3) value = group3(value, Infinity);\n var length4 = valuePrefix.length + value.length + valueSuffix.length, padding2 = length4 < width2 ? new Array(width2 - length4 + 1).join(fill) : \"\";\n if (comma && zero3) value = group3(padding2 + value, padding2.length ? width2 - valueSuffix.length : Infinity), padding2 = \"\";\n switch (align3) {\n case \"<\":\n value = valuePrefix + value + valueSuffix + padding2;\n break;\n case \"=\":\n value = valuePrefix + padding2 + value + valueSuffix;\n break;\n case \"^\":\n value = padding2.slice(0, length4 = padding2.length >> 1) + valuePrefix + value + valueSuffix + padding2.slice(length4);\n break;\n default:\n value = padding2 + valuePrefix + value + valueSuffix;\n break;\n }\n return numerals(value);\n }\n format3.toString = function() {\n return specifier + \"\";\n };\n return format3;\n }\n function formatPrefix2(specifier, value) {\n var f = newFormat((specifier = formatSpecifier(specifier), specifier.type = \"f\", specifier)), e = Math.max(-8, Math.min(8, Math.floor(exponent_default(value) / 3))) * 3, k2 = Math.pow(10, -e), prefix2 = prefixes[8 + e / 3];\n return function(value2) {\n return f(k2 * value2) + prefix2;\n };\n }\n return {\n format: newFormat,\n formatPrefix: formatPrefix2\n };\n}\n\n// ../../node_modules/d3-format/src/defaultLocale.js\nvar locale;\nvar format;\nvar formatPrefix;\ndefaultLocale({\n thousands: \",\",\n grouping: [3],\n currency: [\"$\", \"\"]\n});\nfunction defaultLocale(definition) {\n locale = locale_default(definition);\n format = locale.format;\n formatPrefix = locale.formatPrefix;\n return locale;\n}\n\n// ../../node_modules/d3-format/src/precisionFixed.js\nfunction precisionFixed_default(step) {\n return Math.max(0, -exponent_default(Math.abs(step)));\n}\n\n// ../../node_modules/d3-format/src/precisionPrefix.js\nfunction precisionPrefix_default(step, value) {\n return Math.max(0, Math.max(-8, Math.min(8, Math.floor(exponent_default(value) / 3))) * 3 - exponent_default(Math.abs(step)));\n}\n\n// ../../node_modules/d3-format/src/precisionRound.js\nfunction precisionRound_default(step, max4) {\n step = Math.abs(step), max4 = Math.abs(max4) - step;\n return Math.max(0, exponent_default(max4) - exponent_default(step)) + 1;\n}\n\n// ../../node_modules/d3-geo/src/math.js\nvar epsilon6 = 1e-6;\nvar epsilon22 = 1e-12;\nvar pi2 = Math.PI;\nvar halfPi = pi2 / 2;\nvar quarterPi = pi2 / 4;\nvar tau3 = pi2 * 2;\nvar degrees3 = 180 / pi2;\nvar radians2 = pi2 / 180;\nvar abs2 = Math.abs;\nvar atan = Math.atan;\nvar atan2 = Math.atan2;\nvar cos = Math.cos;\nvar ceil = Math.ceil;\nvar exp = Math.exp;\nvar hypot = Math.hypot;\nvar log = Math.log;\nvar pow2 = Math.pow;\nvar sin = Math.sin;\nvar sign = Math.sign || function(x3) {\n return x3 > 0 ? 1 : x3 < 0 ? -1 : 0;\n};\nvar sqrt = Math.sqrt;\nvar tan = Math.tan;\nfunction acos(x3) {\n return x3 > 1 ? 0 : x3 < -1 ? pi2 : Math.acos(x3);\n}\nfunction asin(x3) {\n return x3 > 1 ? halfPi : x3 < -1 ? -halfPi : Math.asin(x3);\n}\n\n// ../../node_modules/d3-geo/src/noop.js\nfunction noop2() {\n}\n\n// ../../node_modules/d3-geo/src/stream.js\nfunction streamGeometry(geometry, stream) {\n if (geometry && streamGeometryType.hasOwnProperty(geometry.type)) {\n streamGeometryType[geometry.type](geometry, stream);\n }\n}\nvar streamObjectType = {\n Feature: function(object, stream) {\n streamGeometry(object.geometry, stream);\n },\n FeatureCollection: function(object, stream) {\n var features = object.features, i = -1, n = features.length;\n while (++i < n) streamGeometry(features[i].geometry, stream);\n }\n};\nvar streamGeometryType = {\n Sphere: function(object, stream) {\n stream.sphere();\n },\n Point: function(object, stream) {\n object = object.coordinates;\n stream.point(object[0], object[1], object[2]);\n },\n MultiPoint: function(object, stream) {\n var coordinates = object.coordinates, i = -1, n = coordinates.length;\n while (++i < n) object = coordinates[i], stream.point(object[0], object[1], object[2]);\n },\n LineString: function(object, stream) {\n streamLine(object.coordinates, stream, 0);\n },\n MultiLineString: function(object, stream) {\n var coordinates = object.coordinates, i = -1, n = coordinates.length;\n while (++i < n) streamLine(coordinates[i], stream, 0);\n },\n Polygon: function(object, stream) {\n streamPolygon(object.coordinates, stream);\n },\n MultiPolygon: function(object, stream) {\n var coordinates = object.coordinates, i = -1, n = coordinates.length;\n while (++i < n) streamPolygon(coordinates[i], stream);\n },\n GeometryCollection: function(object, stream) {\n var geometries = object.geometries, i = -1, n = geometries.length;\n while (++i < n) streamGeometry(geometries[i], stream);\n }\n};\nfunction streamLine(coordinates, stream, closed) {\n var i = -1, n = coordinates.length - closed, coordinate;\n stream.lineStart();\n while (++i < n) coordinate = coordinates[i], stream.point(coordinate[0], coordinate[1], coordinate[2]);\n stream.lineEnd();\n}\nfunction streamPolygon(coordinates, stream) {\n var i = -1, n = coordinates.length;\n stream.polygonStart();\n while (++i < n) streamLine(coordinates[i], stream, 1);\n stream.polygonEnd();\n}\nfunction stream_default(object, stream) {\n if (object && streamObjectType.hasOwnProperty(object.type)) {\n streamObjectType[object.type](object, stream);\n } else {\n streamGeometry(object, stream);\n }\n}\n\n// ../../node_modules/d3-geo/src/cartesian.js\nfunction spherical(cartesian2) {\n return [atan2(cartesian2[1], cartesian2[0]), asin(cartesian2[2])];\n}\nfunction cartesian(spherical2) {\n var lambda = spherical2[0], phi = spherical2[1], cosPhi = cos(phi);\n return [cosPhi * cos(lambda), cosPhi * sin(lambda), sin(phi)];\n}\nfunction cartesianDot(a2, b) {\n return a2[0] * b[0] + a2[1] * b[1] + a2[2] * b[2];\n}\nfunction cartesianCross(a2, b) {\n return [a2[1] * b[2] - a2[2] * b[1], a2[2] * b[0] - a2[0] * b[2], a2[0] * b[1] - a2[1] * b[0]];\n}\nfunction cartesianAddInPlace(a2, b) {\n a2[0] += b[0], a2[1] += b[1], a2[2] += b[2];\n}\nfunction cartesianScale(vector3, k2) {\n return [vector3[0] * k2, vector3[1] * k2, vector3[2] * k2];\n}\nfunction cartesianNormalizeInPlace(d) {\n var l = sqrt(d[0] * d[0] + d[1] * d[1] + d[2] * d[2]);\n d[0] /= l, d[1] /= l, d[2] /= l;\n}\n\n// ../../node_modules/d3-geo/src/centroid.js\nvar W0;\nvar W1;\nvar X0;\nvar Y0;\nvar Z0;\nvar X1;\nvar Y1;\nvar Z1;\nvar X2;\nvar Y2;\nvar Z2;\nvar lambda00;\nvar phi00;\nvar x0;\nvar y0;\nvar z0;\nvar centroidStream = {\n sphere: noop2,\n point: centroidPoint,\n lineStart: centroidLineStart,\n lineEnd: centroidLineEnd,\n polygonStart: function() {\n centroidStream.lineStart = centroidRingStart;\n centroidStream.lineEnd = centroidRingEnd;\n },\n polygonEnd: function() {\n centroidStream.lineStart = centroidLineStart;\n centroidStream.lineEnd = centroidLineEnd;\n }\n};\nfunction centroidPoint(lambda, phi) {\n lambda *= radians2, phi *= radians2;\n var cosPhi = cos(phi);\n centroidPointCartesian(cosPhi * cos(lambda), cosPhi * sin(lambda), sin(phi));\n}\nfunction centroidPointCartesian(x3, y3, z) {\n ++W0;\n X0 += (x3 - X0) / W0;\n Y0 += (y3 - Y0) / W0;\n Z0 += (z - Z0) / W0;\n}\nfunction centroidLineStart() {\n centroidStream.point = centroidLinePointFirst;\n}\nfunction centroidLinePointFirst(lambda, phi) {\n lambda *= radians2, phi *= radians2;\n var cosPhi = cos(phi);\n x0 = cosPhi * cos(lambda);\n y0 = cosPhi * sin(lambda);\n z0 = sin(phi);\n centroidStream.point = centroidLinePoint;\n centroidPointCartesian(x0, y0, z0);\n}\nfunction centroidLinePoint(lambda, phi) {\n lambda *= radians2, phi *= radians2;\n var cosPhi = cos(phi), x3 = cosPhi * cos(lambda), y3 = cosPhi * sin(lambda), z = sin(phi), w = atan2(sqrt((w = y0 * z - z0 * y3) * w + (w = z0 * x3 - x0 * z) * w + (w = x0 * y3 - y0 * x3) * w), x0 * x3 + y0 * y3 + z0 * z);\n W1 += w;\n X1 += w * (x0 + (x0 = x3));\n Y1 += w * (y0 + (y0 = y3));\n Z1 += w * (z0 + (z0 = z));\n centroidPointCartesian(x0, y0, z0);\n}\nfunction centroidLineEnd() {\n centroidStream.point = centroidPoint;\n}\nfunction centroidRingStart() {\n centroidStream.point = centroidRingPointFirst;\n}\nfunction centroidRingEnd() {\n centroidRingPoint(lambda00, phi00);\n centroidStream.point = centroidPoint;\n}\nfunction centroidRingPointFirst(lambda, phi) {\n lambda00 = lambda, phi00 = phi;\n lambda *= radians2, phi *= radians2;\n centroidStream.point = centroidRingPoint;\n var cosPhi = cos(phi);\n x0 = cosPhi * cos(lambda);\n y0 = cosPhi * sin(lambda);\n z0 = sin(phi);\n centroidPointCartesian(x0, y0, z0);\n}\nfunction centroidRingPoint(lambda, phi) {\n lambda *= radians2, phi *= radians2;\n var cosPhi = cos(phi), x3 = cosPhi * cos(lambda), y3 = cosPhi * sin(lambda), z = sin(phi), cx = y0 * z - z0 * y3, cy = z0 * x3 - x0 * z, cz = x0 * y3 - y0 * x3, m = hypot(cx, cy, cz), w = asin(m), v2 = m && -w / m;\n X2.add(v2 * cx);\n Y2.add(v2 * cy);\n Z2.add(v2 * cz);\n W1 += w;\n X1 += w * (x0 + (x0 = x3));\n Y1 += w * (y0 + (y0 = y3));\n Z1 += w * (z0 + (z0 = z));\n centroidPointCartesian(x0, y0, z0);\n}\nfunction centroid_default(object) {\n W0 = W1 = X0 = Y0 = Z0 = X1 = Y1 = Z1 = 0;\n X2 = new Adder();\n Y2 = new Adder();\n Z2 = new Adder();\n stream_default(object, centroidStream);\n var x3 = +X2, y3 = +Y2, z = +Z2, m = hypot(x3, y3, z);\n if (m < epsilon22) {\n x3 = X1, y3 = Y1, z = Z1;\n if (W1 < epsilon6) x3 = X0, y3 = Y0, z = Z0;\n m = hypot(x3, y3, z);\n if (m < epsilon22) return [NaN, NaN];\n }\n return [atan2(y3, x3) * degrees3, asin(z / m) * degrees3];\n}\n\n// ../../node_modules/d3-geo/src/compose.js\nfunction compose_default(a2, b) {\n function compose(x3, y3) {\n return x3 = a2(x3, y3), b(x3[0], x3[1]);\n }\n if (a2.invert && b.invert) compose.invert = function(x3, y3) {\n return x3 = b.invert(x3, y3), x3 && a2.invert(x3[0], x3[1]);\n };\n return compose;\n}\n\n// ../../node_modules/d3-geo/src/rotation.js\nfunction rotationIdentity(lambda, phi) {\n if (abs2(lambda) > pi2) lambda -= Math.round(lambda / tau3) * tau3;\n return [lambda, phi];\n}\nrotationIdentity.invert = rotationIdentity;\nfunction rotateRadians(deltaLambda, deltaPhi, deltaGamma) {\n return (deltaLambda %= tau3) ? deltaPhi || deltaGamma ? compose_default(rotationLambda(deltaLambda), rotationPhiGamma(deltaPhi, deltaGamma)) : rotationLambda(deltaLambda) : deltaPhi || deltaGamma ? rotationPhiGamma(deltaPhi, deltaGamma) : rotationIdentity;\n}\nfunction forwardRotationLambda(deltaLambda) {\n return function(lambda, phi) {\n lambda += deltaLambda;\n if (abs2(lambda) > pi2) lambda -= Math.round(lambda / tau3) * tau3;\n return [lambda, phi];\n };\n}\nfunction rotationLambda(deltaLambda) {\n var rotation = forwardRotationLambda(deltaLambda);\n rotation.invert = forwardRotationLambda(-deltaLambda);\n return rotation;\n}\nfunction rotationPhiGamma(deltaPhi, deltaGamma) {\n var cosDeltaPhi = cos(deltaPhi), sinDeltaPhi = sin(deltaPhi), cosDeltaGamma = cos(deltaGamma), sinDeltaGamma = sin(deltaGamma);\n function rotation(lambda, phi) {\n var cosPhi = cos(phi), x3 = cos(lambda) * cosPhi, y3 = sin(lambda) * cosPhi, z = sin(phi), k2 = z * cosDeltaPhi + x3 * sinDeltaPhi;\n return [\n atan2(y3 * cosDeltaGamma - k2 * sinDeltaGamma, x3 * cosDeltaPhi - z * sinDeltaPhi),\n asin(k2 * cosDeltaGamma + y3 * sinDeltaGamma)\n ];\n }\n rotation.invert = function(lambda, phi) {\n var cosPhi = cos(phi), x3 = cos(lambda) * cosPhi, y3 = sin(lambda) * cosPhi, z = sin(phi), k2 = z * cosDeltaGamma - y3 * sinDeltaGamma;\n return [\n atan2(y3 * cosDeltaGamma + z * sinDeltaGamma, x3 * cosDeltaPhi + k2 * sinDeltaPhi),\n asin(k2 * cosDeltaPhi - x3 * sinDeltaPhi)\n ];\n };\n return rotation;\n}\nfunction rotation_default(rotate) {\n rotate = rotateRadians(rotate[0] * radians2, rotate[1] * radians2, rotate.length > 2 ? rotate[2] * radians2 : 0);\n function forward(coordinates) {\n coordinates = rotate(coordinates[0] * radians2, coordinates[1] * radians2);\n return coordinates[0] *= degrees3, coordinates[1] *= degrees3, coordinates;\n }\n forward.invert = function(coordinates) {\n coordinates = rotate.invert(coordinates[0] * radians2, coordinates[1] * radians2);\n return coordinates[0] *= degrees3, coordinates[1] *= degrees3, coordinates;\n };\n return forward;\n}\n\n// ../../node_modules/d3-geo/src/circle.js\nfunction circleStream(stream, radius2, delta, direction, t03, t13) {\n if (!delta) return;\n var cosRadius = cos(radius2), sinRadius = sin(radius2), step = direction * delta;\n if (t03 == null) {\n t03 = radius2 + direction * tau3;\n t13 = radius2 - step / 2;\n } else {\n t03 = circleRadius(cosRadius, t03);\n t13 = circleRadius(cosRadius, t13);\n if (direction > 0 ? t03 < t13 : t03 > t13) t03 += direction * tau3;\n }\n for (var point6, t = t03; direction > 0 ? t > t13 : t < t13; t -= step) {\n point6 = spherical([cosRadius, -sinRadius * cos(t), -sinRadius * sin(t)]);\n stream.point(point6[0], point6[1]);\n }\n}\nfunction circleRadius(cosRadius, point6) {\n point6 = cartesian(point6), point6[0] -= cosRadius;\n cartesianNormalizeInPlace(point6);\n var radius2 = acos(-point6[1]);\n return ((-point6[2] < 0 ? -radius2 : radius2) + tau3 - epsilon6) % tau3;\n}\n\n// ../../node_modules/d3-geo/src/clip/buffer.js\nfunction buffer_default() {\n var lines = [], line3;\n return {\n point: function(x3, y3, m) {\n line3.push([x3, y3, m]);\n },\n lineStart: function() {\n lines.push(line3 = []);\n },\n lineEnd: noop2,\n rejoin: function() {\n if (lines.length > 1) lines.push(lines.pop().concat(lines.shift()));\n },\n result: function() {\n var result = lines;\n lines = [];\n line3 = null;\n return result;\n }\n };\n}\n\n// ../../node_modules/d3-geo/src/pointEqual.js\nfunction pointEqual_default(a2, b) {\n return abs2(a2[0] - b[0]) < epsilon6 && abs2(a2[1] - b[1]) < epsilon6;\n}\n\n// ../../node_modules/d3-geo/src/clip/rejoin.js\nfunction Intersection(point6, points2, other, entry) {\n this.x = point6;\n this.z = points2;\n this.o = other;\n this.e = entry;\n this.v = false;\n this.n = this.p = null;\n}\nfunction rejoin_default(segments, compareIntersection2, startInside, interpolate, stream) {\n var subject = [], clip = [], i, n;\n segments.forEach(function(segment) {\n if ((n2 = segment.length - 1) <= 0) return;\n var n2, p0 = segment[0], p1 = segment[n2], x3;\n if (pointEqual_default(p0, p1)) {\n if (!p0[2] && !p1[2]) {\n stream.lineStart();\n for (i = 0; i < n2; ++i) stream.point((p0 = segment[i])[0], p0[1]);\n stream.lineEnd();\n return;\n }\n p1[0] += 2 * epsilon6;\n }\n subject.push(x3 = new Intersection(p0, segment, null, true));\n clip.push(x3.o = new Intersection(p0, null, x3, false));\n subject.push(x3 = new Intersection(p1, segment, null, false));\n clip.push(x3.o = new Intersection(p1, null, x3, true));\n });\n if (!subject.length) return;\n clip.sort(compareIntersection2);\n link(subject);\n link(clip);\n for (i = 0, n = clip.length; i < n; ++i) {\n clip[i].e = startInside = !startInside;\n }\n var start2 = subject[0], points2, point6;\n while (1) {\n var current = start2, isSubject = true;\n while (current.v) if ((current = current.n) === start2) return;\n points2 = current.z;\n stream.lineStart();\n do {\n current.v = current.o.v = true;\n if (current.e) {\n if (isSubject) {\n for (i = 0, n = points2.length; i < n; ++i) stream.point((point6 = points2[i])[0], point6[1]);\n } else {\n interpolate(current.x, current.n.x, 1, stream);\n }\n current = current.n;\n } else {\n if (isSubject) {\n points2 = current.p.z;\n for (i = points2.length - 1; i >= 0; --i) stream.point((point6 = points2[i])[0], point6[1]);\n } else {\n interpolate(current.x, current.p.x, -1, stream);\n }\n current = current.p;\n }\n current = current.o;\n points2 = current.z;\n isSubject = !isSubject;\n } while (!current.v);\n stream.lineEnd();\n }\n}\nfunction link(array4) {\n if (!(n = array4.length)) return;\n var n, i = 0, a2 = array4[0], b;\n while (++i < n) {\n a2.n = b = array4[i];\n b.p = a2;\n a2 = b;\n }\n a2.n = b = array4[0];\n b.p = a2;\n}\n\n// ../../node_modules/d3-geo/src/polygonContains.js\nfunction longitude(point6) {\n return abs2(point6[0]) <= pi2 ? point6[0] : sign(point6[0]) * ((abs2(point6[0]) + pi2) % tau3 - pi2);\n}\nfunction polygonContains_default(polygon, point6) {\n var lambda = longitude(point6), phi = point6[1], sinPhi = sin(phi), normal = [sin(lambda), -cos(lambda), 0], angle = 0, winding = 0;\n var sum4 = new Adder();\n if (sinPhi === 1) phi = halfPi + epsilon6;\n else if (sinPhi === -1) phi = -halfPi - epsilon6;\n for (var i = 0, n = polygon.length; i < n; ++i) {\n if (!(m = (ring = polygon[i]).length)) continue;\n var ring, m, point0 = ring[m - 1], lambda0 = longitude(point0), phi0 = point0[1] / 2 + quarterPi, sinPhi0 = sin(phi0), cosPhi0 = cos(phi0);\n for (var j = 0; j < m; ++j, lambda0 = lambda1, sinPhi0 = sinPhi1, cosPhi0 = cosPhi1, point0 = point1) {\n var point1 = ring[j], lambda1 = longitude(point1), phi1 = point1[1] / 2 + quarterPi, sinPhi1 = sin(phi1), cosPhi1 = cos(phi1), delta = lambda1 - lambda0, sign3 = delta >= 0 ? 1 : -1, absDelta = sign3 * delta, antimeridian = absDelta > pi2, k2 = sinPhi0 * sinPhi1;\n sum4.add(atan2(k2 * sign3 * sin(absDelta), cosPhi0 * cosPhi1 + k2 * cos(absDelta)));\n angle += antimeridian ? delta + sign3 * tau3 : delta;\n if (antimeridian ^ lambda0 >= lambda ^ lambda1 >= lambda) {\n var arc = cartesianCross(cartesian(point0), cartesian(point1));\n cartesianNormalizeInPlace(arc);\n var intersection = cartesianCross(normal, arc);\n cartesianNormalizeInPlace(intersection);\n var phiArc = (antimeridian ^ delta >= 0 ? -1 : 1) * asin(intersection[2]);\n if (phi > phiArc || phi === phiArc && (arc[0] || arc[1])) {\n winding += antimeridian ^ delta >= 0 ? 1 : -1;\n }\n }\n }\n }\n return (angle < -epsilon6 || angle < epsilon6 && sum4 < -epsilon22) ^ winding & 1;\n}\n\n// ../../node_modules/d3-geo/src/clip/index.js\nfunction clip_default(pointVisible, clipLine, interpolate, start2) {\n return function(sink) {\n var line3 = clipLine(sink), ringBuffer = buffer_default(), ringSink = clipLine(ringBuffer), polygonStarted = false, polygon, segments, ring;\n var clip = {\n point: point6,\n lineStart,\n lineEnd,\n polygonStart: function() {\n clip.point = pointRing;\n clip.lineStart = ringStart;\n clip.lineEnd = ringEnd;\n segments = [];\n polygon = [];\n },\n polygonEnd: function() {\n clip.point = point6;\n clip.lineStart = lineStart;\n clip.lineEnd = lineEnd;\n segments = merge(segments);\n var startInside = polygonContains_default(polygon, start2);\n if (segments.length) {\n if (!polygonStarted) sink.polygonStart(), polygonStarted = true;\n rejoin_default(segments, compareIntersection, startInside, interpolate, sink);\n } else if (startInside) {\n if (!polygonStarted) sink.polygonStart(), polygonStarted = true;\n sink.lineStart();\n interpolate(null, null, 1, sink);\n sink.lineEnd();\n }\n if (polygonStarted) sink.polygonEnd(), polygonStarted = false;\n segments = polygon = null;\n },\n sphere: function() {\n sink.polygonStart();\n sink.lineStart();\n interpolate(null, null, 1, sink);\n sink.lineEnd();\n sink.polygonEnd();\n }\n };\n function point6(lambda, phi) {\n if (pointVisible(lambda, phi)) sink.point(lambda, phi);\n }\n function pointLine(lambda, phi) {\n line3.point(lambda, phi);\n }\n function lineStart() {\n clip.point = pointLine;\n line3.lineStart();\n }\n function lineEnd() {\n clip.point = point6;\n line3.lineEnd();\n }\n function pointRing(lambda, phi) {\n ring.push([lambda, phi]);\n ringSink.point(lambda, phi);\n }\n function ringStart() {\n ringSink.lineStart();\n ring = [];\n }\n function ringEnd() {\n pointRing(ring[0][0], ring[0][1]);\n ringSink.lineEnd();\n var clean = ringSink.clean(), ringSegments = ringBuffer.result(), i, n = ringSegments.length, m, segment, point7;\n ring.pop();\n polygon.push(ring);\n ring = null;\n if (!n) return;\n if (clean & 1) {\n segment = ringSegments[0];\n if ((m = segment.length - 1) > 0) {\n if (!polygonStarted) sink.polygonStart(), polygonStarted = true;\n sink.lineStart();\n for (i = 0; i < m; ++i) sink.point((point7 = segment[i])[0], point7[1]);\n sink.lineEnd();\n }\n return;\n }\n if (n > 1 && clean & 2) ringSegments.push(ringSegments.pop().concat(ringSegments.shift()));\n segments.push(ringSegments.filter(validSegment));\n }\n return clip;\n };\n}\nfunction validSegment(segment) {\n return segment.length > 1;\n}\nfunction compareIntersection(a2, b) {\n return ((a2 = a2.x)[0] < 0 ? a2[1] - halfPi - epsilon6 : halfPi - a2[1]) - ((b = b.x)[0] < 0 ? b[1] - halfPi - epsilon6 : halfPi - b[1]);\n}\n\n// ../../node_modules/d3-geo/src/clip/antimeridian.js\nvar antimeridian_default = clip_default(\n function() {\n return true;\n },\n clipAntimeridianLine,\n clipAntimeridianInterpolate,\n [-pi2, -halfPi]\n);\nfunction clipAntimeridianLine(stream) {\n var lambda0 = NaN, phi0 = NaN, sign0 = NaN, clean;\n return {\n lineStart: function() {\n stream.lineStart();\n clean = 1;\n },\n point: function(lambda1, phi1) {\n var sign1 = lambda1 > 0 ? pi2 : -pi2, delta = abs2(lambda1 - lambda0);\n if (abs2(delta - pi2) < epsilon6) {\n stream.point(lambda0, phi0 = (phi0 + phi1) / 2 > 0 ? halfPi : -halfPi);\n stream.point(sign0, phi0);\n stream.lineEnd();\n stream.lineStart();\n stream.point(sign1, phi0);\n stream.point(lambda1, phi0);\n clean = 0;\n } else if (sign0 !== sign1 && delta >= pi2) {\n if (abs2(lambda0 - sign0) < epsilon6) lambda0 -= sign0 * epsilon6;\n if (abs2(lambda1 - sign1) < epsilon6) lambda1 -= sign1 * epsilon6;\n phi0 = clipAntimeridianIntersect(lambda0, phi0, lambda1, phi1);\n stream.point(sign0, phi0);\n stream.lineEnd();\n stream.lineStart();\n stream.point(sign1, phi0);\n clean = 0;\n }\n stream.point(lambda0 = lambda1, phi0 = phi1);\n sign0 = sign1;\n },\n lineEnd: function() {\n stream.lineEnd();\n lambda0 = phi0 = NaN;\n },\n clean: function() {\n return 2 - clean;\n }\n };\n}\nfunction clipAntimeridianIntersect(lambda0, phi0, lambda1, phi1) {\n var cosPhi0, cosPhi1, sinLambda0Lambda1 = sin(lambda0 - lambda1);\n return abs2(sinLambda0Lambda1) > epsilon6 ? atan((sin(phi0) * (cosPhi1 = cos(phi1)) * sin(lambda1) - sin(phi1) * (cosPhi0 = cos(phi0)) * sin(lambda0)) / (cosPhi0 * cosPhi1 * sinLambda0Lambda1)) : (phi0 + phi1) / 2;\n}\nfunction clipAntimeridianInterpolate(from2, to, direction, stream) {\n var phi;\n if (from2 == null) {\n phi = direction * halfPi;\n stream.point(-pi2, phi);\n stream.point(0, phi);\n stream.point(pi2, phi);\n stream.point(pi2, 0);\n stream.point(pi2, -phi);\n stream.point(0, -phi);\n stream.point(-pi2, -phi);\n stream.point(-pi2, 0);\n stream.point(-pi2, phi);\n } else if (abs2(from2[0] - to[0]) > epsilon6) {\n var lambda = from2[0] < to[0] ? pi2 : -pi2;\n phi = direction * lambda / 2;\n stream.point(-lambda, phi);\n stream.point(0, phi);\n stream.point(lambda, phi);\n } else {\n stream.point(to[0], to[1]);\n }\n}\n\n// ../../node_modules/d3-geo/src/clip/circle.js\nfunction circle_default(radius2) {\n var cr = cos(radius2), delta = 6 * radians2, smallRadius = cr > 0, notHemisphere = abs2(cr) > epsilon6;\n function interpolate(from2, to, direction, stream) {\n circleStream(stream, radius2, delta, direction, from2, to);\n }\n function visible(lambda, phi) {\n return cos(lambda) * cos(phi) > cr;\n }\n function clipLine(stream) {\n var point0, c0, v0, v00, clean;\n return {\n lineStart: function() {\n v00 = v0 = false;\n clean = 1;\n },\n point: function(lambda, phi) {\n var point1 = [lambda, phi], point22, v2 = visible(lambda, phi), c4 = smallRadius ? v2 ? 0 : code(lambda, phi) : v2 ? code(lambda + (lambda < 0 ? pi2 : -pi2), phi) : 0;\n if (!point0 && (v00 = v0 = v2)) stream.lineStart();\n if (v2 !== v0) {\n point22 = intersect(point0, point1);\n if (!point22 || pointEqual_default(point0, point22) || pointEqual_default(point1, point22))\n point1[2] = 1;\n }\n if (v2 !== v0) {\n clean = 0;\n if (v2) {\n stream.lineStart();\n point22 = intersect(point1, point0);\n stream.point(point22[0], point22[1]);\n } else {\n point22 = intersect(point0, point1);\n stream.point(point22[0], point22[1], 2);\n stream.lineEnd();\n }\n point0 = point22;\n } else if (notHemisphere && point0 && smallRadius ^ v2) {\n var t;\n if (!(c4 & c0) && (t = intersect(point1, point0, true))) {\n clean = 0;\n if (smallRadius) {\n stream.lineStart();\n stream.point(t[0][0], t[0][1]);\n stream.point(t[1][0], t[1][1]);\n stream.lineEnd();\n } else {\n stream.point(t[1][0], t[1][1]);\n stream.lineEnd();\n stream.lineStart();\n stream.point(t[0][0], t[0][1], 3);\n }\n }\n }\n if (v2 && (!point0 || !pointEqual_default(point0, point1))) {\n stream.point(point1[0], point1[1]);\n }\n point0 = point1, v0 = v2, c0 = c4;\n },\n lineEnd: function() {\n if (v0) stream.lineEnd();\n point0 = null;\n },\n // Rejoin first and last segments if there were intersections and the first\n // and last points were visible.\n clean: function() {\n return clean | (v00 && v0) << 1;\n }\n };\n }\n function intersect(a2, b, two) {\n var pa = cartesian(a2), pb = cartesian(b);\n var n1 = [1, 0, 0], n2 = cartesianCross(pa, pb), n2n2 = cartesianDot(n2, n2), n1n2 = n2[0], determinant = n2n2 - n1n2 * n1n2;\n if (!determinant) return !two && a2;\n var c1 = cr * n2n2 / determinant, c22 = -cr * n1n2 / determinant, n1xn2 = cartesianCross(n1, n2), A5 = cartesianScale(n1, c1), B3 = cartesianScale(n2, c22);\n cartesianAddInPlace(A5, B3);\n var u4 = n1xn2, w = cartesianDot(A5, u4), uu = cartesianDot(u4, u4), t22 = w * w - uu * (cartesianDot(A5, A5) - 1);\n if (t22 < 0) return;\n var t = sqrt(t22), q = cartesianScale(u4, (-w - t) / uu);\n cartesianAddInPlace(q, A5);\n q = spherical(q);\n if (!two) return q;\n var lambda0 = a2[0], lambda1 = b[0], phi0 = a2[1], phi1 = b[1], z;\n if (lambda1 < lambda0) z = lambda0, lambda0 = lambda1, lambda1 = z;\n var delta2 = lambda1 - lambda0, polar = abs2(delta2 - pi2) < epsilon6, meridian = polar || delta2 < epsilon6;\n if (!polar && phi1 < phi0) z = phi0, phi0 = phi1, phi1 = z;\n if (meridian ? polar ? phi0 + phi1 > 0 ^ q[1] < (abs2(q[0] - lambda0) < epsilon6 ? phi0 : phi1) : phi0 <= q[1] && q[1] <= phi1 : delta2 > pi2 ^ (lambda0 <= q[0] && q[0] <= lambda1)) {\n var q1 = cartesianScale(u4, (-w + t) / uu);\n cartesianAddInPlace(q1, A5);\n return [q, spherical(q1)];\n }\n }\n function code(lambda, phi) {\n var r = smallRadius ? radius2 : pi2 - radius2, code2 = 0;\n if (lambda < -r) code2 |= 1;\n else if (lambda > r) code2 |= 2;\n if (phi < -r) code2 |= 4;\n else if (phi > r) code2 |= 8;\n return code2;\n }\n return clip_default(visible, clipLine, interpolate, smallRadius ? [0, -radius2] : [-pi2, radius2 - pi2]);\n}\n\n// ../../node_modules/d3-geo/src/clip/line.js\nfunction line_default(a2, b, x06, y06, x12, y12) {\n var ax = a2[0], ay = a2[1], bx = b[0], by = b[1], t03 = 0, t13 = 1, dx = bx - ax, dy = by - ay, r;\n r = x06 - ax;\n if (!dx && r > 0) return;\n r /= dx;\n if (dx < 0) {\n if (r < t03) return;\n if (r < t13) t13 = r;\n } else if (dx > 0) {\n if (r > t13) return;\n if (r > t03) t03 = r;\n }\n r = x12 - ax;\n if (!dx && r < 0) return;\n r /= dx;\n if (dx < 0) {\n if (r > t13) return;\n if (r > t03) t03 = r;\n } else if (dx > 0) {\n if (r < t03) return;\n if (r < t13) t13 = r;\n }\n r = y06 - ay;\n if (!dy && r > 0) return;\n r /= dy;\n if (dy < 0) {\n if (r < t03) return;\n if (r < t13) t13 = r;\n } else if (dy > 0) {\n if (r > t13) return;\n if (r > t03) t03 = r;\n }\n r = y12 - ay;\n if (!dy && r < 0) return;\n r /= dy;\n if (dy < 0) {\n if (r > t13) return;\n if (r > t03) t03 = r;\n } else if (dy > 0) {\n if (r < t03) return;\n if (r < t13) t13 = r;\n }\n if (t03 > 0) a2[0] = ax + t03 * dx, a2[1] = ay + t03 * dy;\n if (t13 < 1) b[0] = ax + t13 * dx, b[1] = ay + t13 * dy;\n return true;\n}\n\n// ../../node_modules/d3-geo/src/clip/rectangle.js\nvar clipMax = 1e9;\nvar clipMin = -clipMax;\nfunction clipRectangle(x06, y06, x12, y12) {\n function visible(x3, y3) {\n return x06 <= x3 && x3 <= x12 && y06 <= y3 && y3 <= y12;\n }\n function interpolate(from2, to, direction, stream) {\n var a2 = 0, a1 = 0;\n if (from2 == null || (a2 = corner(from2, direction)) !== (a1 = corner(to, direction)) || comparePoint(from2, to) < 0 ^ direction > 0) {\n do\n stream.point(a2 === 0 || a2 === 3 ? x06 : x12, a2 > 1 ? y12 : y06);\n while ((a2 = (a2 + direction + 4) % 4) !== a1);\n } else {\n stream.point(to[0], to[1]);\n }\n }\n function corner(p, direction) {\n return abs2(p[0] - x06) < epsilon6 ? direction > 0 ? 0 : 3 : abs2(p[0] - x12) < epsilon6 ? direction > 0 ? 2 : 1 : abs2(p[1] - y06) < epsilon6 ? direction > 0 ? 1 : 0 : direction > 0 ? 3 : 2;\n }\n function compareIntersection2(a2, b) {\n return comparePoint(a2.x, b.x);\n }\n function comparePoint(a2, b) {\n var ca3 = corner(a2, 1), cb = corner(b, 1);\n return ca3 !== cb ? ca3 - cb : ca3 === 0 ? b[1] - a2[1] : ca3 === 1 ? a2[0] - b[0] : ca3 === 2 ? a2[1] - b[1] : b[0] - a2[0];\n }\n return function(stream) {\n var activeStream = stream, bufferStream = buffer_default(), segments, polygon, ring, x__, y__, v__, x_, y_, v_, first3, clean;\n var clipStream = {\n point: point6,\n lineStart,\n lineEnd,\n polygonStart,\n polygonEnd\n };\n function point6(x3, y3) {\n if (visible(x3, y3)) activeStream.point(x3, y3);\n }\n function polygonInside() {\n var winding = 0;\n for (var i = 0, n = polygon.length; i < n; ++i) {\n for (var ring2 = polygon[i], j = 1, m = ring2.length, point7 = ring2[0], a0, a1, b0 = point7[0], b1 = point7[1]; j < m; ++j) {\n a0 = b0, a1 = b1, point7 = ring2[j], b0 = point7[0], b1 = point7[1];\n if (a1 <= y12) {\n if (b1 > y12 && (b0 - a0) * (y12 - a1) > (b1 - a1) * (x06 - a0)) ++winding;\n } else {\n if (b1 <= y12 && (b0 - a0) * (y12 - a1) < (b1 - a1) * (x06 - a0)) --winding;\n }\n }\n }\n return winding;\n }\n function polygonStart() {\n activeStream = bufferStream, segments = [], polygon = [], clean = true;\n }\n function polygonEnd() {\n var startInside = polygonInside(), cleanInside = clean && startInside, visible2 = (segments = merge(segments)).length;\n if (cleanInside || visible2) {\n stream.polygonStart();\n if (cleanInside) {\n stream.lineStart();\n interpolate(null, null, 1, stream);\n stream.lineEnd();\n }\n if (visible2) {\n rejoin_default(segments, compareIntersection2, startInside, interpolate, stream);\n }\n stream.polygonEnd();\n }\n activeStream = stream, segments = polygon = ring = null;\n }\n function lineStart() {\n clipStream.point = linePoint;\n if (polygon) polygon.push(ring = []);\n first3 = true;\n v_ = false;\n x_ = y_ = NaN;\n }\n function lineEnd() {\n if (segments) {\n linePoint(x__, y__);\n if (v__ && v_) bufferStream.rejoin();\n segments.push(bufferStream.result());\n }\n clipStream.point = point6;\n if (v_) activeStream.lineEnd();\n }\n function linePoint(x3, y3) {\n var v2 = visible(x3, y3);\n if (polygon) ring.push([x3, y3]);\n if (first3) {\n x__ = x3, y__ = y3, v__ = v2;\n first3 = false;\n if (v2) {\n activeStream.lineStart();\n activeStream.point(x3, y3);\n }\n } else {\n if (v2 && v_) activeStream.point(x3, y3);\n else {\n var a2 = [x_ = Math.max(clipMin, Math.min(clipMax, x_)), y_ = Math.max(clipMin, Math.min(clipMax, y_))], b = [x3 = Math.max(clipMin, Math.min(clipMax, x3)), y3 = Math.max(clipMin, Math.min(clipMax, y3))];\n if (line_default(a2, b, x06, y06, x12, y12)) {\n if (!v_) {\n activeStream.lineStart();\n activeStream.point(a2[0], a2[1]);\n }\n activeStream.point(b[0], b[1]);\n if (!v2) activeStream.lineEnd();\n clean = false;\n } else if (v2) {\n activeStream.lineStart();\n activeStream.point(x3, y3);\n clean = false;\n }\n }\n }\n x_ = x3, y_ = y3, v_ = v2;\n }\n return clipStream;\n };\n}\n\n// ../../node_modules/d3-geo/src/graticule.js\nfunction graticuleX(y06, y12, dy) {\n var y3 = range(y06, y12 - epsilon6, dy).concat(y12);\n return function(x3) {\n return y3.map(function(y4) {\n return [x3, y4];\n });\n };\n}\nfunction graticuleY(x06, x12, dx) {\n var x3 = range(x06, x12 - epsilon6, dx).concat(x12);\n return function(y3) {\n return x3.map(function(x4) {\n return [x4, y3];\n });\n };\n}\nfunction graticule() {\n var x12, x06, X13, X03, y12, y06, Y13, Y03, dx = 10, dy = dx, DX = 90, DY = 360, x3, y3, X3, Y3, precision = 2.5;\n function graticule4() {\n return { type: \"MultiLineString\", coordinates: lines() };\n }\n function lines() {\n return range(ceil(X03 / DX) * DX, X13, DX).map(X3).concat(range(ceil(Y03 / DY) * DY, Y13, DY).map(Y3)).concat(range(ceil(x06 / dx) * dx, x12, dx).filter(function(x4) {\n return abs2(x4 % DX) > epsilon6;\n }).map(x3)).concat(range(ceil(y06 / dy) * dy, y12, dy).filter(function(y4) {\n return abs2(y4 % DY) > epsilon6;\n }).map(y3));\n }\n graticule4.lines = function() {\n return lines().map(function(coordinates) {\n return { type: \"LineString\", coordinates };\n });\n };\n graticule4.outline = function() {\n return {\n type: \"Polygon\",\n coordinates: [\n X3(X03).concat(\n Y3(Y13).slice(1),\n X3(X13).reverse().slice(1),\n Y3(Y03).reverse().slice(1)\n )\n ]\n };\n };\n graticule4.extent = function(_) {\n if (!arguments.length) return graticule4.extentMinor();\n return graticule4.extentMajor(_).extentMinor(_);\n };\n graticule4.extentMajor = function(_) {\n if (!arguments.length) return [[X03, Y03], [X13, Y13]];\n X03 = +_[0][0], X13 = +_[1][0];\n Y03 = +_[0][1], Y13 = +_[1][1];\n if (X03 > X13) _ = X03, X03 = X13, X13 = _;\n if (Y03 > Y13) _ = Y03, Y03 = Y13, Y13 = _;\n return graticule4.precision(precision);\n };\n graticule4.extentMinor = function(_) {\n if (!arguments.length) return [[x06, y06], [x12, y12]];\n x06 = +_[0][0], x12 = +_[1][0];\n y06 = +_[0][1], y12 = +_[1][1];\n if (x06 > x12) _ = x06, x06 = x12, x12 = _;\n if (y06 > y12) _ = y06, y06 = y12, y12 = _;\n return graticule4.precision(precision);\n };\n graticule4.step = function(_) {\n if (!arguments.length) return graticule4.stepMinor();\n return graticule4.stepMajor(_).stepMinor(_);\n };\n graticule4.stepMajor = function(_) {\n if (!arguments.length) return [DX, DY];\n DX = +_[0], DY = +_[1];\n return graticule4;\n };\n graticule4.stepMinor = function(_) {\n if (!arguments.length) return [dx, dy];\n dx = +_[0], dy = +_[1];\n return graticule4;\n };\n graticule4.precision = function(_) {\n if (!arguments.length) return precision;\n precision = +_;\n x3 = graticuleX(y06, y12, 90);\n y3 = graticuleY(x06, x12, precision);\n X3 = graticuleX(Y03, Y13, 90);\n Y3 = graticuleY(X03, X13, precision);\n return graticule4;\n };\n return graticule4.extentMajor([[-180, -90 + epsilon6], [180, 90 - epsilon6]]).extentMinor([[-180, -80 - epsilon6], [180, 80 + epsilon6]]);\n}\nfunction graticule10() {\n return graticule()();\n}\n\n// ../../node_modules/d3-geo/src/identity.js\nvar identity_default3 = (x3) => x3;\n\n// ../../node_modules/d3-geo/src/path/area.js\nvar areaSum = new Adder();\nvar areaRingSum = new Adder();\nvar x00;\nvar y00;\nvar x02;\nvar y02;\nvar areaStream = {\n point: noop2,\n lineStart: noop2,\n lineEnd: noop2,\n polygonStart: function() {\n areaStream.lineStart = areaRingStart;\n areaStream.lineEnd = areaRingEnd;\n },\n polygonEnd: function() {\n areaStream.lineStart = areaStream.lineEnd = areaStream.point = noop2;\n areaSum.add(abs2(areaRingSum));\n areaRingSum = new Adder();\n },\n result: function() {\n var area3 = areaSum / 2;\n areaSum = new Adder();\n return area3;\n }\n};\nfunction areaRingStart() {\n areaStream.point = areaPointFirst;\n}\nfunction areaPointFirst(x3, y3) {\n areaStream.point = areaPoint;\n x00 = x02 = x3, y00 = y02 = y3;\n}\nfunction areaPoint(x3, y3) {\n areaRingSum.add(y02 * x3 - x02 * y3);\n x02 = x3, y02 = y3;\n}\nfunction areaRingEnd() {\n areaPoint(x00, y00);\n}\nvar area_default2 = areaStream;\n\n// ../../node_modules/d3-geo/src/path/bounds.js\nvar x03 = Infinity;\nvar y03 = x03;\nvar x1 = -x03;\nvar y1 = x1;\nvar boundsStream = {\n point: boundsPoint,\n lineStart: noop2,\n lineEnd: noop2,\n polygonStart: noop2,\n polygonEnd: noop2,\n result: function() {\n var bounds = [[x03, y03], [x1, y1]];\n x1 = y1 = -(y03 = x03 = Infinity);\n return bounds;\n }\n};\nfunction boundsPoint(x3, y3) {\n if (x3 < x03) x03 = x3;\n if (x3 > x1) x1 = x3;\n if (y3 < y03) y03 = y3;\n if (y3 > y1) y1 = y3;\n}\nvar bounds_default = boundsStream;\n\n// ../../node_modules/d3-geo/src/path/centroid.js\nvar X02 = 0;\nvar Y02 = 0;\nvar Z02 = 0;\nvar X12 = 0;\nvar Y12 = 0;\nvar Z12 = 0;\nvar X22 = 0;\nvar Y22 = 0;\nvar Z22 = 0;\nvar x002;\nvar y002;\nvar x04;\nvar y04;\nvar centroidStream2 = {\n point: centroidPoint2,\n lineStart: centroidLineStart2,\n lineEnd: centroidLineEnd2,\n polygonStart: function() {\n centroidStream2.lineStart = centroidRingStart2;\n centroidStream2.lineEnd = centroidRingEnd2;\n },\n polygonEnd: function() {\n centroidStream2.point = centroidPoint2;\n centroidStream2.lineStart = centroidLineStart2;\n centroidStream2.lineEnd = centroidLineEnd2;\n },\n result: function() {\n var centroid3 = Z22 ? [X22 / Z22, Y22 / Z22] : Z12 ? [X12 / Z12, Y12 / Z12] : Z02 ? [X02 / Z02, Y02 / Z02] : [NaN, NaN];\n X02 = Y02 = Z02 = X12 = Y12 = Z12 = X22 = Y22 = Z22 = 0;\n return centroid3;\n }\n};\nfunction centroidPoint2(x3, y3) {\n X02 += x3;\n Y02 += y3;\n ++Z02;\n}\nfunction centroidLineStart2() {\n centroidStream2.point = centroidPointFirstLine;\n}\nfunction centroidPointFirstLine(x3, y3) {\n centroidStream2.point = centroidPointLine;\n centroidPoint2(x04 = x3, y04 = y3);\n}\nfunction centroidPointLine(x3, y3) {\n var dx = x3 - x04, dy = y3 - y04, z = sqrt(dx * dx + dy * dy);\n X12 += z * (x04 + x3) / 2;\n Y12 += z * (y04 + y3) / 2;\n Z12 += z;\n centroidPoint2(x04 = x3, y04 = y3);\n}\nfunction centroidLineEnd2() {\n centroidStream2.point = centroidPoint2;\n}\nfunction centroidRingStart2() {\n centroidStream2.point = centroidPointFirstRing;\n}\nfunction centroidRingEnd2() {\n centroidPointRing(x002, y002);\n}\nfunction centroidPointFirstRing(x3, y3) {\n centroidStream2.point = centroidPointRing;\n centroidPoint2(x002 = x04 = x3, y002 = y04 = y3);\n}\nfunction centroidPointRing(x3, y3) {\n var dx = x3 - x04, dy = y3 - y04, z = sqrt(dx * dx + dy * dy);\n X12 += z * (x04 + x3) / 2;\n Y12 += z * (y04 + y3) / 2;\n Z12 += z;\n z = y04 * x3 - x04 * y3;\n X22 += z * (x04 + x3);\n Y22 += z * (y04 + y3);\n Z22 += z * 3;\n centroidPoint2(x04 = x3, y04 = y3);\n}\nvar centroid_default2 = centroidStream2;\n\n// ../../node_modules/d3-geo/src/path/context.js\nfunction PathContext(context) {\n this._context = context;\n}\nPathContext.prototype = {\n _radius: 4.5,\n pointRadius: function(_) {\n return this._radius = _, this;\n },\n polygonStart: function() {\n this._line = 0;\n },\n polygonEnd: function() {\n this._line = NaN;\n },\n lineStart: function() {\n this._point = 0;\n },\n lineEnd: function() {\n if (this._line === 0) this._context.closePath();\n this._point = NaN;\n },\n point: function(x3, y3) {\n switch (this._point) {\n case 0: {\n this._context.moveTo(x3, y3);\n this._point = 1;\n break;\n }\n case 1: {\n this._context.lineTo(x3, y3);\n break;\n }\n default: {\n this._context.moveTo(x3 + this._radius, y3);\n this._context.arc(x3, y3, this._radius, 0, tau3);\n break;\n }\n }\n },\n result: noop2\n};\n\n// ../../node_modules/d3-geo/src/path/measure.js\nvar lengthSum = new Adder();\nvar lengthRing;\nvar x003;\nvar y003;\nvar x05;\nvar y05;\nvar lengthStream = {\n point: noop2,\n lineStart: function() {\n lengthStream.point = lengthPointFirst;\n },\n lineEnd: function() {\n if (lengthRing) lengthPoint(x003, y003);\n lengthStream.point = noop2;\n },\n polygonStart: function() {\n lengthRing = true;\n },\n polygonEnd: function() {\n lengthRing = null;\n },\n result: function() {\n var length4 = +lengthSum;\n lengthSum = new Adder();\n return length4;\n }\n};\nfunction lengthPointFirst(x3, y3) {\n lengthStream.point = lengthPoint;\n x003 = x05 = x3, y003 = y05 = y3;\n}\nfunction lengthPoint(x3, y3) {\n x05 -= x3, y05 -= y3;\n lengthSum.add(sqrt(x05 * x05 + y05 * y05));\n x05 = x3, y05 = y3;\n}\nvar measure_default = lengthStream;\n\n// ../../node_modules/d3-geo/src/path/string.js\nvar cacheDigits;\nvar cacheAppend;\nvar cacheRadius;\nvar cacheCircle;\nvar PathString = class {\n constructor(digits) {\n this._append = digits == null ? append2 : appendRound2(digits);\n this._radius = 4.5;\n this._ = \"\";\n }\n pointRadius(_) {\n this._radius = +_;\n return this;\n }\n polygonStart() {\n this._line = 0;\n }\n polygonEnd() {\n this._line = NaN;\n }\n lineStart() {\n this._point = 0;\n }\n lineEnd() {\n if (this._line === 0) this._ += \"Z\";\n this._point = NaN;\n }\n point(x3, y3) {\n switch (this._point) {\n case 0: {\n this._append`M${x3},${y3}`;\n this._point = 1;\n break;\n }\n case 1: {\n this._append`L${x3},${y3}`;\n break;\n }\n default: {\n this._append`M${x3},${y3}`;\n if (this._radius !== cacheRadius || this._append !== cacheAppend) {\n const r = this._radius;\n const s2 = this._;\n this._ = \"\";\n this._append`m0,${r}a${r},${r} 0 1,1 0,${-2 * r}a${r},${r} 0 1,1 0,${2 * r}z`;\n cacheRadius = r;\n cacheAppend = this._append;\n cacheCircle = this._;\n this._ = s2;\n }\n this._ += cacheCircle;\n break;\n }\n }\n }\n result() {\n const result = this._;\n this._ = \"\";\n return result.length ? result : null;\n }\n};\nfunction append2(strings) {\n let i = 1;\n this._ += strings[0];\n for (const j = strings.length; i < j; ++i) {\n this._ += arguments[i] + strings[i];\n }\n}\nfunction appendRound2(digits) {\n const d = Math.floor(digits);\n if (!(d >= 0)) throw new RangeError(`invalid digits: ${digits}`);\n if (d > 15) return append2;\n if (d !== cacheDigits) {\n const k2 = 10 ** d;\n cacheDigits = d;\n cacheAppend = function append3(strings) {\n let i = 1;\n this._ += strings[0];\n for (const j = strings.length; i < j; ++i) {\n this._ += Math.round(arguments[i] * k2) / k2 + strings[i];\n }\n };\n }\n return cacheAppend;\n}\n\n// ../../node_modules/d3-geo/src/path/index.js\nfunction path_default(projection3, context) {\n let digits = 3, pointRadius = 4.5, projectionStream, contextStream;\n function path2(object) {\n if (object) {\n if (typeof pointRadius === \"function\") contextStream.pointRadius(+pointRadius.apply(this, arguments));\n stream_default(object, projectionStream(contextStream));\n }\n return contextStream.result();\n }\n path2.area = function(object) {\n stream_default(object, projectionStream(area_default2));\n return area_default2.result();\n };\n path2.measure = function(object) {\n stream_default(object, projectionStream(measure_default));\n return measure_default.result();\n };\n path2.bounds = function(object) {\n stream_default(object, projectionStream(bounds_default));\n return bounds_default.result();\n };\n path2.centroid = function(object) {\n stream_default(object, projectionStream(centroid_default2));\n return centroid_default2.result();\n };\n path2.projection = function(_) {\n if (!arguments.length) return projection3;\n projectionStream = _ == null ? (projection3 = null, identity_default3) : (projection3 = _).stream;\n return path2;\n };\n path2.context = function(_) {\n if (!arguments.length) return context;\n contextStream = _ == null ? (context = null, new PathString(digits)) : new PathContext(context = _);\n if (typeof pointRadius !== \"function\") contextStream.pointRadius(pointRadius);\n return path2;\n };\n path2.pointRadius = function(_) {\n if (!arguments.length) return pointRadius;\n pointRadius = typeof _ === \"function\" ? _ : (contextStream.pointRadius(+_), +_);\n return path2;\n };\n path2.digits = function(_) {\n if (!arguments.length) return digits;\n if (_ == null) digits = null;\n else {\n const d = Math.floor(_);\n if (!(d >= 0)) throw new RangeError(`invalid digits: ${_}`);\n digits = d;\n }\n if (context === null) contextStream = new PathString(digits);\n return path2;\n };\n return path2.projection(projection3).digits(digits).context(context);\n}\n\n// ../../node_modules/d3-geo/src/transform.js\nfunction transform_default(methods) {\n return {\n stream: transformer(methods)\n };\n}\nfunction transformer(methods) {\n return function(stream) {\n var s2 = new TransformStream();\n for (var key in methods) s2[key] = methods[key];\n s2.stream = stream;\n return s2;\n };\n}\nfunction TransformStream() {\n}\nTransformStream.prototype = {\n constructor: TransformStream,\n point: function(x3, y3) {\n this.stream.point(x3, y3);\n },\n sphere: function() {\n this.stream.sphere();\n },\n lineStart: function() {\n this.stream.lineStart();\n },\n lineEnd: function() {\n this.stream.lineEnd();\n },\n polygonStart: function() {\n this.stream.polygonStart();\n },\n polygonEnd: function() {\n this.stream.polygonEnd();\n }\n};\n\n// ../../node_modules/d3-geo/src/projection/fit.js\nfunction fit(projection3, fitBounds, object) {\n var clip = projection3.clipExtent && projection3.clipExtent();\n projection3.scale(150).translate([0, 0]);\n if (clip != null) projection3.clipExtent(null);\n stream_default(object, projection3.stream(bounds_default));\n fitBounds(bounds_default.result());\n if (clip != null) projection3.clipExtent(clip);\n return projection3;\n}\nfunction fitExtent(projection3, extent4, object) {\n return fit(projection3, function(b) {\n var w = extent4[1][0] - extent4[0][0], h = extent4[1][1] - extent4[0][1], k2 = Math.min(w / (b[1][0] - b[0][0]), h / (b[1][1] - b[0][1])), x3 = +extent4[0][0] + (w - k2 * (b[1][0] + b[0][0])) / 2, y3 = +extent4[0][1] + (h - k2 * (b[1][1] + b[0][1])) / 2;\n projection3.scale(150 * k2).translate([x3, y3]);\n }, object);\n}\nfunction fitSize(projection3, size, object) {\n return fitExtent(projection3, [[0, 0], size], object);\n}\nfunction fitWidth(projection3, width2, object) {\n return fit(projection3, function(b) {\n var w = +width2, k2 = w / (b[1][0] - b[0][0]), x3 = (w - k2 * (b[1][0] + b[0][0])) / 2, y3 = -k2 * b[0][1];\n projection3.scale(150 * k2).translate([x3, y3]);\n }, object);\n}\nfunction fitHeight(projection3, height2, object) {\n return fit(projection3, function(b) {\n var h = +height2, k2 = h / (b[1][1] - b[0][1]), x3 = -k2 * b[0][0], y3 = (h - k2 * (b[1][1] + b[0][1])) / 2;\n projection3.scale(150 * k2).translate([x3, y3]);\n }, object);\n}\n\n// ../../node_modules/d3-geo/src/projection/resample.js\nvar maxDepth = 16;\nvar cosMinDistance = cos(30 * radians2);\nfunction resample_default(project2, delta2) {\n return +delta2 ? resample(project2, delta2) : resampleNone(project2);\n}\nfunction resampleNone(project2) {\n return transformer({\n point: function(x3, y3) {\n x3 = project2(x3, y3);\n this.stream.point(x3[0], x3[1]);\n }\n });\n}\nfunction resample(project2, delta2) {\n function resampleLineTo(x06, y06, lambda0, a0, b0, c0, x12, y12, lambda1, a1, b1, c1, depth, stream) {\n var dx = x12 - x06, dy = y12 - y06, d2 = dx * dx + dy * dy;\n if (d2 > 4 * delta2 && depth--) {\n var a2 = a0 + a1, b = b0 + b1, c4 = c0 + c1, m = sqrt(a2 * a2 + b * b + c4 * c4), phi2 = asin(c4 /= m), lambda2 = abs2(abs2(c4) - 1) < epsilon6 || abs2(lambda0 - lambda1) < epsilon6 ? (lambda0 + lambda1) / 2 : atan2(b, a2), p = project2(lambda2, phi2), x22 = p[0], y22 = p[1], dx2 = x22 - x06, dy2 = y22 - y06, dz = dy * dx2 - dx * dy2;\n if (dz * dz / d2 > delta2 || abs2((dx * dx2 + dy * dy2) / d2 - 0.5) > 0.3 || a0 * a1 + b0 * b1 + c0 * c1 < cosMinDistance) {\n resampleLineTo(x06, y06, lambda0, a0, b0, c0, x22, y22, lambda2, a2 /= m, b /= m, c4, depth, stream);\n stream.point(x22, y22);\n resampleLineTo(x22, y22, lambda2, a2, b, c4, x12, y12, lambda1, a1, b1, c1, depth, stream);\n }\n }\n }\n return function(stream) {\n var lambda002, x004, y004, a00, b00, c00, lambda0, x06, y06, a0, b0, c0;\n var resampleStream = {\n point: point6,\n lineStart,\n lineEnd,\n polygonStart: function() {\n stream.polygonStart();\n resampleStream.lineStart = ringStart;\n },\n polygonEnd: function() {\n stream.polygonEnd();\n resampleStream.lineStart = lineStart;\n }\n };\n function point6(x3, y3) {\n x3 = project2(x3, y3);\n stream.point(x3[0], x3[1]);\n }\n function lineStart() {\n x06 = NaN;\n resampleStream.point = linePoint;\n stream.lineStart();\n }\n function linePoint(lambda, phi) {\n var c4 = cartesian([lambda, phi]), p = project2(lambda, phi);\n resampleLineTo(x06, y06, lambda0, a0, b0, c0, x06 = p[0], y06 = p[1], lambda0 = lambda, a0 = c4[0], b0 = c4[1], c0 = c4[2], maxDepth, stream);\n stream.point(x06, y06);\n }\n function lineEnd() {\n resampleStream.point = point6;\n stream.lineEnd();\n }\n function ringStart() {\n lineStart();\n resampleStream.point = ringPoint;\n resampleStream.lineEnd = ringEnd;\n }\n function ringPoint(lambda, phi) {\n linePoint(lambda002 = lambda, phi), x004 = x06, y004 = y06, a00 = a0, b00 = b0, c00 = c0;\n resampleStream.point = linePoint;\n }\n function ringEnd() {\n resampleLineTo(x06, y06, lambda0, a0, b0, c0, x004, y004, lambda002, a00, b00, c00, maxDepth, stream);\n resampleStream.lineEnd = lineEnd;\n lineEnd();\n }\n return resampleStream;\n };\n}\n\n// ../../node_modules/d3-geo/src/projection/index.js\nvar transformRadians = transformer({\n point: function(x3, y3) {\n this.stream.point(x3 * radians2, y3 * radians2);\n }\n});\nfunction transformRotate(rotate) {\n return transformer({\n point: function(x3, y3) {\n var r = rotate(x3, y3);\n return this.stream.point(r[0], r[1]);\n }\n });\n}\nfunction scaleTranslate(k2, dx, dy, sx, sy) {\n function transform3(x3, y3) {\n x3 *= sx;\n y3 *= sy;\n return [dx + k2 * x3, dy - k2 * y3];\n }\n transform3.invert = function(x3, y3) {\n return [(x3 - dx) / k2 * sx, (dy - y3) / k2 * sy];\n };\n return transform3;\n}\nfunction scaleTranslateRotate(k2, dx, dy, sx, sy, alpha) {\n if (!alpha) return scaleTranslate(k2, dx, dy, sx, sy);\n var cosAlpha = cos(alpha), sinAlpha = sin(alpha), a2 = cosAlpha * k2, b = sinAlpha * k2, ai = cosAlpha / k2, bi = sinAlpha / k2, ci = (sinAlpha * dy - cosAlpha * dx) / k2, fi = (sinAlpha * dx + cosAlpha * dy) / k2;\n function transform3(x3, y3) {\n x3 *= sx;\n y3 *= sy;\n return [a2 * x3 - b * y3 + dx, dy - b * x3 - a2 * y3];\n }\n transform3.invert = function(x3, y3) {\n return [sx * (ai * x3 - bi * y3 + ci), sy * (fi - bi * x3 - ai * y3)];\n };\n return transform3;\n}\nfunction projection(project2) {\n return projectionMutator(function() {\n return project2;\n })();\n}\nfunction projectionMutator(projectAt) {\n var project2, k2 = 150, x3 = 480, y3 = 250, lambda = 0, phi = 0, deltaLambda = 0, deltaPhi = 0, deltaGamma = 0, rotate, alpha = 0, sx = 1, sy = 1, theta = null, preclip = antimeridian_default, x06 = null, y06, x12, y12, postclip = identity_default3, delta2 = 0.5, projectResample, projectTransform, projectRotateTransform, cache, cacheStream;\n function projection3(point6) {\n return projectRotateTransform(point6[0] * radians2, point6[1] * radians2);\n }\n function invert2(point6) {\n point6 = projectRotateTransform.invert(point6[0], point6[1]);\n return point6 && [point6[0] * degrees3, point6[1] * degrees3];\n }\n projection3.stream = function(stream) {\n return cache && cacheStream === stream ? cache : cache = transformRadians(transformRotate(rotate)(preclip(projectResample(postclip(cacheStream = stream)))));\n };\n projection3.preclip = function(_) {\n return arguments.length ? (preclip = _, theta = void 0, reset()) : preclip;\n };\n projection3.postclip = function(_) {\n return arguments.length ? (postclip = _, x06 = y06 = x12 = y12 = null, reset()) : postclip;\n };\n projection3.clipAngle = function(_) {\n return arguments.length ? (preclip = +_ ? circle_default(theta = _ * radians2) : (theta = null, antimeridian_default), reset()) : theta * degrees3;\n };\n projection3.clipExtent = function(_) {\n return arguments.length ? (postclip = _ == null ? (x06 = y06 = x12 = y12 = null, identity_default3) : clipRectangle(x06 = +_[0][0], y06 = +_[0][1], x12 = +_[1][0], y12 = +_[1][1]), reset()) : x06 == null ? null : [[x06, y06], [x12, y12]];\n };\n projection3.scale = function(_) {\n return arguments.length ? (k2 = +_, recenter()) : k2;\n };\n projection3.translate = function(_) {\n return arguments.length ? (x3 = +_[0], y3 = +_[1], recenter()) : [x3, y3];\n };\n projection3.center = function(_) {\n return arguments.length ? (lambda = _[0] % 360 * radians2, phi = _[1] % 360 * radians2, recenter()) : [lambda * degrees3, phi * degrees3];\n };\n projection3.rotate = function(_) {\n return arguments.length ? (deltaLambda = _[0] % 360 * radians2, deltaPhi = _[1] % 360 * radians2, deltaGamma = _.length > 2 ? _[2] % 360 * radians2 : 0, recenter()) : [deltaLambda * degrees3, deltaPhi * degrees3, deltaGamma * degrees3];\n };\n projection3.angle = function(_) {\n return arguments.length ? (alpha = _ % 360 * radians2, recenter()) : alpha * degrees3;\n };\n projection3.reflectX = function(_) {\n return arguments.length ? (sx = _ ? -1 : 1, recenter()) : sx < 0;\n };\n projection3.reflectY = function(_) {\n return arguments.length ? (sy = _ ? -1 : 1, recenter()) : sy < 0;\n };\n projection3.precision = function(_) {\n return arguments.length ? (projectResample = resample_default(projectTransform, delta2 = _ * _), reset()) : sqrt(delta2);\n };\n projection3.fitExtent = function(extent4, object) {\n return fitExtent(projection3, extent4, object);\n };\n projection3.fitSize = function(size, object) {\n return fitSize(projection3, size, object);\n };\n projection3.fitWidth = function(width2, object) {\n return fitWidth(projection3, width2, object);\n };\n projection3.fitHeight = function(height2, object) {\n return fitHeight(projection3, height2, object);\n };\n function recenter() {\n var center2 = scaleTranslateRotate(k2, 0, 0, sx, sy, alpha).apply(null, project2(lambda, phi)), transform3 = scaleTranslateRotate(k2, x3 - center2[0], y3 - center2[1], sx, sy, alpha);\n rotate = rotateRadians(deltaLambda, deltaPhi, deltaGamma);\n projectTransform = compose_default(project2, transform3);\n projectRotateTransform = compose_default(rotate, projectTransform);\n projectResample = resample_default(projectTransform, delta2);\n return reset();\n }\n function reset() {\n cache = cacheStream = null;\n return projection3;\n }\n return function() {\n project2 = projectAt.apply(this, arguments);\n projection3.invert = project2.invert && invert2;\n return recenter();\n };\n}\n\n// ../../node_modules/d3-geo/src/projection/conic.js\nfunction conicProjection(projectAt) {\n var phi0 = 0, phi1 = pi2 / 3, m = projectionMutator(projectAt), p = m(phi0, phi1);\n p.parallels = function(_) {\n return arguments.length ? m(phi0 = _[0] * radians2, phi1 = _[1] * radians2) : [phi0 * degrees3, phi1 * degrees3];\n };\n return p;\n}\n\n// ../../node_modules/d3-geo/src/projection/cylindricalEqualArea.js\nfunction cylindricalEqualAreaRaw(phi0) {\n var cosPhi0 = cos(phi0);\n function forward(lambda, phi) {\n return [lambda * cosPhi0, sin(phi) / cosPhi0];\n }\n forward.invert = function(x3, y3) {\n return [x3 / cosPhi0, asin(y3 * cosPhi0)];\n };\n return forward;\n}\n\n// ../../node_modules/d3-geo/src/projection/conicEqualArea.js\nfunction conicEqualAreaRaw(y06, y12) {\n var sy0 = sin(y06), n = (sy0 + sin(y12)) / 2;\n if (abs2(n) < epsilon6) return cylindricalEqualAreaRaw(y06);\n var c4 = 1 + sy0 * (2 * n - sy0), r0 = sqrt(c4) / n;\n function project2(x3, y3) {\n var r = sqrt(c4 - 2 * n * sin(y3)) / n;\n return [r * sin(x3 *= n), r0 - r * cos(x3)];\n }\n project2.invert = function(x3, y3) {\n var r0y = r0 - y3, l = atan2(x3, abs2(r0y)) * sign(r0y);\n if (r0y * n < 0)\n l -= pi2 * sign(x3) * sign(r0y);\n return [l / n, asin((c4 - (x3 * x3 + r0y * r0y) * n * n) / (2 * n))];\n };\n return project2;\n}\nfunction conicEqualArea_default() {\n return conicProjection(conicEqualAreaRaw).scale(155.424).center([0, 33.6442]);\n}\n\n// ../../node_modules/d3-geo/src/projection/albers.js\nfunction albers_default() {\n return conicEqualArea_default().parallels([29.5, 45.5]).scale(1070).translate([480, 250]).rotate([96, 0]).center([-0.6, 38.7]);\n}\n\n// ../../node_modules/d3-geo/src/projection/albersUsa.js\nfunction multiplex(streams) {\n var n = streams.length;\n return {\n point: function(x3, y3) {\n var i = -1;\n while (++i < n) streams[i].point(x3, y3);\n },\n sphere: function() {\n var i = -1;\n while (++i < n) streams[i].sphere();\n },\n lineStart: function() {\n var i = -1;\n while (++i < n) streams[i].lineStart();\n },\n lineEnd: function() {\n var i = -1;\n while (++i < n) streams[i].lineEnd();\n },\n polygonStart: function() {\n var i = -1;\n while (++i < n) streams[i].polygonStart();\n },\n polygonEnd: function() {\n var i = -1;\n while (++i < n) streams[i].polygonEnd();\n }\n };\n}\nfunction albersUsa_default() {\n var cache, cacheStream, lower48 = albers_default(), lower48Point, alaska = conicEqualArea_default().rotate([154, 0]).center([-2, 58.5]).parallels([55, 65]), alaskaPoint, hawaii = conicEqualArea_default().rotate([157, 0]).center([-3, 19.9]).parallels([8, 18]), hawaiiPoint, point6, pointStream = { point: function(x3, y3) {\n point6 = [x3, y3];\n } };\n function albersUsa(coordinates) {\n var x3 = coordinates[0], y3 = coordinates[1];\n return point6 = null, (lower48Point.point(x3, y3), point6) || (alaskaPoint.point(x3, y3), point6) || (hawaiiPoint.point(x3, y3), point6);\n }\n albersUsa.invert = function(coordinates) {\n var k2 = lower48.scale(), t = lower48.translate(), x3 = (coordinates[0] - t[0]) / k2, y3 = (coordinates[1] - t[1]) / k2;\n return (y3 >= 0.12 && y3 < 0.234 && x3 >= -0.425 && x3 < -0.214 ? alaska : y3 >= 0.166 && y3 < 0.234 && x3 >= -0.214 && x3 < -0.115 ? hawaii : lower48).invert(coordinates);\n };\n albersUsa.stream = function(stream) {\n return cache && cacheStream === stream ? cache : cache = multiplex([lower48.stream(cacheStream = stream), alaska.stream(stream), hawaii.stream(stream)]);\n };\n albersUsa.precision = function(_) {\n if (!arguments.length) return lower48.precision();\n lower48.precision(_), alaska.precision(_), hawaii.precision(_);\n return reset();\n };\n albersUsa.scale = function(_) {\n if (!arguments.length) return lower48.scale();\n lower48.scale(_), alaska.scale(_ * 0.35), hawaii.scale(_);\n return albersUsa.translate(lower48.translate());\n };\n albersUsa.translate = function(_) {\n if (!arguments.length) return lower48.translate();\n var k2 = lower48.scale(), x3 = +_[0], y3 = +_[1];\n lower48Point = lower48.translate(_).clipExtent([[x3 - 0.455 * k2, y3 - 0.238 * k2], [x3 + 0.455 * k2, y3 + 0.238 * k2]]).stream(pointStream);\n alaskaPoint = alaska.translate([x3 - 0.307 * k2, y3 + 0.201 * k2]).clipExtent([[x3 - 0.425 * k2 + epsilon6, y3 + 0.12 * k2 + epsilon6], [x3 - 0.214 * k2 - epsilon6, y3 + 0.234 * k2 - epsilon6]]).stream(pointStream);\n hawaiiPoint = hawaii.translate([x3 - 0.205 * k2, y3 + 0.212 * k2]).clipExtent([[x3 - 0.214 * k2 + epsilon6, y3 + 0.166 * k2 + epsilon6], [x3 - 0.115 * k2 - epsilon6, y3 + 0.234 * k2 - epsilon6]]).stream(pointStream);\n return reset();\n };\n albersUsa.fitExtent = function(extent4, object) {\n return fitExtent(albersUsa, extent4, object);\n };\n albersUsa.fitSize = function(size, object) {\n return fitSize(albersUsa, size, object);\n };\n albersUsa.fitWidth = function(width2, object) {\n return fitWidth(albersUsa, width2, object);\n };\n albersUsa.fitHeight = function(height2, object) {\n return fitHeight(albersUsa, height2, object);\n };\n function reset() {\n cache = cacheStream = null;\n return albersUsa;\n }\n return albersUsa.scale(1070);\n}\n\n// ../../node_modules/d3-geo/src/projection/azimuthal.js\nfunction azimuthalRaw(scale3) {\n return function(x3, y3) {\n var cx = cos(x3), cy = cos(y3), k2 = scale3(cx * cy);\n if (k2 === Infinity) return [2, 0];\n return [\n k2 * cy * sin(x3),\n k2 * sin(y3)\n ];\n };\n}\nfunction azimuthalInvert(angle) {\n return function(x3, y3) {\n var z = sqrt(x3 * x3 + y3 * y3), c4 = angle(z), sc = sin(c4), cc2 = cos(c4);\n return [\n atan2(x3 * sc, z * cc2),\n asin(z && y3 * sc / z)\n ];\n };\n}\n\n// ../../node_modules/d3-geo/src/projection/azimuthalEqualArea.js\nvar azimuthalEqualAreaRaw = azimuthalRaw(function(cxcy) {\n return sqrt(2 / (1 + cxcy));\n});\nazimuthalEqualAreaRaw.invert = azimuthalInvert(function(z) {\n return 2 * asin(z / 2);\n});\nfunction azimuthalEqualArea_default() {\n return projection(azimuthalEqualAreaRaw).scale(124.75).clipAngle(180 - 1e-3);\n}\n\n// ../../node_modules/d3-geo/src/projection/azimuthalEquidistant.js\nvar azimuthalEquidistantRaw = azimuthalRaw(function(c4) {\n return (c4 = acos(c4)) && c4 / sin(c4);\n});\nazimuthalEquidistantRaw.invert = azimuthalInvert(function(z) {\n return z;\n});\nfunction azimuthalEquidistant_default() {\n return projection(azimuthalEquidistantRaw).scale(79.4188).clipAngle(180 - 1e-3);\n}\n\n// ../../node_modules/d3-geo/src/projection/mercator.js\nfunction mercatorRaw(lambda, phi) {\n return [lambda, log(tan((halfPi + phi) / 2))];\n}\nmercatorRaw.invert = function(x3, y3) {\n return [x3, 2 * atan(exp(y3)) - halfPi];\n};\nfunction mercator_default() {\n return mercatorProjection(mercatorRaw).scale(961 / tau3);\n}\nfunction mercatorProjection(project2) {\n var m = projection(project2), center2 = m.center, scale3 = m.scale, translate = m.translate, clipExtent = m.clipExtent, x06 = null, y06, x12, y12;\n m.scale = function(_) {\n return arguments.length ? (scale3(_), reclip()) : scale3();\n };\n m.translate = function(_) {\n return arguments.length ? (translate(_), reclip()) : translate();\n };\n m.center = function(_) {\n return arguments.length ? (center2(_), reclip()) : center2();\n };\n m.clipExtent = function(_) {\n return arguments.length ? (_ == null ? x06 = y06 = x12 = y12 = null : (x06 = +_[0][0], y06 = +_[0][1], x12 = +_[1][0], y12 = +_[1][1]), reclip()) : x06 == null ? null : [[x06, y06], [x12, y12]];\n };\n function reclip() {\n var k2 = pi2 * scale3(), t = m(rotation_default(m.rotate()).invert([0, 0]));\n return clipExtent(x06 == null ? [[t[0] - k2, t[1] - k2], [t[0] + k2, t[1] + k2]] : project2 === mercatorRaw ? [[Math.max(t[0] - k2, x06), y06], [Math.min(t[0] + k2, x12), y12]] : [[x06, Math.max(t[1] - k2, y06)], [x12, Math.min(t[1] + k2, y12)]]);\n }\n return reclip();\n}\n\n// ../../node_modules/d3-geo/src/projection/conicConformal.js\nfunction tany(y3) {\n return tan((halfPi + y3) / 2);\n}\nfunction conicConformalRaw(y06, y12) {\n var cy0 = cos(y06), n = y06 === y12 ? sin(y06) : log(cy0 / cos(y12)) / log(tany(y12) / tany(y06)), f = cy0 * pow2(tany(y06), n) / n;\n if (!n) return mercatorRaw;\n function project2(x3, y3) {\n if (f > 0) {\n if (y3 < -halfPi + epsilon6) y3 = -halfPi + epsilon6;\n } else {\n if (y3 > halfPi - epsilon6) y3 = halfPi - epsilon6;\n }\n var r = f / pow2(tany(y3), n);\n return [r * sin(n * x3), f - r * cos(n * x3)];\n }\n project2.invert = function(x3, y3) {\n var fy = f - y3, r = sign(n) * sqrt(x3 * x3 + fy * fy), l = atan2(x3, abs2(fy)) * sign(fy);\n if (fy * n < 0)\n l -= pi2 * sign(x3) * sign(fy);\n return [l / n, 2 * atan(pow2(f / r, 1 / n)) - halfPi];\n };\n return project2;\n}\nfunction conicConformal_default() {\n return conicProjection(conicConformalRaw).scale(109.5).parallels([30, 30]);\n}\n\n// ../../node_modules/d3-geo/src/projection/equirectangular.js\nfunction equirectangularRaw(lambda, phi) {\n return [lambda, phi];\n}\nequirectangularRaw.invert = equirectangularRaw;\nfunction equirectangular_default() {\n return projection(equirectangularRaw).scale(152.63);\n}\n\n// ../../node_modules/d3-geo/src/projection/conicEquidistant.js\nfunction conicEquidistantRaw(y06, y12) {\n var cy0 = cos(y06), n = y06 === y12 ? sin(y06) : (cy0 - cos(y12)) / (y12 - y06), g = cy0 / n + y06;\n if (abs2(n) < epsilon6) return equirectangularRaw;\n function project2(x3, y3) {\n var gy = g - y3, nx = n * x3;\n return [gy * sin(nx), g - gy * cos(nx)];\n }\n project2.invert = function(x3, y3) {\n var gy = g - y3, l = atan2(x3, abs2(gy)) * sign(gy);\n if (gy * n < 0)\n l -= pi2 * sign(x3) * sign(gy);\n return [l / n, g - sign(n) * sqrt(x3 * x3 + gy * gy)];\n };\n return project2;\n}\nfunction conicEquidistant_default() {\n return conicProjection(conicEquidistantRaw).scale(131.154).center([0, 13.9389]);\n}\n\n// ../../node_modules/d3-geo/src/projection/equalEarth.js\nvar A1 = 1.340264;\nvar A2 = -0.081106;\nvar A3 = 893e-6;\nvar A4 = 3796e-6;\nvar M = sqrt(3) / 2;\nvar iterations = 12;\nfunction equalEarthRaw(lambda, phi) {\n var l = asin(M * sin(phi)), l2 = l * l, l6 = l2 * l2 * l2;\n return [\n lambda * cos(l) / (M * (A1 + 3 * A2 * l2 + l6 * (7 * A3 + 9 * A4 * l2))),\n l * (A1 + A2 * l2 + l6 * (A3 + A4 * l2))\n ];\n}\nequalEarthRaw.invert = function(x3, y3) {\n var l = y3, l2 = l * l, l6 = l2 * l2 * l2;\n for (var i = 0, delta, fy, fpy; i < iterations; ++i) {\n fy = l * (A1 + A2 * l2 + l6 * (A3 + A4 * l2)) - y3;\n fpy = A1 + 3 * A2 * l2 + l6 * (7 * A3 + 9 * A4 * l2);\n l -= delta = fy / fpy, l2 = l * l, l6 = l2 * l2 * l2;\n if (abs2(delta) < epsilon22) break;\n }\n return [\n M * x3 * (A1 + 3 * A2 * l2 + l6 * (7 * A3 + 9 * A4 * l2)) / cos(l),\n asin(sin(l) / M)\n ];\n};\nfunction equalEarth_default() {\n return projection(equalEarthRaw).scale(177.158);\n}\n\n// ../../node_modules/d3-geo/src/projection/gnomonic.js\nfunction gnomonicRaw(x3, y3) {\n var cy = cos(y3), k2 = cos(x3) * cy;\n return [cy * sin(x3) / k2, sin(y3) / k2];\n}\ngnomonicRaw.invert = azimuthalInvert(atan);\nfunction gnomonic_default() {\n return projection(gnomonicRaw).scale(144.049).clipAngle(60);\n}\n\n// ../../node_modules/d3-geo/src/projection/orthographic.js\nfunction orthographicRaw(x3, y3) {\n return [cos(y3) * sin(x3), sin(y3)];\n}\northographicRaw.invert = azimuthalInvert(asin);\nfunction orthographic_default() {\n return projection(orthographicRaw).scale(249.5).clipAngle(90 + epsilon6);\n}\n\n// ../../node_modules/d3-geo/src/projection/stereographic.js\nfunction stereographicRaw(x3, y3) {\n var cy = cos(y3), k2 = 1 + cos(x3) * cy;\n return [cy * sin(x3) / k2, sin(y3) / k2];\n}\nstereographicRaw.invert = azimuthalInvert(function(z) {\n return 2 * atan(z);\n});\nfunction stereographic_default() {\n return projection(stereographicRaw).scale(250).clipAngle(142);\n}\n\n// ../../node_modules/d3-geo/src/projection/transverseMercator.js\nfunction transverseMercatorRaw(lambda, phi) {\n return [log(tan((halfPi + phi) / 2)), -lambda];\n}\ntransverseMercatorRaw.invert = function(x3, y3) {\n return [-y3, 2 * atan(exp(x3)) - halfPi];\n};\nfunction transverseMercator_default() {\n var m = mercatorProjection(transverseMercatorRaw), center2 = m.center, rotate = m.rotate;\n m.center = function(_) {\n return arguments.length ? center2([-_[1], _[0]]) : (_ = center2(), [_[1], -_[0]]);\n };\n m.rotate = function(_) {\n return arguments.length ? rotate([_[0], _[1], _.length > 2 ? _[2] + 90 : 90]) : (_ = rotate(), [_[0], _[1], _[2] - 90]);\n };\n return rotate([0, 0, 90]).scale(159.155);\n}\n\n// ../../node_modules/d3-hierarchy/src/cluster.js\nfunction defaultSeparation(a2, b) {\n return a2.parent === b.parent ? 1 : 2;\n}\nfunction meanX(children2) {\n return children2.reduce(meanXReduce, 0) / children2.length;\n}\nfunction meanXReduce(x3, c4) {\n return x3 + c4.x;\n}\nfunction maxY(children2) {\n return 1 + children2.reduce(maxYReduce, 0);\n}\nfunction maxYReduce(y3, c4) {\n return Math.max(y3, c4.y);\n}\nfunction leafLeft(node) {\n var children2;\n while (children2 = node.children) node = children2[0];\n return node;\n}\nfunction leafRight(node) {\n var children2;\n while (children2 = node.children) node = children2[children2.length - 1];\n return node;\n}\nfunction cluster_default() {\n var separation = defaultSeparation, dx = 1, dy = 1, nodeSize = false;\n function cluster2(root2) {\n var previousNode, x3 = 0;\n root2.eachAfter(function(node) {\n var children2 = node.children;\n if (children2) {\n node.x = meanX(children2);\n node.y = maxY(children2);\n } else {\n node.x = previousNode ? x3 += separation(node, previousNode) : 0;\n node.y = 0;\n previousNode = node;\n }\n });\n var left2 = leafLeft(root2), right2 = leafRight(root2), x06 = left2.x - separation(left2, right2) / 2, x12 = right2.x + separation(right2, left2) / 2;\n return root2.eachAfter(nodeSize ? function(node) {\n node.x = (node.x - root2.x) * dx;\n node.y = (root2.y - node.y) * dy;\n } : function(node) {\n node.x = (node.x - x06) / (x12 - x06) * dx;\n node.y = (1 - (root2.y ? node.y / root2.y : 1)) * dy;\n });\n }\n cluster2.separation = function(x3) {\n return arguments.length ? (separation = x3, cluster2) : separation;\n };\n cluster2.size = function(x3) {\n return arguments.length ? (nodeSize = false, dx = +x3[0], dy = +x3[1], cluster2) : nodeSize ? null : [dx, dy];\n };\n cluster2.nodeSize = function(x3) {\n return arguments.length ? (nodeSize = true, dx = +x3[0], dy = +x3[1], cluster2) : nodeSize ? [dx, dy] : null;\n };\n return cluster2;\n}\n\n// ../../node_modules/d3-hierarchy/src/hierarchy/count.js\nfunction count3(node) {\n var sum4 = 0, children2 = node.children, i = children2 && children2.length;\n if (!i) sum4 = 1;\n else while (--i >= 0) sum4 += children2[i].value;\n node.value = sum4;\n}\nfunction count_default() {\n return this.eachAfter(count3);\n}\n\n// ../../node_modules/d3-hierarchy/src/hierarchy/each.js\nfunction each_default2(callback, that) {\n let index2 = -1;\n for (const node of this) {\n callback.call(that, node, ++index2, this);\n }\n return this;\n}\n\n// ../../node_modules/d3-hierarchy/src/hierarchy/eachBefore.js\nfunction eachBefore_default(callback, that) {\n var node = this, nodes = [node], children2, i, index2 = -1;\n while (node = nodes.pop()) {\n callback.call(that, node, ++index2, this);\n if (children2 = node.children) {\n for (i = children2.length - 1; i >= 0; --i) {\n nodes.push(children2[i]);\n }\n }\n }\n return this;\n}\n\n// ../../node_modules/d3-hierarchy/src/hierarchy/eachAfter.js\nfunction eachAfter_default(callback, that) {\n var node = this, nodes = [node], next = [], children2, i, n, index2 = -1;\n while (node = nodes.pop()) {\n next.push(node);\n if (children2 = node.children) {\n for (i = 0, n = children2.length; i < n; ++i) {\n nodes.push(children2[i]);\n }\n }\n }\n while (node = next.pop()) {\n callback.call(that, node, ++index2, this);\n }\n return this;\n}\n\n// ../../node_modules/d3-hierarchy/src/hierarchy/find.js\nfunction find_default(callback, that) {\n let index2 = -1;\n for (const node of this) {\n if (callback.call(that, node, ++index2, this)) {\n return node;\n }\n }\n}\n\n// ../../node_modules/d3-hierarchy/src/hierarchy/sum.js\nfunction sum_default(value) {\n return this.eachAfter(function(node) {\n var sum4 = +value(node.data) || 0, children2 = node.children, i = children2 && children2.length;\n while (--i >= 0) sum4 += children2[i].value;\n node.value = sum4;\n });\n}\n\n// ../../node_modules/d3-hierarchy/src/hierarchy/sort.js\nfunction sort_default2(compare) {\n return this.eachBefore(function(node) {\n if (node.children) {\n node.children.sort(compare);\n }\n });\n}\n\n// ../../node_modules/d3-hierarchy/src/hierarchy/path.js\nfunction path_default2(end) {\n var start2 = this, ancestor = leastCommonAncestor(start2, end), nodes = [start2];\n while (start2 !== ancestor) {\n start2 = start2.parent;\n nodes.push(start2);\n }\n var k2 = nodes.length;\n while (end !== ancestor) {\n nodes.splice(k2, 0, end);\n end = end.parent;\n }\n return nodes;\n}\nfunction leastCommonAncestor(a2, b) {\n if (a2 === b) return a2;\n var aNodes = a2.ancestors(), bNodes = b.ancestors(), c4 = null;\n a2 = aNodes.pop();\n b = bNodes.pop();\n while (a2 === b) {\n c4 = a2;\n a2 = aNodes.pop();\n b = bNodes.pop();\n }\n return c4;\n}\n\n// ../../node_modules/d3-hierarchy/src/hierarchy/ancestors.js\nfunction ancestors_default() {\n var node = this, nodes = [node];\n while (node = node.parent) {\n nodes.push(node);\n }\n return nodes;\n}\n\n// ../../node_modules/d3-hierarchy/src/hierarchy/descendants.js\nfunction descendants_default() {\n return Array.from(this);\n}\n\n// ../../node_modules/d3-hierarchy/src/hierarchy/leaves.js\nfunction leaves_default() {\n var leaves = [];\n this.eachBefore(function(node) {\n if (!node.children) {\n leaves.push(node);\n }\n });\n return leaves;\n}\n\n// ../../node_modules/d3-hierarchy/src/hierarchy/links.js\nfunction links_default() {\n var root2 = this, links = [];\n root2.each(function(node) {\n if (node !== root2) {\n links.push({ source: node.parent, target: node });\n }\n });\n return links;\n}\n\n// ../../node_modules/d3-hierarchy/src/hierarchy/iterator.js\nfunction* iterator_default2() {\n var node = this, current, next = [node], children2, i, n;\n do {\n current = next.reverse(), next = [];\n while (node = current.pop()) {\n yield node;\n if (children2 = node.children) {\n for (i = 0, n = children2.length; i < n; ++i) {\n next.push(children2[i]);\n }\n }\n }\n } while (next.length);\n}\n\n// ../../node_modules/d3-hierarchy/src/hierarchy/index.js\nfunction hierarchy(data, children2) {\n if (data instanceof Map) {\n data = [void 0, data];\n if (children2 === void 0) children2 = mapChildren;\n } else if (children2 === void 0) {\n children2 = objectChildren;\n }\n var root2 = new Node(data), node, nodes = [root2], child, childs, i, n;\n while (node = nodes.pop()) {\n if ((childs = children2(node.data)) && (n = (childs = Array.from(childs)).length)) {\n node.children = childs;\n for (i = n - 1; i >= 0; --i) {\n nodes.push(child = childs[i] = new Node(childs[i]));\n child.parent = node;\n child.depth = node.depth + 1;\n }\n }\n }\n return root2.eachBefore(computeHeight);\n}\nfunction node_copy() {\n return hierarchy(this).eachBefore(copyData);\n}\nfunction objectChildren(d) {\n return d.children;\n}\nfunction mapChildren(d) {\n return Array.isArray(d) ? d[1] : null;\n}\nfunction copyData(node) {\n if (node.data.value !== void 0) node.value = node.data.value;\n node.data = node.data.data;\n}\nfunction computeHeight(node) {\n var height2 = 0;\n do\n node.height = height2;\n while ((node = node.parent) && node.height < ++height2);\n}\nfunction Node(data) {\n this.data = data;\n this.depth = this.height = 0;\n this.parent = null;\n}\nNode.prototype = hierarchy.prototype = {\n constructor: Node,\n count: count_default,\n each: each_default2,\n eachAfter: eachAfter_default,\n eachBefore: eachBefore_default,\n find: find_default,\n sum: sum_default,\n sort: sort_default2,\n path: path_default2,\n ancestors: ancestors_default,\n descendants: descendants_default,\n leaves: leaves_default,\n links: links_default,\n copy: node_copy,\n [Symbol.iterator]: iterator_default2\n};\n\n// ../../node_modules/d3-hierarchy/src/accessors.js\nfunction optional(f) {\n return f == null ? null : required(f);\n}\nfunction required(f) {\n if (typeof f !== \"function\") throw new Error();\n return f;\n}\n\n// ../../node_modules/d3-hierarchy/src/stratify.js\nvar preroot = { depth: -1 };\nvar ambiguous = {};\nvar imputed = {};\nfunction defaultId(d) {\n return d.id;\n}\nfunction defaultParentId(d) {\n return d.parentId;\n}\nfunction stratify_default() {\n var id2 = defaultId, parentId = defaultParentId, path2;\n function stratify(data) {\n var nodes = Array.from(data), currentId = id2, currentParentId = parentId, n, d, i, root2, parent, node, nodeId, nodeKey, nodeByKey = /* @__PURE__ */ new Map();\n if (path2 != null) {\n const I = nodes.map((d2, i2) => normalize(path2(d2, i2, data)));\n const P = I.map(parentof);\n const S = new Set(I).add(\"\");\n for (const i2 of P) {\n if (!S.has(i2)) {\n S.add(i2);\n I.push(i2);\n P.push(parentof(i2));\n nodes.push(imputed);\n }\n }\n currentId = (_, i2) => I[i2];\n currentParentId = (_, i2) => P[i2];\n }\n for (i = 0, n = nodes.length; i < n; ++i) {\n d = nodes[i], node = nodes[i] = new Node(d);\n if ((nodeId = currentId(d, i, data)) != null && (nodeId += \"\")) {\n nodeKey = node.id = nodeId;\n nodeByKey.set(nodeKey, nodeByKey.has(nodeKey) ? ambiguous : node);\n }\n if ((nodeId = currentParentId(d, i, data)) != null && (nodeId += \"\")) {\n node.parent = nodeId;\n }\n }\n for (i = 0; i < n; ++i) {\n node = nodes[i];\n if (nodeId = node.parent) {\n parent = nodeByKey.get(nodeId);\n if (!parent) throw new Error(\"missing: \" + nodeId);\n if (parent === ambiguous) throw new Error(\"ambiguous: \" + nodeId);\n if (parent.children) parent.children.push(node);\n else parent.children = [node];\n node.parent = parent;\n } else {\n if (root2) throw new Error(\"multiple roots\");\n root2 = node;\n }\n }\n if (!root2) throw new Error(\"no root\");\n if (path2 != null) {\n while (root2.data === imputed && root2.children.length === 1) {\n root2 = root2.children[0], --n;\n }\n for (let i2 = nodes.length - 1; i2 >= 0; --i2) {\n node = nodes[i2];\n if (node.data !== imputed) break;\n node.data = null;\n }\n }\n root2.parent = preroot;\n root2.eachBefore(function(node2) {\n node2.depth = node2.parent.depth + 1;\n --n;\n }).eachBefore(computeHeight);\n root2.parent = null;\n if (n > 0) throw new Error(\"cycle\");\n return root2;\n }\n stratify.id = function(x3) {\n return arguments.length ? (id2 = optional(x3), stratify) : id2;\n };\n stratify.parentId = function(x3) {\n return arguments.length ? (parentId = optional(x3), stratify) : parentId;\n };\n stratify.path = function(x3) {\n return arguments.length ? (path2 = optional(x3), stratify) : path2;\n };\n return stratify;\n}\nfunction normalize(path2) {\n path2 = `${path2}`;\n let i = path2.length;\n if (slash(path2, i - 1) && !slash(path2, i - 2)) path2 = path2.slice(0, -1);\n return path2[0] === \"/\" ? path2 : `/${path2}`;\n}\nfunction parentof(path2) {\n let i = path2.length;\n if (i < 2) return \"\";\n while (--i > 1) if (slash(path2, i)) break;\n return path2.slice(0, i);\n}\nfunction slash(path2, i) {\n if (path2[i] === \"/\") {\n let k2 = 0;\n while (i > 0 && path2[--i] === \"\\\\\") ++k2;\n if ((k2 & 1) === 0) return true;\n }\n return false;\n}\n\n// ../../node_modules/d3-hierarchy/src/tree.js\nfunction defaultSeparation2(a2, b) {\n return a2.parent === b.parent ? 1 : 2;\n}\nfunction nextLeft(v2) {\n var children2 = v2.children;\n return children2 ? children2[0] : v2.t;\n}\nfunction nextRight(v2) {\n var children2 = v2.children;\n return children2 ? children2[children2.length - 1] : v2.t;\n}\nfunction moveSubtree(wm, wp, shift) {\n var change = shift / (wp.i - wm.i);\n wp.c -= change;\n wp.s += shift;\n wm.c += change;\n wp.z += shift;\n wp.m += shift;\n}\nfunction executeShifts(v2) {\n var shift = 0, change = 0, children2 = v2.children, i = children2.length, w;\n while (--i >= 0) {\n w = children2[i];\n w.z += shift;\n w.m += shift;\n shift += w.s + (change += w.c);\n }\n}\nfunction nextAncestor(vim, v2, ancestor) {\n return vim.a.parent === v2.parent ? vim.a : ancestor;\n}\nfunction TreeNode(node, i) {\n this._ = node;\n this.parent = null;\n this.children = null;\n this.A = null;\n this.a = this;\n this.z = 0;\n this.m = 0;\n this.c = 0;\n this.s = 0;\n this.t = null;\n this.i = i;\n}\nTreeNode.prototype = Object.create(Node.prototype);\nfunction treeRoot(root2) {\n var tree2 = new TreeNode(root2, 0), node, nodes = [tree2], child, children2, i, n;\n while (node = nodes.pop()) {\n if (children2 = node._.children) {\n node.children = new Array(n = children2.length);\n for (i = n - 1; i >= 0; --i) {\n nodes.push(child = node.children[i] = new TreeNode(children2[i], i));\n child.parent = node;\n }\n }\n }\n (tree2.parent = new TreeNode(null, 0)).children = [tree2];\n return tree2;\n}\nfunction tree_default() {\n var separation = defaultSeparation2, dx = 1, dy = 1, nodeSize = null;\n function tree2(root2) {\n var t = treeRoot(root2);\n t.eachAfter(firstWalk), t.parent.m = -t.z;\n t.eachBefore(secondWalk);\n if (nodeSize) root2.eachBefore(sizeNode);\n else {\n var left2 = root2, right2 = root2, bottom2 = root2;\n root2.eachBefore(function(node) {\n if (node.x < left2.x) left2 = node;\n if (node.x > right2.x) right2 = node;\n if (node.depth > bottom2.depth) bottom2 = node;\n });\n var s2 = left2 === right2 ? 1 : separation(left2, right2) / 2, tx = s2 - left2.x, kx2 = dx / (right2.x + s2 + tx), ky2 = dy / (bottom2.depth || 1);\n root2.eachBefore(function(node) {\n node.x = (node.x + tx) * kx2;\n node.y = node.depth * ky2;\n });\n }\n return root2;\n }\n function firstWalk(v2) {\n var children2 = v2.children, siblings = v2.parent.children, w = v2.i ? siblings[v2.i - 1] : null;\n if (children2) {\n executeShifts(v2);\n var midpoint = (children2[0].z + children2[children2.length - 1].z) / 2;\n if (w) {\n v2.z = w.z + separation(v2._, w._);\n v2.m = v2.z - midpoint;\n } else {\n v2.z = midpoint;\n }\n } else if (w) {\n v2.z = w.z + separation(v2._, w._);\n }\n v2.parent.A = apportion(v2, w, v2.parent.A || siblings[0]);\n }\n function secondWalk(v2) {\n v2._.x = v2.z + v2.parent.m;\n v2.m += v2.parent.m;\n }\n function apportion(v2, w, ancestor) {\n if (w) {\n var vip = v2, vop = v2, vim = w, vom = vip.parent.children[0], sip = vip.m, sop = vop.m, sim = vim.m, som = vom.m, shift;\n while (vim = nextRight(vim), vip = nextLeft(vip), vim && vip) {\n vom = nextLeft(vom);\n vop = nextRight(vop);\n vop.a = v2;\n shift = vim.z + sim - vip.z - sip + separation(vim._, vip._);\n if (shift > 0) {\n moveSubtree(nextAncestor(vim, v2, ancestor), v2, shift);\n sip += shift;\n sop += shift;\n }\n sim += vim.m;\n sip += vip.m;\n som += vom.m;\n sop += vop.m;\n }\n if (vim && !nextRight(vop)) {\n vop.t = vim;\n vop.m += sim - sop;\n }\n if (vip && !nextLeft(vom)) {\n vom.t = vip;\n vom.m += sip - som;\n ancestor = v2;\n }\n }\n return ancestor;\n }\n function sizeNode(node) {\n node.x *= dx;\n node.y = node.depth * dy;\n }\n tree2.separation = function(x3) {\n return arguments.length ? (separation = x3, tree2) : separation;\n };\n tree2.size = function(x3) {\n return arguments.length ? (nodeSize = false, dx = +x3[0], dy = +x3[1], tree2) : nodeSize ? null : [dx, dy];\n };\n tree2.nodeSize = function(x3) {\n return arguments.length ? (nodeSize = true, dx = +x3[0], dy = +x3[1], tree2) : nodeSize ? [dx, dy] : null;\n };\n return tree2;\n}\n\n// ../../node_modules/d3-random/src/lcg.js\nvar mul = 1664525;\nvar inc = 1013904223;\nvar eps = 1 / 4294967296;\nfunction lcg(seed = Math.random()) {\n let state = (0 <= seed && seed < 1 ? seed / eps : Math.abs(seed)) | 0;\n return () => (state = mul * state + inc | 0, eps * (state >>> 0));\n}\n\n// ../../node_modules/d3-scale/src/init.js\nfunction initRange(domain, range3) {\n switch (arguments.length) {\n case 0:\n break;\n case 1:\n this.range(domain);\n break;\n default:\n this.range(range3).domain(domain);\n break;\n }\n return this;\n}\nfunction initInterpolator(domain, interpolator) {\n switch (arguments.length) {\n case 0:\n break;\n case 1: {\n if (typeof domain === \"function\") this.interpolator(domain);\n else this.range(domain);\n break;\n }\n default: {\n this.domain(domain);\n if (typeof interpolator === \"function\") this.interpolator(interpolator);\n else this.range(interpolator);\n break;\n }\n }\n return this;\n}\n\n// ../../node_modules/d3-scale/src/ordinal.js\nvar implicit = Symbol(\"implicit\");\nfunction ordinal() {\n var index2 = new InternMap(), domain = [], range3 = [], unknown = implicit;\n function scale3(d) {\n let i = index2.get(d);\n if (i === void 0) {\n if (unknown !== implicit) return unknown;\n index2.set(d, i = domain.push(d) - 1);\n }\n return range3[i % range3.length];\n }\n scale3.domain = function(_) {\n if (!arguments.length) return domain.slice();\n domain = [], index2 = new InternMap();\n for (const value of _) {\n if (index2.has(value)) continue;\n index2.set(value, domain.push(value) - 1);\n }\n return scale3;\n };\n scale3.range = function(_) {\n return arguments.length ? (range3 = Array.from(_), scale3) : range3.slice();\n };\n scale3.unknown = function(_) {\n return arguments.length ? (unknown = _, scale3) : unknown;\n };\n scale3.copy = function() {\n return ordinal(domain, range3).unknown(unknown);\n };\n initRange.apply(scale3, arguments);\n return scale3;\n}\n\n// ../../node_modules/d3-scale/src/band.js\nfunction band() {\n var scale3 = ordinal().unknown(void 0), domain = scale3.domain, ordinalRange2 = scale3.range, r0 = 0, r1 = 1, step, bandwidth, round2 = false, paddingInner = 0, paddingOuter = 0, align3 = 0.5;\n delete scale3.unknown;\n function rescale() {\n var n = domain().length, reverse3 = r1 < r0, start2 = reverse3 ? r1 : r0, stop = reverse3 ? r0 : r1;\n step = (stop - start2) / Math.max(1, n - paddingInner + paddingOuter * 2);\n if (round2) step = Math.floor(step);\n start2 += (stop - start2 - step * (n - paddingInner)) * align3;\n bandwidth = step * (1 - paddingInner);\n if (round2) start2 = Math.round(start2), bandwidth = Math.round(bandwidth);\n var values2 = range(n).map(function(i) {\n return start2 + step * i;\n });\n return ordinalRange2(reverse3 ? values2.reverse() : values2);\n }\n scale3.domain = function(_) {\n return arguments.length ? (domain(_), rescale()) : domain();\n };\n scale3.range = function(_) {\n return arguments.length ? ([r0, r1] = _, r0 = +r0, r1 = +r1, rescale()) : [r0, r1];\n };\n scale3.rangeRound = function(_) {\n return [r0, r1] = _, r0 = +r0, r1 = +r1, round2 = true, rescale();\n };\n scale3.bandwidth = function() {\n return bandwidth;\n };\n scale3.step = function() {\n return step;\n };\n scale3.round = function(_) {\n return arguments.length ? (round2 = !!_, rescale()) : round2;\n };\n scale3.padding = function(_) {\n return arguments.length ? (paddingInner = Math.min(1, paddingOuter = +_), rescale()) : paddingInner;\n };\n scale3.paddingInner = function(_) {\n return arguments.length ? (paddingInner = Math.min(1, _), rescale()) : paddingInner;\n };\n scale3.paddingOuter = function(_) {\n return arguments.length ? (paddingOuter = +_, rescale()) : paddingOuter;\n };\n scale3.align = function(_) {\n return arguments.length ? (align3 = Math.max(0, Math.min(1, _)), rescale()) : align3;\n };\n scale3.copy = function() {\n return band(domain(), [r0, r1]).round(round2).paddingInner(paddingInner).paddingOuter(paddingOuter).align(align3);\n };\n return initRange.apply(rescale(), arguments);\n}\nfunction pointish(scale3) {\n var copy4 = scale3.copy;\n scale3.padding = scale3.paddingOuter;\n delete scale3.paddingInner;\n delete scale3.paddingOuter;\n scale3.copy = function() {\n return pointish(copy4());\n };\n return scale3;\n}\nfunction point() {\n return pointish(band.apply(null, arguments).paddingInner(1));\n}\n\n// ../../node_modules/d3-scale/src/constant.js\nfunction constants(x3) {\n return function() {\n return x3;\n };\n}\n\n// ../../node_modules/d3-scale/src/number.js\nfunction number3(x3) {\n return +x3;\n}\n\n// ../../node_modules/d3-scale/src/continuous.js\nvar unit = [0, 1];\nfunction identity4(x3) {\n return x3;\n}\nfunction normalize2(a2, b) {\n return (b -= a2 = +a2) ? function(x3) {\n return (x3 - a2) / b;\n } : constants(isNaN(b) ? NaN : 0.5);\n}\nfunction clamper(a2, b) {\n var t;\n if (a2 > b) t = a2, a2 = b, b = t;\n return function(x3) {\n return Math.max(a2, Math.min(b, x3));\n };\n}\nfunction bimap(domain, range3, interpolate) {\n var d0 = domain[0], d1 = domain[1], r0 = range3[0], r1 = range3[1];\n if (d1 < d0) d0 = normalize2(d1, d0), r0 = interpolate(r1, r0);\n else d0 = normalize2(d0, d1), r0 = interpolate(r0, r1);\n return function(x3) {\n return r0(d0(x3));\n };\n}\nfunction polymap(domain, range3, interpolate) {\n var j = Math.min(domain.length, range3.length) - 1, d = new Array(j), r = new Array(j), i = -1;\n if (domain[j] < domain[0]) {\n domain = domain.slice().reverse();\n range3 = range3.slice().reverse();\n }\n while (++i < j) {\n d[i] = normalize2(domain[i], domain[i + 1]);\n r[i] = interpolate(range3[i], range3[i + 1]);\n }\n return function(x3) {\n var i2 = bisect_default(domain, x3, 1, j) - 1;\n return r[i2](d[i2](x3));\n };\n}\nfunction copy(source, target) {\n return target.domain(source.domain()).range(source.range()).interpolate(source.interpolate()).clamp(source.clamp()).unknown(source.unknown());\n}\nfunction transformer2() {\n var domain = unit, range3 = unit, interpolate = value_default, transform3, untransform, unknown, clamp = identity4, piecewise2, output, input3;\n function rescale() {\n var n = Math.min(domain.length, range3.length);\n if (clamp !== identity4) clamp = clamper(domain[0], domain[n - 1]);\n piecewise2 = n > 2 ? polymap : bimap;\n output = input3 = null;\n return scale3;\n }\n function scale3(x3) {\n return x3 == null || isNaN(x3 = +x3) ? unknown : (output || (output = piecewise2(domain.map(transform3), range3, interpolate)))(transform3(clamp(x3)));\n }\n scale3.invert = function(y3) {\n return clamp(untransform((input3 || (input3 = piecewise2(range3, domain.map(transform3), number_default)))(y3)));\n };\n scale3.domain = function(_) {\n return arguments.length ? (domain = Array.from(_, number3), rescale()) : domain.slice();\n };\n scale3.range = function(_) {\n return arguments.length ? (range3 = Array.from(_), rescale()) : range3.slice();\n };\n scale3.rangeRound = function(_) {\n return range3 = Array.from(_), interpolate = round_default, rescale();\n };\n scale3.clamp = function(_) {\n return arguments.length ? (clamp = _ ? true : identity4, rescale()) : clamp !== identity4;\n };\n scale3.interpolate = function(_) {\n return arguments.length ? (interpolate = _, rescale()) : interpolate;\n };\n scale3.unknown = function(_) {\n return arguments.length ? (unknown = _, scale3) : unknown;\n };\n return function(t, u4) {\n transform3 = t, untransform = u4;\n return rescale();\n };\n}\nfunction continuous() {\n return transformer2()(identity4, identity4);\n}\n\n// ../../node_modules/d3-scale/src/tickFormat.js\nfunction tickFormat(start2, stop, count4, specifier) {\n var step = tickStep(start2, stop, count4), precision;\n specifier = formatSpecifier(specifier == null ? \",f\" : specifier);\n switch (specifier.type) {\n case \"s\": {\n var value = Math.max(Math.abs(start2), Math.abs(stop));\n if (specifier.precision == null && !isNaN(precision = precisionPrefix_default(step, value))) specifier.precision = precision;\n return formatPrefix(specifier, value);\n }\n case \"\":\n case \"e\":\n case \"g\":\n case \"p\":\n case \"r\": {\n if (specifier.precision == null && !isNaN(precision = precisionRound_default(step, Math.max(Math.abs(start2), Math.abs(stop))))) specifier.precision = precision - (specifier.type === \"e\");\n break;\n }\n case \"f\":\n case \"%\": {\n if (specifier.precision == null && !isNaN(precision = precisionFixed_default(step))) specifier.precision = precision - (specifier.type === \"%\") * 2;\n break;\n }\n }\n return format(specifier);\n}\n\n// ../../node_modules/d3-scale/src/linear.js\nfunction linearish(scale3) {\n var domain = scale3.domain;\n scale3.ticks = function(count4) {\n var d = domain();\n return ticks(d[0], d[d.length - 1], count4 == null ? 10 : count4);\n };\n scale3.tickFormat = function(count4, specifier) {\n var d = domain();\n return tickFormat(d[0], d[d.length - 1], count4 == null ? 10 : count4, specifier);\n };\n scale3.nice = function(count4) {\n if (count4 == null) count4 = 10;\n var d = domain();\n var i0 = 0;\n var i1 = d.length - 1;\n var start2 = d[i0];\n var stop = d[i1];\n var prestep;\n var step;\n var maxIter = 10;\n if (stop < start2) {\n step = start2, start2 = stop, stop = step;\n step = i0, i0 = i1, i1 = step;\n }\n while (maxIter-- > 0) {\n step = tickIncrement(start2, stop, count4);\n if (step === prestep) {\n d[i0] = start2;\n d[i1] = stop;\n return domain(d);\n } else if (step > 0) {\n start2 = Math.floor(start2 / step) * step;\n stop = Math.ceil(stop / step) * step;\n } else if (step < 0) {\n start2 = Math.ceil(start2 * step) / step;\n stop = Math.floor(stop * step) / step;\n } else {\n break;\n }\n prestep = step;\n }\n return scale3;\n };\n return scale3;\n}\nfunction linear2() {\n var scale3 = continuous();\n scale3.copy = function() {\n return copy(scale3, linear2());\n };\n initRange.apply(scale3, arguments);\n return linearish(scale3);\n}\n\n// ../../node_modules/d3-scale/src/identity.js\nfunction identity5(domain) {\n var unknown;\n function scale3(x3) {\n return x3 == null || isNaN(x3 = +x3) ? unknown : x3;\n }\n scale3.invert = scale3;\n scale3.domain = scale3.range = function(_) {\n return arguments.length ? (domain = Array.from(_, number3), scale3) : domain.slice();\n };\n scale3.unknown = function(_) {\n return arguments.length ? (unknown = _, scale3) : unknown;\n };\n scale3.copy = function() {\n return identity5(domain).unknown(unknown);\n };\n domain = arguments.length ? Array.from(domain, number3) : [0, 1];\n return linearish(scale3);\n}\n\n// ../../node_modules/d3-scale/src/nice.js\nfunction nice2(domain, interval3) {\n domain = domain.slice();\n var i0 = 0, i1 = domain.length - 1, x06 = domain[i0], x12 = domain[i1], t;\n if (x12 < x06) {\n t = i0, i0 = i1, i1 = t;\n t = x06, x06 = x12, x12 = t;\n }\n domain[i0] = interval3.floor(x06);\n domain[i1] = interval3.ceil(x12);\n return domain;\n}\n\n// ../../node_modules/d3-scale/src/log.js\nfunction transformLog(x3) {\n return Math.log(x3);\n}\nfunction transformExp(x3) {\n return Math.exp(x3);\n}\nfunction transformLogn(x3) {\n return -Math.log(-x3);\n}\nfunction transformExpn(x3) {\n return -Math.exp(-x3);\n}\nfunction pow10(x3) {\n return isFinite(x3) ? +(\"1e\" + x3) : x3 < 0 ? 0 : x3;\n}\nfunction powp(base) {\n return base === 10 ? pow10 : base === Math.E ? Math.exp : (x3) => Math.pow(base, x3);\n}\nfunction logp(base) {\n return base === Math.E ? Math.log : base === 10 && Math.log10 || base === 2 && Math.log2 || (base = Math.log(base), (x3) => Math.log(x3) / base);\n}\nfunction reflect(f) {\n return (x3, k2) => -f(-x3, k2);\n}\nfunction loggish(transform3) {\n const scale3 = transform3(transformLog, transformExp);\n const domain = scale3.domain;\n let base = 10;\n let logs;\n let pows;\n function rescale() {\n logs = logp(base), pows = powp(base);\n if (domain()[0] < 0) {\n logs = reflect(logs), pows = reflect(pows);\n transform3(transformLogn, transformExpn);\n } else {\n transform3(transformLog, transformExp);\n }\n return scale3;\n }\n scale3.base = function(_) {\n return arguments.length ? (base = +_, rescale()) : base;\n };\n scale3.domain = function(_) {\n return arguments.length ? (domain(_), rescale()) : domain();\n };\n scale3.ticks = (count4) => {\n const d = domain();\n let u4 = d[0];\n let v2 = d[d.length - 1];\n const r = v2 < u4;\n if (r) [u4, v2] = [v2, u4];\n let i = logs(u4);\n let j = logs(v2);\n let k2;\n let t;\n const n = count4 == null ? 10 : +count4;\n let z = [];\n if (!(base % 1) && j - i < n) {\n i = Math.floor(i), j = Math.ceil(j);\n if (u4 > 0) for (; i <= j; ++i) {\n for (k2 = 1; k2 < base; ++k2) {\n t = i < 0 ? k2 / pows(-i) : k2 * pows(i);\n if (t < u4) continue;\n if (t > v2) break;\n z.push(t);\n }\n }\n else for (; i <= j; ++i) {\n for (k2 = base - 1; k2 >= 1; --k2) {\n t = i > 0 ? k2 / pows(-i) : k2 * pows(i);\n if (t < u4) continue;\n if (t > v2) break;\n z.push(t);\n }\n }\n if (z.length * 2 < n) z = ticks(u4, v2, n);\n } else {\n z = ticks(i, j, Math.min(j - i, n)).map(pows);\n }\n return r ? z.reverse() : z;\n };\n scale3.tickFormat = (count4, specifier) => {\n if (count4 == null) count4 = 10;\n if (specifier == null) specifier = base === 10 ? \"s\" : \",\";\n if (typeof specifier !== \"function\") {\n if (!(base % 1) && (specifier = formatSpecifier(specifier)).precision == null) specifier.trim = true;\n specifier = format(specifier);\n }\n if (count4 === Infinity) return specifier;\n const k2 = Math.max(1, base * count4 / scale3.ticks().length);\n return (d) => {\n let i = d / pows(Math.round(logs(d)));\n if (i * base < base - 0.5) i *= base;\n return i <= k2 ? specifier(d) : \"\";\n };\n };\n scale3.nice = () => {\n return domain(nice2(domain(), {\n floor: (x3) => pows(Math.floor(logs(x3))),\n ceil: (x3) => pows(Math.ceil(logs(x3)))\n }));\n };\n return scale3;\n}\nfunction log2() {\n const scale3 = loggish(transformer2()).domain([1, 10]);\n scale3.copy = () => copy(scale3, log2()).base(scale3.base());\n initRange.apply(scale3, arguments);\n return scale3;\n}\n\n// ../../node_modules/d3-scale/src/symlog.js\nfunction transformSymlog(c4) {\n return function(x3) {\n return Math.sign(x3) * Math.log1p(Math.abs(x3 / c4));\n };\n}\nfunction transformSymexp(c4) {\n return function(x3) {\n return Math.sign(x3) * Math.expm1(Math.abs(x3)) * c4;\n };\n}\nfunction symlogish(transform3) {\n var c4 = 1, scale3 = transform3(transformSymlog(c4), transformSymexp(c4));\n scale3.constant = function(_) {\n return arguments.length ? transform3(transformSymlog(c4 = +_), transformSymexp(c4)) : c4;\n };\n return linearish(scale3);\n}\nfunction symlog() {\n var scale3 = symlogish(transformer2());\n scale3.copy = function() {\n return copy(scale3, symlog()).constant(scale3.constant());\n };\n return initRange.apply(scale3, arguments);\n}\n\n// ../../node_modules/d3-scale/src/pow.js\nfunction transformPow(exponent) {\n return function(x3) {\n return x3 < 0 ? -Math.pow(-x3, exponent) : Math.pow(x3, exponent);\n };\n}\nfunction transformSqrt(x3) {\n return x3 < 0 ? -Math.sqrt(-x3) : Math.sqrt(x3);\n}\nfunction transformSquare(x3) {\n return x3 < 0 ? -x3 * x3 : x3 * x3;\n}\nfunction powish(transform3) {\n var scale3 = transform3(identity4, identity4), exponent = 1;\n function rescale() {\n return exponent === 1 ? transform3(identity4, identity4) : exponent === 0.5 ? transform3(transformSqrt, transformSquare) : transform3(transformPow(exponent), transformPow(1 / exponent));\n }\n scale3.exponent = function(_) {\n return arguments.length ? (exponent = +_, rescale()) : exponent;\n };\n return linearish(scale3);\n}\nfunction pow3() {\n var scale3 = powish(transformer2());\n scale3.copy = function() {\n return copy(scale3, pow3()).exponent(scale3.exponent());\n };\n initRange.apply(scale3, arguments);\n return scale3;\n}\n\n// ../../node_modules/d3-scale/src/quantile.js\nfunction quantile3() {\n var domain = [], range3 = [], thresholds = [], unknown;\n function rescale() {\n var i = 0, n = Math.max(1, range3.length);\n thresholds = new Array(n - 1);\n while (++i < n) thresholds[i - 1] = quantileSorted(domain, i / n);\n return scale3;\n }\n function scale3(x3) {\n return x3 == null || isNaN(x3 = +x3) ? unknown : range3[bisect_default(thresholds, x3)];\n }\n scale3.invertExtent = function(y3) {\n var i = range3.indexOf(y3);\n return i < 0 ? [NaN, NaN] : [\n i > 0 ? thresholds[i - 1] : domain[0],\n i < thresholds.length ? thresholds[i] : domain[domain.length - 1]\n ];\n };\n scale3.domain = function(_) {\n if (!arguments.length) return domain.slice();\n domain = [];\n for (let d of _) if (d != null && !isNaN(d = +d)) domain.push(d);\n domain.sort(ascending);\n return rescale();\n };\n scale3.range = function(_) {\n return arguments.length ? (range3 = Array.from(_), rescale()) : range3.slice();\n };\n scale3.unknown = function(_) {\n return arguments.length ? (unknown = _, scale3) : unknown;\n };\n scale3.quantiles = function() {\n return thresholds.slice();\n };\n scale3.copy = function() {\n return quantile3().domain(domain).range(range3).unknown(unknown);\n };\n return initRange.apply(scale3, arguments);\n}\n\n// ../../node_modules/d3-scale/src/threshold.js\nfunction threshold() {\n var domain = [0.5], range3 = [0, 1], unknown, n = 1;\n function scale3(x3) {\n return x3 != null && x3 <= x3 ? range3[bisect_default(domain, x3, 0, n)] : unknown;\n }\n scale3.domain = function(_) {\n return arguments.length ? (domain = Array.from(_), n = Math.min(domain.length, range3.length - 1), scale3) : domain.slice();\n };\n scale3.range = function(_) {\n return arguments.length ? (range3 = Array.from(_), n = Math.min(domain.length, range3.length - 1), scale3) : range3.slice();\n };\n scale3.invertExtent = function(y3) {\n var i = range3.indexOf(y3);\n return [domain[i - 1], domain[i]];\n };\n scale3.unknown = function(_) {\n return arguments.length ? (unknown = _, scale3) : unknown;\n };\n scale3.copy = function() {\n return threshold().domain(domain).range(range3).unknown(unknown);\n };\n return initRange.apply(scale3, arguments);\n}\n\n// ../../node_modules/d3-time/src/interval.js\nvar t02 = /* @__PURE__ */ new Date();\nvar t12 = /* @__PURE__ */ new Date();\nfunction timeInterval(floori, offseti, count4, field3) {\n function interval3(date3) {\n return floori(date3 = arguments.length === 0 ? /* @__PURE__ */ new Date() : /* @__PURE__ */ new Date(+date3)), date3;\n }\n interval3.floor = (date3) => {\n return floori(date3 = /* @__PURE__ */ new Date(+date3)), date3;\n };\n interval3.ceil = (date3) => {\n return floori(date3 = new Date(date3 - 1)), offseti(date3, 1), floori(date3), date3;\n };\n interval3.round = (date3) => {\n const d0 = interval3(date3), d1 = interval3.ceil(date3);\n return date3 - d0 < d1 - date3 ? d0 : d1;\n };\n interval3.offset = (date3, step) => {\n return offseti(date3 = /* @__PURE__ */ new Date(+date3), step == null ? 1 : Math.floor(step)), date3;\n };\n interval3.range = (start2, stop, step) => {\n const range3 = [];\n start2 = interval3.ceil(start2);\n step = step == null ? 1 : Math.floor(step);\n if (!(start2 < stop) || !(step > 0)) return range3;\n let previous;\n do\n range3.push(previous = /* @__PURE__ */ new Date(+start2)), offseti(start2, step), floori(start2);\n while (previous < start2 && start2 < stop);\n return range3;\n };\n interval3.filter = (test) => {\n return timeInterval((date3) => {\n if (date3 >= date3) while (floori(date3), !test(date3)) date3.setTime(date3 - 1);\n }, (date3, step) => {\n if (date3 >= date3) {\n if (step < 0) while (++step <= 0) {\n while (offseti(date3, -1), !test(date3)) {\n }\n }\n else while (--step >= 0) {\n while (offseti(date3, 1), !test(date3)) {\n }\n }\n }\n });\n };\n if (count4) {\n interval3.count = (start2, end) => {\n t02.setTime(+start2), t12.setTime(+end);\n floori(t02), floori(t12);\n return Math.floor(count4(t02, t12));\n };\n interval3.every = (step) => {\n step = Math.floor(step);\n return !isFinite(step) || !(step > 0) ? null : !(step > 1) ? interval3 : interval3.filter(field3 ? (d) => field3(d) % step === 0 : (d) => interval3.count(0, d) % step === 0);\n };\n }\n return interval3;\n}\n\n// ../../node_modules/d3-time/src/millisecond.js\nvar millisecond = timeInterval(() => {\n}, (date3, step) => {\n date3.setTime(+date3 + step);\n}, (start2, end) => {\n return end - start2;\n});\nmillisecond.every = (k2) => {\n k2 = Math.floor(k2);\n if (!isFinite(k2) || !(k2 > 0)) return null;\n if (!(k2 > 1)) return millisecond;\n return timeInterval((date3) => {\n date3.setTime(Math.floor(date3 / k2) * k2);\n }, (date3, step) => {\n date3.setTime(+date3 + step * k2);\n }, (start2, end) => {\n return (end - start2) / k2;\n });\n};\nvar milliseconds = millisecond.range;\n\n// ../../node_modules/d3-time/src/duration.js\nvar durationSecond = 1e3;\nvar durationMinute = durationSecond * 60;\nvar durationHour = durationMinute * 60;\nvar durationDay = durationHour * 24;\nvar durationWeek = durationDay * 7;\nvar durationMonth = durationDay * 30;\nvar durationYear = durationDay * 365;\n\n// ../../node_modules/d3-time/src/second.js\nvar second = timeInterval((date3) => {\n date3.setTime(date3 - date3.getMilliseconds());\n}, (date3, step) => {\n date3.setTime(+date3 + step * durationSecond);\n}, (start2, end) => {\n return (end - start2) / durationSecond;\n}, (date3) => {\n return date3.getUTCSeconds();\n});\nvar seconds = second.range;\n\n// ../../node_modules/d3-time/src/minute.js\nvar timeMinute = timeInterval((date3) => {\n date3.setTime(date3 - date3.getMilliseconds() - date3.getSeconds() * durationSecond);\n}, (date3, step) => {\n date3.setTime(+date3 + step * durationMinute);\n}, (start2, end) => {\n return (end - start2) / durationMinute;\n}, (date3) => {\n return date3.getMinutes();\n});\nvar timeMinutes = timeMinute.range;\nvar utcMinute = timeInterval((date3) => {\n date3.setUTCSeconds(0, 0);\n}, (date3, step) => {\n date3.setTime(+date3 + step * durationMinute);\n}, (start2, end) => {\n return (end - start2) / durationMinute;\n}, (date3) => {\n return date3.getUTCMinutes();\n});\nvar utcMinutes = utcMinute.range;\n\n// ../../node_modules/d3-time/src/hour.js\nvar timeHour = timeInterval((date3) => {\n date3.setTime(date3 - date3.getMilliseconds() - date3.getSeconds() * durationSecond - date3.getMinutes() * durationMinute);\n}, (date3, step) => {\n date3.setTime(+date3 + step * durationHour);\n}, (start2, end) => {\n return (end - start2) / durationHour;\n}, (date3) => {\n return date3.getHours();\n});\nvar timeHours = timeHour.range;\nvar utcHour = timeInterval((date3) => {\n date3.setUTCMinutes(0, 0, 0);\n}, (date3, step) => {\n date3.setTime(+date3 + step * durationHour);\n}, (start2, end) => {\n return (end - start2) / durationHour;\n}, (date3) => {\n return date3.getUTCHours();\n});\nvar utcHours = utcHour.range;\n\n// ../../node_modules/d3-time/src/day.js\nvar timeDay = timeInterval(\n (date3) => date3.setHours(0, 0, 0, 0),\n (date3, step) => date3.setDate(date3.getDate() + step),\n (start2, end) => (end - start2 - (end.getTimezoneOffset() - start2.getTimezoneOffset()) * durationMinute) / durationDay,\n (date3) => date3.getDate() - 1\n);\nvar timeDays = timeDay.range;\nvar utcDay = timeInterval((date3) => {\n date3.setUTCHours(0, 0, 0, 0);\n}, (date3, step) => {\n date3.setUTCDate(date3.getUTCDate() + step);\n}, (start2, end) => {\n return (end - start2) / durationDay;\n}, (date3) => {\n return date3.getUTCDate() - 1;\n});\nvar utcDays = utcDay.range;\nvar unixDay = timeInterval((date3) => {\n date3.setUTCHours(0, 0, 0, 0);\n}, (date3, step) => {\n date3.setUTCDate(date3.getUTCDate() + step);\n}, (start2, end) => {\n return (end - start2) / durationDay;\n}, (date3) => {\n return Math.floor(date3 / durationDay);\n});\nvar unixDays = unixDay.range;\n\n// ../../node_modules/d3-time/src/week.js\nfunction timeWeekday(i) {\n return timeInterval((date3) => {\n date3.setDate(date3.getDate() - (date3.getDay() + 7 - i) % 7);\n date3.setHours(0, 0, 0, 0);\n }, (date3, step) => {\n date3.setDate(date3.getDate() + step * 7);\n }, (start2, end) => {\n return (end - start2 - (end.getTimezoneOffset() - start2.getTimezoneOffset()) * durationMinute) / durationWeek;\n });\n}\nvar timeSunday = timeWeekday(0);\nvar timeMonday = timeWeekday(1);\nvar timeTuesday = timeWeekday(2);\nvar timeWednesday = timeWeekday(3);\nvar timeThursday = timeWeekday(4);\nvar timeFriday = timeWeekday(5);\nvar timeSaturday = timeWeekday(6);\nvar timeSundays = timeSunday.range;\nvar timeMondays = timeMonday.range;\nvar timeTuesdays = timeTuesday.range;\nvar timeWednesdays = timeWednesday.range;\nvar timeThursdays = timeThursday.range;\nvar timeFridays = timeFriday.range;\nvar timeSaturdays = timeSaturday.range;\nfunction utcWeekday(i) {\n return timeInterval((date3) => {\n date3.setUTCDate(date3.getUTCDate() - (date3.getUTCDay() + 7 - i) % 7);\n date3.setUTCHours(0, 0, 0, 0);\n }, (date3, step) => {\n date3.setUTCDate(date3.getUTCDate() + step * 7);\n }, (start2, end) => {\n return (end - start2) / durationWeek;\n });\n}\nvar utcSunday = utcWeekday(0);\nvar utcMonday = utcWeekday(1);\nvar utcTuesday = utcWeekday(2);\nvar utcWednesday = utcWeekday(3);\nvar utcThursday = utcWeekday(4);\nvar utcFriday = utcWeekday(5);\nvar utcSaturday = utcWeekday(6);\nvar utcSundays = utcSunday.range;\nvar utcMondays = utcMonday.range;\nvar utcTuesdays = utcTuesday.range;\nvar utcWednesdays = utcWednesday.range;\nvar utcThursdays = utcThursday.range;\nvar utcFridays = utcFriday.range;\nvar utcSaturdays = utcSaturday.range;\n\n// ../../node_modules/d3-time/src/month.js\nvar timeMonth = timeInterval((date3) => {\n date3.setDate(1);\n date3.setHours(0, 0, 0, 0);\n}, (date3, step) => {\n date3.setMonth(date3.getMonth() + step);\n}, (start2, end) => {\n return end.getMonth() - start2.getMonth() + (end.getFullYear() - start2.getFullYear()) * 12;\n}, (date3) => {\n return date3.getMonth();\n});\nvar timeMonths = timeMonth.range;\nvar utcMonth = timeInterval((date3) => {\n date3.setUTCDate(1);\n date3.setUTCHours(0, 0, 0, 0);\n}, (date3, step) => {\n date3.setUTCMonth(date3.getUTCMonth() + step);\n}, (start2, end) => {\n return end.getUTCMonth() - start2.getUTCMonth() + (end.getUTCFullYear() - start2.getUTCFullYear()) * 12;\n}, (date3) => {\n return date3.getUTCMonth();\n});\nvar utcMonths = utcMonth.range;\n\n// ../../node_modules/d3-time/src/year.js\nvar timeYear = timeInterval((date3) => {\n date3.setMonth(0, 1);\n date3.setHours(0, 0, 0, 0);\n}, (date3, step) => {\n date3.setFullYear(date3.getFullYear() + step);\n}, (start2, end) => {\n return end.getFullYear() - start2.getFullYear();\n}, (date3) => {\n return date3.getFullYear();\n});\ntimeYear.every = (k2) => {\n return !isFinite(k2 = Math.floor(k2)) || !(k2 > 0) ? null : timeInterval((date3) => {\n date3.setFullYear(Math.floor(date3.getFullYear() / k2) * k2);\n date3.setMonth(0, 1);\n date3.setHours(0, 0, 0, 0);\n }, (date3, step) => {\n date3.setFullYear(date3.getFullYear() + step * k2);\n });\n};\nvar timeYears = timeYear.range;\nvar utcYear = timeInterval((date3) => {\n date3.setUTCMonth(0, 1);\n date3.setUTCHours(0, 0, 0, 0);\n}, (date3, step) => {\n date3.setUTCFullYear(date3.getUTCFullYear() + step);\n}, (start2, end) => {\n return end.getUTCFullYear() - start2.getUTCFullYear();\n}, (date3) => {\n return date3.getUTCFullYear();\n});\nutcYear.every = (k2) => {\n return !isFinite(k2 = Math.floor(k2)) || !(k2 > 0) ? null : timeInterval((date3) => {\n date3.setUTCFullYear(Math.floor(date3.getUTCFullYear() / k2) * k2);\n date3.setUTCMonth(0, 1);\n date3.setUTCHours(0, 0, 0, 0);\n }, (date3, step) => {\n date3.setUTCFullYear(date3.getUTCFullYear() + step * k2);\n });\n};\nvar utcYears = utcYear.range;\n\n// ../../node_modules/d3-time/src/ticks.js\nfunction ticker(year, month, week, day, hour, minute) {\n const tickIntervals2 = [\n [second, 1, durationSecond],\n [second, 5, 5 * durationSecond],\n [second, 15, 15 * durationSecond],\n [second, 30, 30 * durationSecond],\n [minute, 1, durationMinute],\n [minute, 5, 5 * durationMinute],\n [minute, 15, 15 * durationMinute],\n [minute, 30, 30 * durationMinute],\n [hour, 1, durationHour],\n [hour, 3, 3 * durationHour],\n [hour, 6, 6 * durationHour],\n [hour, 12, 12 * durationHour],\n [day, 1, durationDay],\n [day, 2, 2 * durationDay],\n [week, 1, durationWeek],\n [month, 1, durationMonth],\n [month, 3, 3 * durationMonth],\n [year, 1, durationYear]\n ];\n function ticks2(start2, stop, count4) {\n const reverse3 = stop < start2;\n if (reverse3) [start2, stop] = [stop, start2];\n const interval3 = count4 && typeof count4.range === \"function\" ? count4 : tickInterval(start2, stop, count4);\n const ticks3 = interval3 ? interval3.range(start2, +stop + 1) : [];\n return reverse3 ? ticks3.reverse() : ticks3;\n }\n function tickInterval(start2, stop, count4) {\n const target = Math.abs(stop - start2) / count4;\n const i = bisector(([, , step2]) => step2).right(tickIntervals2, target);\n if (i === tickIntervals2.length) return year.every(tickStep(start2 / durationYear, stop / durationYear, count4));\n if (i === 0) return millisecond.every(Math.max(tickStep(start2, stop, count4), 1));\n const [t, step] = tickIntervals2[target / tickIntervals2[i - 1][2] < tickIntervals2[i][2] / target ? i - 1 : i];\n return t.every(step);\n }\n return [ticks2, tickInterval];\n}\nvar [utcTicks, utcTickInterval] = ticker(utcYear, utcMonth, utcSunday, unixDay, utcHour, utcMinute);\nvar [timeTicks, timeTickInterval] = ticker(timeYear, timeMonth, timeSunday, timeDay, timeHour, timeMinute);\n\n// ../../node_modules/d3-time-format/src/locale.js\nfunction localDate(d) {\n if (0 <= d.y && d.y < 100) {\n var date3 = new Date(-1, d.m, d.d, d.H, d.M, d.S, d.L);\n date3.setFullYear(d.y);\n return date3;\n }\n return new Date(d.y, d.m, d.d, d.H, d.M, d.S, d.L);\n}\nfunction utcDate(d) {\n if (0 <= d.y && d.y < 100) {\n var date3 = new Date(Date.UTC(-1, d.m, d.d, d.H, d.M, d.S, d.L));\n date3.setUTCFullYear(d.y);\n return date3;\n }\n return new Date(Date.UTC(d.y, d.m, d.d, d.H, d.M, d.S, d.L));\n}\nfunction newDate(y3, m, d) {\n return { y: y3, m, d, H: 0, M: 0, S: 0, L: 0 };\n}\nfunction formatLocale(locale3) {\n var locale_dateTime = locale3.dateTime, locale_date = locale3.date, locale_time = locale3.time, locale_periods = locale3.periods, locale_weekdays = locale3.days, locale_shortWeekdays = locale3.shortDays, locale_months = locale3.months, locale_shortMonths = locale3.shortMonths;\n var periodRe = formatRe(locale_periods), periodLookup = formatLookup(locale_periods), weekdayRe = formatRe(locale_weekdays), weekdayLookup = formatLookup(locale_weekdays), shortWeekdayRe = formatRe(locale_shortWeekdays), shortWeekdayLookup = formatLookup(locale_shortWeekdays), monthRe = formatRe(locale_months), monthLookup = formatLookup(locale_months), shortMonthRe = formatRe(locale_shortMonths), shortMonthLookup = formatLookup(locale_shortMonths);\n var formats = {\n \"a\": formatShortWeekday,\n \"A\": formatWeekday2,\n \"b\": formatShortMonth,\n \"B\": formatMonth2,\n \"c\": null,\n \"d\": formatDayOfMonth,\n \"e\": formatDayOfMonth,\n \"f\": formatMicroseconds,\n \"g\": formatYearISO,\n \"G\": formatFullYearISO,\n \"H\": formatHour24,\n \"I\": formatHour12,\n \"j\": formatDayOfYear,\n \"L\": formatMilliseconds,\n \"m\": formatMonthNumber,\n \"M\": formatMinutes,\n \"p\": formatPeriod,\n \"q\": formatQuarter,\n \"Q\": formatUnixTimestamp,\n \"s\": formatUnixTimestampSeconds,\n \"S\": formatSeconds,\n \"u\": formatWeekdayNumberMonday,\n \"U\": formatWeekNumberSunday,\n \"V\": formatWeekNumberISO,\n \"w\": formatWeekdayNumberSunday,\n \"W\": formatWeekNumberMonday,\n \"x\": null,\n \"X\": null,\n \"y\": formatYear,\n \"Y\": formatFullYear,\n \"Z\": formatZone,\n \"%\": formatLiteralPercent\n };\n var utcFormats = {\n \"a\": formatUTCShortWeekday,\n \"A\": formatUTCWeekday,\n \"b\": formatUTCShortMonth,\n \"B\": formatUTCMonth,\n \"c\": null,\n \"d\": formatUTCDayOfMonth,\n \"e\": formatUTCDayOfMonth,\n \"f\": formatUTCMicroseconds,\n \"g\": formatUTCYearISO,\n \"G\": formatUTCFullYearISO,\n \"H\": formatUTCHour24,\n \"I\": formatUTCHour12,\n \"j\": formatUTCDayOfYear,\n \"L\": formatUTCMilliseconds,\n \"m\": formatUTCMonthNumber,\n \"M\": formatUTCMinutes,\n \"p\": formatUTCPeriod,\n \"q\": formatUTCQuarter,\n \"Q\": formatUnixTimestamp,\n \"s\": formatUnixTimestampSeconds,\n \"S\": formatUTCSeconds,\n \"u\": formatUTCWeekdayNumberMonday,\n \"U\": formatUTCWeekNumberSunday,\n \"V\": formatUTCWeekNumberISO,\n \"w\": formatUTCWeekdayNumberSunday,\n \"W\": formatUTCWeekNumberMonday,\n \"x\": null,\n \"X\": null,\n \"y\": formatUTCYear,\n \"Y\": formatUTCFullYear,\n \"Z\": formatUTCZone,\n \"%\": formatLiteralPercent\n };\n var parses = {\n \"a\": parseShortWeekday,\n \"A\": parseWeekday,\n \"b\": parseShortMonth,\n \"B\": parseMonth,\n \"c\": parseLocaleDateTime,\n \"d\": parseDayOfMonth,\n \"e\": parseDayOfMonth,\n \"f\": parseMicroseconds,\n \"g\": parseYear,\n \"G\": parseFullYear,\n \"H\": parseHour24,\n \"I\": parseHour24,\n \"j\": parseDayOfYear,\n \"L\": parseMilliseconds,\n \"m\": parseMonthNumber,\n \"M\": parseMinutes,\n \"p\": parsePeriod,\n \"q\": parseQuarter,\n \"Q\": parseUnixTimestamp,\n \"s\": parseUnixTimestampSeconds,\n \"S\": parseSeconds,\n \"u\": parseWeekdayNumberMonday,\n \"U\": parseWeekNumberSunday,\n \"V\": parseWeekNumberISO,\n \"w\": parseWeekdayNumberSunday,\n \"W\": parseWeekNumberMonday,\n \"x\": parseLocaleDate,\n \"X\": parseLocaleTime,\n \"y\": parseYear,\n \"Y\": parseFullYear,\n \"Z\": parseZone,\n \"%\": parseLiteralPercent\n };\n formats.x = newFormat(locale_date, formats);\n formats.X = newFormat(locale_time, formats);\n formats.c = newFormat(locale_dateTime, formats);\n utcFormats.x = newFormat(locale_date, utcFormats);\n utcFormats.X = newFormat(locale_time, utcFormats);\n utcFormats.c = newFormat(locale_dateTime, utcFormats);\n function newFormat(specifier, formats2) {\n return function(date3) {\n var string2 = [], i = -1, j = 0, n = specifier.length, c4, pad3, format3;\n if (!(date3 instanceof Date)) date3 = /* @__PURE__ */ new Date(+date3);\n while (++i < n) {\n if (specifier.charCodeAt(i) === 37) {\n string2.push(specifier.slice(j, i));\n if ((pad3 = pads[c4 = specifier.charAt(++i)]) != null) c4 = specifier.charAt(++i);\n else pad3 = c4 === \"e\" ? \" \" : \"0\";\n if (format3 = formats2[c4]) c4 = format3(date3, pad3);\n string2.push(c4);\n j = i + 1;\n }\n }\n string2.push(specifier.slice(j, i));\n return string2.join(\"\");\n };\n }\n function newParse(specifier, Z) {\n return function(string2) {\n var d = newDate(1900, void 0, 1), i = parseSpecifier(d, specifier, string2 += \"\", 0), week, day;\n if (i != string2.length) return null;\n if (\"Q\" in d) return new Date(d.Q);\n if (\"s\" in d) return new Date(d.s * 1e3 + (\"L\" in d ? d.L : 0));\n if (Z && !(\"Z\" in d)) d.Z = 0;\n if (\"p\" in d) d.H = d.H % 12 + d.p * 12;\n if (d.m === void 0) d.m = \"q\" in d ? d.q : 0;\n if (\"V\" in d) {\n if (d.V < 1 || d.V > 53) return null;\n if (!(\"w\" in d)) d.w = 1;\n if (\"Z\" in d) {\n week = utcDate(newDate(d.y, 0, 1)), day = week.getUTCDay();\n week = day > 4 || day === 0 ? utcMonday.ceil(week) : utcMonday(week);\n week = utcDay.offset(week, (d.V - 1) * 7);\n d.y = week.getUTCFullYear();\n d.m = week.getUTCMonth();\n d.d = week.getUTCDate() + (d.w + 6) % 7;\n } else {\n week = localDate(newDate(d.y, 0, 1)), day = week.getDay();\n week = day > 4 || day === 0 ? timeMonday.ceil(week) : timeMonday(week);\n week = timeDay.offset(week, (d.V - 1) * 7);\n d.y = week.getFullYear();\n d.m = week.getMonth();\n d.d = week.getDate() + (d.w + 6) % 7;\n }\n } else if (\"W\" in d || \"U\" in d) {\n if (!(\"w\" in d)) d.w = \"u\" in d ? d.u % 7 : \"W\" in d ? 1 : 0;\n day = \"Z\" in d ? utcDate(newDate(d.y, 0, 1)).getUTCDay() : localDate(newDate(d.y, 0, 1)).getDay();\n d.m = 0;\n d.d = \"W\" in d ? (d.w + 6) % 7 + d.W * 7 - (day + 5) % 7 : d.w + d.U * 7 - (day + 6) % 7;\n }\n if (\"Z\" in d) {\n d.H += d.Z / 100 | 0;\n d.M += d.Z % 100;\n return utcDate(d);\n }\n return localDate(d);\n };\n }\n function parseSpecifier(d, specifier, string2, j) {\n var i = 0, n = specifier.length, m = string2.length, c4, parse2;\n while (i < n) {\n if (j >= m) return -1;\n c4 = specifier.charCodeAt(i++);\n if (c4 === 37) {\n c4 = specifier.charAt(i++);\n parse2 = parses[c4 in pads ? specifier.charAt(i++) : c4];\n if (!parse2 || (j = parse2(d, string2, j)) < 0) return -1;\n } else if (c4 != string2.charCodeAt(j++)) {\n return -1;\n }\n }\n return j;\n }\n function parsePeriod(d, string2, i) {\n var n = periodRe.exec(string2.slice(i));\n return n ? (d.p = periodLookup.get(n[0].toLowerCase()), i + n[0].length) : -1;\n }\n function parseShortWeekday(d, string2, i) {\n var n = shortWeekdayRe.exec(string2.slice(i));\n return n ? (d.w = shortWeekdayLookup.get(n[0].toLowerCase()), i + n[0].length) : -1;\n }\n function parseWeekday(d, string2, i) {\n var n = weekdayRe.exec(string2.slice(i));\n return n ? (d.w = weekdayLookup.get(n[0].toLowerCase()), i + n[0].length) : -1;\n }\n function parseShortMonth(d, string2, i) {\n var n = shortMonthRe.exec(string2.slice(i));\n return n ? (d.m = shortMonthLookup.get(n[0].toLowerCase()), i + n[0].length) : -1;\n }\n function parseMonth(d, string2, i) {\n var n = monthRe.exec(string2.slice(i));\n return n ? (d.m = monthLookup.get(n[0].toLowerCase()), i + n[0].length) : -1;\n }\n function parseLocaleDateTime(d, string2, i) {\n return parseSpecifier(d, locale_dateTime, string2, i);\n }\n function parseLocaleDate(d, string2, i) {\n return parseSpecifier(d, locale_date, string2, i);\n }\n function parseLocaleTime(d, string2, i) {\n return parseSpecifier(d, locale_time, string2, i);\n }\n function formatShortWeekday(d) {\n return locale_shortWeekdays[d.getDay()];\n }\n function formatWeekday2(d) {\n return locale_weekdays[d.getDay()];\n }\n function formatShortMonth(d) {\n return locale_shortMonths[d.getMonth()];\n }\n function formatMonth2(d) {\n return locale_months[d.getMonth()];\n }\n function formatPeriod(d) {\n return locale_periods[+(d.getHours() >= 12)];\n }\n function formatQuarter(d) {\n return 1 + ~~(d.getMonth() / 3);\n }\n function formatUTCShortWeekday(d) {\n return locale_shortWeekdays[d.getUTCDay()];\n }\n function formatUTCWeekday(d) {\n return locale_weekdays[d.getUTCDay()];\n }\n function formatUTCShortMonth(d) {\n return locale_shortMonths[d.getUTCMonth()];\n }\n function formatUTCMonth(d) {\n return locale_months[d.getUTCMonth()];\n }\n function formatUTCPeriod(d) {\n return locale_periods[+(d.getUTCHours() >= 12)];\n }\n function formatUTCQuarter(d) {\n return 1 + ~~(d.getUTCMonth() / 3);\n }\n return {\n format: function(specifier) {\n var f = newFormat(specifier += \"\", formats);\n f.toString = function() {\n return specifier;\n };\n return f;\n },\n parse: function(specifier) {\n var p = newParse(specifier += \"\", false);\n p.toString = function() {\n return specifier;\n };\n return p;\n },\n utcFormat: function(specifier) {\n var f = newFormat(specifier += \"\", utcFormats);\n f.toString = function() {\n return specifier;\n };\n return f;\n },\n utcParse: function(specifier) {\n var p = newParse(specifier += \"\", true);\n p.toString = function() {\n return specifier;\n };\n return p;\n }\n };\n}\nvar pads = { \"-\": \"\", \"_\": \" \", \"0\": \"0\" };\nvar numberRe = /^\\s*\\d+/;\nvar percentRe = /^%/;\nvar requoteRe = /[\\\\^$*+?|[\\]().{}]/g;\nfunction pad(value, fill, width2) {\n var sign3 = value < 0 ? \"-\" : \"\", string2 = (sign3 ? -value : value) + \"\", length4 = string2.length;\n return sign3 + (length4 < width2 ? new Array(width2 - length4 + 1).join(fill) + string2 : string2);\n}\nfunction requote(s2) {\n return s2.replace(requoteRe, \"\\\\$&\");\n}\nfunction formatRe(names) {\n return new RegExp(\"^(?:\" + names.map(requote).join(\"|\") + \")\", \"i\");\n}\nfunction formatLookup(names) {\n return new Map(names.map((name2, i) => [name2.toLowerCase(), i]));\n}\nfunction parseWeekdayNumberSunday(d, string2, i) {\n var n = numberRe.exec(string2.slice(i, i + 1));\n return n ? (d.w = +n[0], i + n[0].length) : -1;\n}\nfunction parseWeekdayNumberMonday(d, string2, i) {\n var n = numberRe.exec(string2.slice(i, i + 1));\n return n ? (d.u = +n[0], i + n[0].length) : -1;\n}\nfunction parseWeekNumberSunday(d, string2, i) {\n var n = numberRe.exec(string2.slice(i, i + 2));\n return n ? (d.U = +n[0], i + n[0].length) : -1;\n}\nfunction parseWeekNumberISO(d, string2, i) {\n var n = numberRe.exec(string2.slice(i, i + 2));\n return n ? (d.V = +n[0], i + n[0].length) : -1;\n}\nfunction parseWeekNumberMonday(d, string2, i) {\n var n = numberRe.exec(string2.slice(i, i + 2));\n return n ? (d.W = +n[0], i + n[0].length) : -1;\n}\nfunction parseFullYear(d, string2, i) {\n var n = numberRe.exec(string2.slice(i, i + 4));\n return n ? (d.y = +n[0], i + n[0].length) : -1;\n}\nfunction parseYear(d, string2, i) {\n var n = numberRe.exec(string2.slice(i, i + 2));\n return n ? (d.y = +n[0] + (+n[0] > 68 ? 1900 : 2e3), i + n[0].length) : -1;\n}\nfunction parseZone(d, string2, i) {\n var n = /^(Z)|([+-]\\d\\d)(?::?(\\d\\d))?/.exec(string2.slice(i, i + 6));\n return n ? (d.Z = n[1] ? 0 : -(n[2] + (n[3] || \"00\")), i + n[0].length) : -1;\n}\nfunction parseQuarter(d, string2, i) {\n var n = numberRe.exec(string2.slice(i, i + 1));\n return n ? (d.q = n[0] * 3 - 3, i + n[0].length) : -1;\n}\nfunction parseMonthNumber(d, string2, i) {\n var n = numberRe.exec(string2.slice(i, i + 2));\n return n ? (d.m = n[0] - 1, i + n[0].length) : -1;\n}\nfunction parseDayOfMonth(d, string2, i) {\n var n = numberRe.exec(string2.slice(i, i + 2));\n return n ? (d.d = +n[0], i + n[0].length) : -1;\n}\nfunction parseDayOfYear(d, string2, i) {\n var n = numberRe.exec(string2.slice(i, i + 3));\n return n ? (d.m = 0, d.d = +n[0], i + n[0].length) : -1;\n}\nfunction parseHour24(d, string2, i) {\n var n = numberRe.exec(string2.slice(i, i + 2));\n return n ? (d.H = +n[0], i + n[0].length) : -1;\n}\nfunction parseMinutes(d, string2, i) {\n var n = numberRe.exec(string2.slice(i, i + 2));\n return n ? (d.M = +n[0], i + n[0].length) : -1;\n}\nfunction parseSeconds(d, string2, i) {\n var n = numberRe.exec(string2.slice(i, i + 2));\n return n ? (d.S = +n[0], i + n[0].length) : -1;\n}\nfunction parseMilliseconds(d, string2, i) {\n var n = numberRe.exec(string2.slice(i, i + 3));\n return n ? (d.L = +n[0], i + n[0].length) : -1;\n}\nfunction parseMicroseconds(d, string2, i) {\n var n = numberRe.exec(string2.slice(i, i + 6));\n return n ? (d.L = Math.floor(n[0] / 1e3), i + n[0].length) : -1;\n}\nfunction parseLiteralPercent(d, string2, i) {\n var n = percentRe.exec(string2.slice(i, i + 1));\n return n ? i + n[0].length : -1;\n}\nfunction parseUnixTimestamp(d, string2, i) {\n var n = numberRe.exec(string2.slice(i));\n return n ? (d.Q = +n[0], i + n[0].length) : -1;\n}\nfunction parseUnixTimestampSeconds(d, string2, i) {\n var n = numberRe.exec(string2.slice(i));\n return n ? (d.s = +n[0], i + n[0].length) : -1;\n}\nfunction formatDayOfMonth(d, p) {\n return pad(d.getDate(), p, 2);\n}\nfunction formatHour24(d, p) {\n return pad(d.getHours(), p, 2);\n}\nfunction formatHour12(d, p) {\n return pad(d.getHours() % 12 || 12, p, 2);\n}\nfunction formatDayOfYear(d, p) {\n return pad(1 + timeDay.count(timeYear(d), d), p, 3);\n}\nfunction formatMilliseconds(d, p) {\n return pad(d.getMilliseconds(), p, 3);\n}\nfunction formatMicroseconds(d, p) {\n return formatMilliseconds(d, p) + \"000\";\n}\nfunction formatMonthNumber(d, p) {\n return pad(d.getMonth() + 1, p, 2);\n}\nfunction formatMinutes(d, p) {\n return pad(d.getMinutes(), p, 2);\n}\nfunction formatSeconds(d, p) {\n return pad(d.getSeconds(), p, 2);\n}\nfunction formatWeekdayNumberMonday(d) {\n var day = d.getDay();\n return day === 0 ? 7 : day;\n}\nfunction formatWeekNumberSunday(d, p) {\n return pad(timeSunday.count(timeYear(d) - 1, d), p, 2);\n}\nfunction dISO(d) {\n var day = d.getDay();\n return day >= 4 || day === 0 ? timeThursday(d) : timeThursday.ceil(d);\n}\nfunction formatWeekNumberISO(d, p) {\n d = dISO(d);\n return pad(timeThursday.count(timeYear(d), d) + (timeYear(d).getDay() === 4), p, 2);\n}\nfunction formatWeekdayNumberSunday(d) {\n return d.getDay();\n}\nfunction formatWeekNumberMonday(d, p) {\n return pad(timeMonday.count(timeYear(d) - 1, d), p, 2);\n}\nfunction formatYear(d, p) {\n return pad(d.getFullYear() % 100, p, 2);\n}\nfunction formatYearISO(d, p) {\n d = dISO(d);\n return pad(d.getFullYear() % 100, p, 2);\n}\nfunction formatFullYear(d, p) {\n return pad(d.getFullYear() % 1e4, p, 4);\n}\nfunction formatFullYearISO(d, p) {\n var day = d.getDay();\n d = day >= 4 || day === 0 ? timeThursday(d) : timeThursday.ceil(d);\n return pad(d.getFullYear() % 1e4, p, 4);\n}\nfunction formatZone(d) {\n var z = d.getTimezoneOffset();\n return (z > 0 ? \"-\" : (z *= -1, \"+\")) + pad(z / 60 | 0, \"0\", 2) + pad(z % 60, \"0\", 2);\n}\nfunction formatUTCDayOfMonth(d, p) {\n return pad(d.getUTCDate(), p, 2);\n}\nfunction formatUTCHour24(d, p) {\n return pad(d.getUTCHours(), p, 2);\n}\nfunction formatUTCHour12(d, p) {\n return pad(d.getUTCHours() % 12 || 12, p, 2);\n}\nfunction formatUTCDayOfYear(d, p) {\n return pad(1 + utcDay.count(utcYear(d), d), p, 3);\n}\nfunction formatUTCMilliseconds(d, p) {\n return pad(d.getUTCMilliseconds(), p, 3);\n}\nfunction formatUTCMicroseconds(d, p) {\n return formatUTCMilliseconds(d, p) + \"000\";\n}\nfunction formatUTCMonthNumber(d, p) {\n return pad(d.getUTCMonth() + 1, p, 2);\n}\nfunction formatUTCMinutes(d, p) {\n return pad(d.getUTCMinutes(), p, 2);\n}\nfunction formatUTCSeconds(d, p) {\n return pad(d.getUTCSeconds(), p, 2);\n}\nfunction formatUTCWeekdayNumberMonday(d) {\n var dow = d.getUTCDay();\n return dow === 0 ? 7 : dow;\n}\nfunction formatUTCWeekNumberSunday(d, p) {\n return pad(utcSunday.count(utcYear(d) - 1, d), p, 2);\n}\nfunction UTCdISO(d) {\n var day = d.getUTCDay();\n return day >= 4 || day === 0 ? utcThursday(d) : utcThursday.ceil(d);\n}\nfunction formatUTCWeekNumberISO(d, p) {\n d = UTCdISO(d);\n return pad(utcThursday.count(utcYear(d), d) + (utcYear(d).getUTCDay() === 4), p, 2);\n}\nfunction formatUTCWeekdayNumberSunday(d) {\n return d.getUTCDay();\n}\nfunction formatUTCWeekNumberMonday(d, p) {\n return pad(utcMonday.count(utcYear(d) - 1, d), p, 2);\n}\nfunction formatUTCYear(d, p) {\n return pad(d.getUTCFullYear() % 100, p, 2);\n}\nfunction formatUTCYearISO(d, p) {\n d = UTCdISO(d);\n return pad(d.getUTCFullYear() % 100, p, 2);\n}\nfunction formatUTCFullYear(d, p) {\n return pad(d.getUTCFullYear() % 1e4, p, 4);\n}\nfunction formatUTCFullYearISO(d, p) {\n var day = d.getUTCDay();\n d = day >= 4 || day === 0 ? utcThursday(d) : utcThursday.ceil(d);\n return pad(d.getUTCFullYear() % 1e4, p, 4);\n}\nfunction formatUTCZone() {\n return \"+0000\";\n}\nfunction formatLiteralPercent() {\n return \"%\";\n}\nfunction formatUnixTimestamp(d) {\n return +d;\n}\nfunction formatUnixTimestampSeconds(d) {\n return Math.floor(+d / 1e3);\n}\n\n// ../../node_modules/d3-time-format/src/defaultLocale.js\nvar locale2;\nvar timeFormat;\nvar timeParse;\nvar utcFormat;\nvar utcParse;\ndefaultLocale2({\n dateTime: \"%x, %X\",\n date: \"%-m/%-d/%Y\",\n time: \"%-I:%M:%S %p\",\n periods: [\"AM\", \"PM\"],\n days: [\"Sunday\", \"Monday\", \"Tuesday\", \"Wednesday\", \"Thursday\", \"Friday\", \"Saturday\"],\n shortDays: [\"Sun\", \"Mon\", \"Tue\", \"Wed\", \"Thu\", \"Fri\", \"Sat\"],\n months: [\"January\", \"February\", \"March\", \"April\", \"May\", \"June\", \"July\", \"August\", \"September\", \"October\", \"November\", \"December\"],\n shortMonths: [\"Jan\", \"Feb\", \"Mar\", \"Apr\", \"May\", \"Jun\", \"Jul\", \"Aug\", \"Sep\", \"Oct\", \"Nov\", \"Dec\"]\n});\nfunction defaultLocale2(definition) {\n locale2 = formatLocale(definition);\n timeFormat = locale2.format;\n timeParse = locale2.parse;\n utcFormat = locale2.utcFormat;\n utcParse = locale2.utcParse;\n return locale2;\n}\n\n// ../../node_modules/d3-scale/src/time.js\nfunction date2(t) {\n return new Date(t);\n}\nfunction number4(t) {\n return t instanceof Date ? +t : +/* @__PURE__ */ new Date(+t);\n}\nfunction calendar(ticks2, tickInterval, year, month, week, day, hour, minute, second3, format3) {\n var scale3 = continuous(), invert2 = scale3.invert, domain = scale3.domain;\n var formatMillisecond = format3(\".%L\"), formatSecond = format3(\":%S\"), formatMinute = format3(\"%I:%M\"), formatHour = format3(\"%I %p\"), formatDay = format3(\"%a %d\"), formatWeek = format3(\"%b %d\"), formatMonth2 = format3(\"%B\"), formatYear3 = format3(\"%Y\");\n function tickFormat2(date3) {\n return (second3(date3) < date3 ? formatMillisecond : minute(date3) < date3 ? formatSecond : hour(date3) < date3 ? formatMinute : day(date3) < date3 ? formatHour : month(date3) < date3 ? week(date3) < date3 ? formatDay : formatWeek : year(date3) < date3 ? formatMonth2 : formatYear3)(date3);\n }\n scale3.invert = function(y3) {\n return new Date(invert2(y3));\n };\n scale3.domain = function(_) {\n return arguments.length ? domain(Array.from(_, number4)) : domain().map(date2);\n };\n scale3.ticks = function(interval3) {\n var d = domain();\n return ticks2(d[0], d[d.length - 1], interval3 == null ? 10 : interval3);\n };\n scale3.tickFormat = function(count4, specifier) {\n return specifier == null ? tickFormat2 : format3(specifier);\n };\n scale3.nice = function(interval3) {\n var d = domain();\n if (!interval3 || typeof interval3.range !== \"function\") interval3 = tickInterval(d[0], d[d.length - 1], interval3 == null ? 10 : interval3);\n return interval3 ? domain(nice2(d, interval3)) : scale3;\n };\n scale3.copy = function() {\n return copy(scale3, calendar(ticks2, tickInterval, year, month, week, day, hour, minute, second3, format3));\n };\n return scale3;\n}\nfunction time2() {\n return initRange.apply(calendar(timeTicks, timeTickInterval, timeYear, timeMonth, timeSunday, timeDay, timeHour, timeMinute, second, timeFormat).domain([new Date(2e3, 0, 1), new Date(2e3, 0, 2)]), arguments);\n}\n\n// ../../node_modules/d3-scale/src/utcTime.js\nfunction utcTime() {\n return initRange.apply(calendar(utcTicks, utcTickInterval, utcYear, utcMonth, utcSunday, utcDay, utcHour, utcMinute, second, utcFormat).domain([Date.UTC(2e3, 0, 1), Date.UTC(2e3, 0, 2)]), arguments);\n}\n\n// ../../node_modules/d3-scale/src/sequential.js\nfunction copy2(source, target) {\n return target.domain(source.domain()).interpolator(source.interpolator()).clamp(source.clamp()).unknown(source.unknown());\n}\n\n// ../../node_modules/d3-scale/src/diverging.js\nfunction transformer3() {\n var x06 = 0, x12 = 0.5, x22 = 1, s2 = 1, t03, t13, t22, k10, k21, interpolator = identity4, transform3, clamp = false, unknown;\n function scale3(x3) {\n return isNaN(x3 = +x3) ? unknown : (x3 = 0.5 + ((x3 = +transform3(x3)) - t13) * (s2 * x3 < s2 * t13 ? k10 : k21), interpolator(clamp ? Math.max(0, Math.min(1, x3)) : x3));\n }\n scale3.domain = function(_) {\n return arguments.length ? ([x06, x12, x22] = _, t03 = transform3(x06 = +x06), t13 = transform3(x12 = +x12), t22 = transform3(x22 = +x22), k10 = t03 === t13 ? 0 : 0.5 / (t13 - t03), k21 = t13 === t22 ? 0 : 0.5 / (t22 - t13), s2 = t13 < t03 ? -1 : 1, scale3) : [x06, x12, x22];\n };\n scale3.clamp = function(_) {\n return arguments.length ? (clamp = !!_, scale3) : clamp;\n };\n scale3.interpolator = function(_) {\n return arguments.length ? (interpolator = _, scale3) : interpolator;\n };\n function range3(interpolate) {\n return function(_) {\n var r0, r1, r2;\n return arguments.length ? ([r0, r1, r2] = _, interpolator = piecewise(interpolate, [r0, r1, r2]), scale3) : [interpolator(0), interpolator(0.5), interpolator(1)];\n };\n }\n scale3.range = range3(value_default);\n scale3.rangeRound = range3(round_default);\n scale3.unknown = function(_) {\n return arguments.length ? (unknown = _, scale3) : unknown;\n };\n return function(t) {\n transform3 = t, t03 = t(x06), t13 = t(x12), t22 = t(x22), k10 = t03 === t13 ? 0 : 0.5 / (t13 - t03), k21 = t13 === t22 ? 0 : 0.5 / (t22 - t13), s2 = t13 < t03 ? -1 : 1;\n return scale3;\n };\n}\nfunction diverging() {\n var scale3 = linearish(transformer3()(identity4));\n scale3.copy = function() {\n return copy2(scale3, diverging());\n };\n return initInterpolator.apply(scale3, arguments);\n}\nfunction divergingLog() {\n var scale3 = loggish(transformer3()).domain([0.1, 1, 10]);\n scale3.copy = function() {\n return copy2(scale3, divergingLog()).base(scale3.base());\n };\n return initInterpolator.apply(scale3, arguments);\n}\nfunction divergingSymlog() {\n var scale3 = symlogish(transformer3());\n scale3.copy = function() {\n return copy2(scale3, divergingSymlog()).constant(scale3.constant());\n };\n return initInterpolator.apply(scale3, arguments);\n}\nfunction divergingPow() {\n var scale3 = powish(transformer3());\n scale3.copy = function() {\n return copy2(scale3, divergingPow()).exponent(scale3.exponent());\n };\n return initInterpolator.apply(scale3, arguments);\n}\n\n// ../../node_modules/d3-scale-chromatic/src/colors.js\nfunction colors_default(specifier) {\n var n = specifier.length / 6 | 0, colors = new Array(n), i = 0;\n while (i < n) colors[i] = \"#\" + specifier.slice(i * 6, ++i * 6);\n return colors;\n}\n\n// ../../node_modules/d3-scale-chromatic/src/categorical/category10.js\nvar category10_default = colors_default(\"1f77b4ff7f0e2ca02cd627289467bd8c564be377c27f7f7fbcbd2217becf\");\n\n// ../../node_modules/d3-scale-chromatic/src/categorical/Accent.js\nvar Accent_default = colors_default(\"7fc97fbeaed4fdc086ffff99386cb0f0027fbf5b17666666\");\n\n// ../../node_modules/d3-scale-chromatic/src/categorical/Dark2.js\nvar Dark2_default = colors_default(\"1b9e77d95f027570b3e7298a66a61ee6ab02a6761d666666\");\n\n// ../../node_modules/d3-scale-chromatic/src/categorical/observable10.js\nvar observable10_default = colors_default(\"4269d0efb118ff725c6cc5b03ca951ff8ab7a463f297bbf59c6b4e9498a0\");\n\n// ../../node_modules/d3-scale-chromatic/src/categorical/Paired.js\nvar Paired_default = colors_default(\"a6cee31f78b4b2df8a33a02cfb9a99e31a1cfdbf6fff7f00cab2d66a3d9affff99b15928\");\n\n// ../../node_modules/d3-scale-chromatic/src/categorical/Pastel1.js\nvar Pastel1_default = colors_default(\"fbb4aeb3cde3ccebc5decbe4fed9a6ffffcce5d8bdfddaecf2f2f2\");\n\n// ../../node_modules/d3-scale-chromatic/src/categorical/Pastel2.js\nvar Pastel2_default = colors_default(\"b3e2cdfdcdaccbd5e8f4cae4e6f5c9fff2aef1e2cccccccc\");\n\n// ../../node_modules/d3-scale-chromatic/src/categorical/Set1.js\nvar Set1_default = colors_default(\"e41a1c377eb84daf4a984ea3ff7f00ffff33a65628f781bf999999\");\n\n// ../../node_modules/d3-scale-chromatic/src/categorical/Set2.js\nvar Set2_default = colors_default(\"66c2a5fc8d628da0cbe78ac3a6d854ffd92fe5c494b3b3b3\");\n\n// ../../node_modules/d3-scale-chromatic/src/categorical/Set3.js\nvar Set3_default = colors_default(\"8dd3c7ffffb3bebadafb807280b1d3fdb462b3de69fccde5d9d9d9bc80bdccebc5ffed6f\");\n\n// ../../node_modules/d3-scale-chromatic/src/categorical/Tableau10.js\nvar Tableau10_default = colors_default(\"4e79a7f28e2ce1575976b7b259a14fedc949af7aa1ff9da79c755fbab0ab\");\n\n// ../../node_modules/d3-scale-chromatic/src/ramp.js\nvar ramp_default = (scheme28) => rgbBasis(scheme28[scheme28.length - 1]);\n\n// ../../node_modules/d3-scale-chromatic/src/diverging/BrBG.js\nvar scheme = new Array(3).concat(\n \"d8b365f5f5f55ab4ac\",\n \"a6611adfc27d80cdc1018571\",\n \"a6611adfc27df5f5f580cdc1018571\",\n \"8c510ad8b365f6e8c3c7eae55ab4ac01665e\",\n \"8c510ad8b365f6e8c3f5f5f5c7eae55ab4ac01665e\",\n \"8c510abf812ddfc27df6e8c3c7eae580cdc135978f01665e\",\n \"8c510abf812ddfc27df6e8c3f5f5f5c7eae580cdc135978f01665e\",\n \"5430058c510abf812ddfc27df6e8c3c7eae580cdc135978f01665e003c30\",\n \"5430058c510abf812ddfc27df6e8c3f5f5f5c7eae580cdc135978f01665e003c30\"\n).map(colors_default);\nvar BrBG_default = ramp_default(scheme);\n\n// ../../node_modules/d3-scale-chromatic/src/diverging/PRGn.js\nvar scheme2 = new Array(3).concat(\n \"af8dc3f7f7f77fbf7b\",\n \"7b3294c2a5cfa6dba0008837\",\n \"7b3294c2a5cff7f7f7a6dba0008837\",\n \"762a83af8dc3e7d4e8d9f0d37fbf7b1b7837\",\n \"762a83af8dc3e7d4e8f7f7f7d9f0d37fbf7b1b7837\",\n \"762a839970abc2a5cfe7d4e8d9f0d3a6dba05aae611b7837\",\n \"762a839970abc2a5cfe7d4e8f7f7f7d9f0d3a6dba05aae611b7837\",\n \"40004b762a839970abc2a5cfe7d4e8d9f0d3a6dba05aae611b783700441b\",\n \"40004b762a839970abc2a5cfe7d4e8f7f7f7d9f0d3a6dba05aae611b783700441b\"\n).map(colors_default);\nvar PRGn_default = ramp_default(scheme2);\n\n// ../../node_modules/d3-scale-chromatic/src/diverging/PiYG.js\nvar scheme3 = new Array(3).concat(\n \"e9a3c9f7f7f7a1d76a\",\n \"d01c8bf1b6dab8e1864dac26\",\n \"d01c8bf1b6daf7f7f7b8e1864dac26\",\n \"c51b7de9a3c9fde0efe6f5d0a1d76a4d9221\",\n \"c51b7de9a3c9fde0eff7f7f7e6f5d0a1d76a4d9221\",\n \"c51b7dde77aef1b6dafde0efe6f5d0b8e1867fbc414d9221\",\n \"c51b7dde77aef1b6dafde0eff7f7f7e6f5d0b8e1867fbc414d9221\",\n \"8e0152c51b7dde77aef1b6dafde0efe6f5d0b8e1867fbc414d9221276419\",\n \"8e0152c51b7dde77aef1b6dafde0eff7f7f7e6f5d0b8e1867fbc414d9221276419\"\n).map(colors_default);\nvar PiYG_default = ramp_default(scheme3);\n\n// ../../node_modules/d3-scale-chromatic/src/diverging/PuOr.js\nvar scheme4 = new Array(3).concat(\n \"998ec3f7f7f7f1a340\",\n \"5e3c99b2abd2fdb863e66101\",\n \"5e3c99b2abd2f7f7f7fdb863e66101\",\n \"542788998ec3d8daebfee0b6f1a340b35806\",\n \"542788998ec3d8daebf7f7f7fee0b6f1a340b35806\",\n \"5427888073acb2abd2d8daebfee0b6fdb863e08214b35806\",\n \"5427888073acb2abd2d8daebf7f7f7fee0b6fdb863e08214b35806\",\n \"2d004b5427888073acb2abd2d8daebfee0b6fdb863e08214b358067f3b08\",\n \"2d004b5427888073acb2abd2d8daebf7f7f7fee0b6fdb863e08214b358067f3b08\"\n).map(colors_default);\nvar PuOr_default = ramp_default(scheme4);\n\n// ../../node_modules/d3-scale-chromatic/src/diverging/RdBu.js\nvar scheme5 = new Array(3).concat(\n \"ef8a62f7f7f767a9cf\",\n \"ca0020f4a58292c5de0571b0\",\n \"ca0020f4a582f7f7f792c5de0571b0\",\n \"b2182bef8a62fddbc7d1e5f067a9cf2166ac\",\n \"b2182bef8a62fddbc7f7f7f7d1e5f067a9cf2166ac\",\n \"b2182bd6604df4a582fddbc7d1e5f092c5de4393c32166ac\",\n \"b2182bd6604df4a582fddbc7f7f7f7d1e5f092c5de4393c32166ac\",\n \"67001fb2182bd6604df4a582fddbc7d1e5f092c5de4393c32166ac053061\",\n \"67001fb2182bd6604df4a582fddbc7f7f7f7d1e5f092c5de4393c32166ac053061\"\n).map(colors_default);\nvar RdBu_default = ramp_default(scheme5);\n\n// ../../node_modules/d3-scale-chromatic/src/diverging/RdGy.js\nvar scheme6 = new Array(3).concat(\n \"ef8a62ffffff999999\",\n \"ca0020f4a582bababa404040\",\n \"ca0020f4a582ffffffbababa404040\",\n \"b2182bef8a62fddbc7e0e0e09999994d4d4d\",\n \"b2182bef8a62fddbc7ffffffe0e0e09999994d4d4d\",\n \"b2182bd6604df4a582fddbc7e0e0e0bababa8787874d4d4d\",\n \"b2182bd6604df4a582fddbc7ffffffe0e0e0bababa8787874d4d4d\",\n \"67001fb2182bd6604df4a582fddbc7e0e0e0bababa8787874d4d4d1a1a1a\",\n \"67001fb2182bd6604df4a582fddbc7ffffffe0e0e0bababa8787874d4d4d1a1a1a\"\n).map(colors_default);\nvar RdGy_default = ramp_default(scheme6);\n\n// ../../node_modules/d3-scale-chromatic/src/diverging/RdYlBu.js\nvar scheme7 = new Array(3).concat(\n \"fc8d59ffffbf91bfdb\",\n \"d7191cfdae61abd9e92c7bb6\",\n \"d7191cfdae61ffffbfabd9e92c7bb6\",\n \"d73027fc8d59fee090e0f3f891bfdb4575b4\",\n \"d73027fc8d59fee090ffffbfe0f3f891bfdb4575b4\",\n \"d73027f46d43fdae61fee090e0f3f8abd9e974add14575b4\",\n \"d73027f46d43fdae61fee090ffffbfe0f3f8abd9e974add14575b4\",\n \"a50026d73027f46d43fdae61fee090e0f3f8abd9e974add14575b4313695\",\n \"a50026d73027f46d43fdae61fee090ffffbfe0f3f8abd9e974add14575b4313695\"\n).map(colors_default);\nvar RdYlBu_default = ramp_default(scheme7);\n\n// ../../node_modules/d3-scale-chromatic/src/diverging/RdYlGn.js\nvar scheme8 = new Array(3).concat(\n \"fc8d59ffffbf91cf60\",\n \"d7191cfdae61a6d96a1a9641\",\n \"d7191cfdae61ffffbfa6d96a1a9641\",\n \"d73027fc8d59fee08bd9ef8b91cf601a9850\",\n \"d73027fc8d59fee08bffffbfd9ef8b91cf601a9850\",\n \"d73027f46d43fdae61fee08bd9ef8ba6d96a66bd631a9850\",\n \"d73027f46d43fdae61fee08bffffbfd9ef8ba6d96a66bd631a9850\",\n \"a50026d73027f46d43fdae61fee08bd9ef8ba6d96a66bd631a9850006837\",\n \"a50026d73027f46d43fdae61fee08bffffbfd9ef8ba6d96a66bd631a9850006837\"\n).map(colors_default);\nvar RdYlGn_default = ramp_default(scheme8);\n\n// ../../node_modules/d3-scale-chromatic/src/diverging/Spectral.js\nvar scheme9 = new Array(3).concat(\n \"fc8d59ffffbf99d594\",\n \"d7191cfdae61abdda42b83ba\",\n \"d7191cfdae61ffffbfabdda42b83ba\",\n \"d53e4ffc8d59fee08be6f59899d5943288bd\",\n \"d53e4ffc8d59fee08bffffbfe6f59899d5943288bd\",\n \"d53e4ff46d43fdae61fee08be6f598abdda466c2a53288bd\",\n \"d53e4ff46d43fdae61fee08bffffbfe6f598abdda466c2a53288bd\",\n \"9e0142d53e4ff46d43fdae61fee08be6f598abdda466c2a53288bd5e4fa2\",\n \"9e0142d53e4ff46d43fdae61fee08bffffbfe6f598abdda466c2a53288bd5e4fa2\"\n).map(colors_default);\nvar Spectral_default = ramp_default(scheme9);\n\n// ../../node_modules/d3-scale-chromatic/src/sequential-multi/BuGn.js\nvar scheme10 = new Array(3).concat(\n \"e5f5f999d8c92ca25f\",\n \"edf8fbb2e2e266c2a4238b45\",\n \"edf8fbb2e2e266c2a42ca25f006d2c\",\n \"edf8fbccece699d8c966c2a42ca25f006d2c\",\n \"edf8fbccece699d8c966c2a441ae76238b45005824\",\n \"f7fcfde5f5f9ccece699d8c966c2a441ae76238b45005824\",\n \"f7fcfde5f5f9ccece699d8c966c2a441ae76238b45006d2c00441b\"\n).map(colors_default);\nvar BuGn_default = ramp_default(scheme10);\n\n// ../../node_modules/d3-scale-chromatic/src/sequential-multi/BuPu.js\nvar scheme11 = new Array(3).concat(\n \"e0ecf49ebcda8856a7\",\n \"edf8fbb3cde38c96c688419d\",\n \"edf8fbb3cde38c96c68856a7810f7c\",\n \"edf8fbbfd3e69ebcda8c96c68856a7810f7c\",\n \"edf8fbbfd3e69ebcda8c96c68c6bb188419d6e016b\",\n \"f7fcfde0ecf4bfd3e69ebcda8c96c68c6bb188419d6e016b\",\n \"f7fcfde0ecf4bfd3e69ebcda8c96c68c6bb188419d810f7c4d004b\"\n).map(colors_default);\nvar BuPu_default = ramp_default(scheme11);\n\n// ../../node_modules/d3-scale-chromatic/src/sequential-multi/GnBu.js\nvar scheme12 = new Array(3).concat(\n \"e0f3dba8ddb543a2ca\",\n \"f0f9e8bae4bc7bccc42b8cbe\",\n \"f0f9e8bae4bc7bccc443a2ca0868ac\",\n \"f0f9e8ccebc5a8ddb57bccc443a2ca0868ac\",\n \"f0f9e8ccebc5a8ddb57bccc44eb3d32b8cbe08589e\",\n \"f7fcf0e0f3dbccebc5a8ddb57bccc44eb3d32b8cbe08589e\",\n \"f7fcf0e0f3dbccebc5a8ddb57bccc44eb3d32b8cbe0868ac084081\"\n).map(colors_default);\nvar GnBu_default = ramp_default(scheme12);\n\n// ../../node_modules/d3-scale-chromatic/src/sequential-multi/OrRd.js\nvar scheme13 = new Array(3).concat(\n \"fee8c8fdbb84e34a33\",\n \"fef0d9fdcc8afc8d59d7301f\",\n \"fef0d9fdcc8afc8d59e34a33b30000\",\n \"fef0d9fdd49efdbb84fc8d59e34a33b30000\",\n \"fef0d9fdd49efdbb84fc8d59ef6548d7301f990000\",\n \"fff7ecfee8c8fdd49efdbb84fc8d59ef6548d7301f990000\",\n \"fff7ecfee8c8fdd49efdbb84fc8d59ef6548d7301fb300007f0000\"\n).map(colors_default);\nvar OrRd_default = ramp_default(scheme13);\n\n// ../../node_modules/d3-scale-chromatic/src/sequential-multi/PuBuGn.js\nvar scheme14 = new Array(3).concat(\n \"ece2f0a6bddb1c9099\",\n \"f6eff7bdc9e167a9cf02818a\",\n \"f6eff7bdc9e167a9cf1c9099016c59\",\n \"f6eff7d0d1e6a6bddb67a9cf1c9099016c59\",\n \"f6eff7d0d1e6a6bddb67a9cf3690c002818a016450\",\n \"fff7fbece2f0d0d1e6a6bddb67a9cf3690c002818a016450\",\n \"fff7fbece2f0d0d1e6a6bddb67a9cf3690c002818a016c59014636\"\n).map(colors_default);\nvar PuBuGn_default = ramp_default(scheme14);\n\n// ../../node_modules/d3-scale-chromatic/src/sequential-multi/PuBu.js\nvar scheme15 = new Array(3).concat(\n \"ece7f2a6bddb2b8cbe\",\n \"f1eef6bdc9e174a9cf0570b0\",\n \"f1eef6bdc9e174a9cf2b8cbe045a8d\",\n \"f1eef6d0d1e6a6bddb74a9cf2b8cbe045a8d\",\n \"f1eef6d0d1e6a6bddb74a9cf3690c00570b0034e7b\",\n \"fff7fbece7f2d0d1e6a6bddb74a9cf3690c00570b0034e7b\",\n \"fff7fbece7f2d0d1e6a6bddb74a9cf3690c00570b0045a8d023858\"\n).map(colors_default);\nvar PuBu_default = ramp_default(scheme15);\n\n// ../../node_modules/d3-scale-chromatic/src/sequential-multi/PuRd.js\nvar scheme16 = new Array(3).concat(\n \"e7e1efc994c7dd1c77\",\n \"f1eef6d7b5d8df65b0ce1256\",\n \"f1eef6d7b5d8df65b0dd1c77980043\",\n \"f1eef6d4b9dac994c7df65b0dd1c77980043\",\n \"f1eef6d4b9dac994c7df65b0e7298ace125691003f\",\n \"f7f4f9e7e1efd4b9dac994c7df65b0e7298ace125691003f\",\n \"f7f4f9e7e1efd4b9dac994c7df65b0e7298ace125698004367001f\"\n).map(colors_default);\nvar PuRd_default = ramp_default(scheme16);\n\n// ../../node_modules/d3-scale-chromatic/src/sequential-multi/RdPu.js\nvar scheme17 = new Array(3).concat(\n \"fde0ddfa9fb5c51b8a\",\n \"feebe2fbb4b9f768a1ae017e\",\n \"feebe2fbb4b9f768a1c51b8a7a0177\",\n \"feebe2fcc5c0fa9fb5f768a1c51b8a7a0177\",\n \"feebe2fcc5c0fa9fb5f768a1dd3497ae017e7a0177\",\n \"fff7f3fde0ddfcc5c0fa9fb5f768a1dd3497ae017e7a0177\",\n \"fff7f3fde0ddfcc5c0fa9fb5f768a1dd3497ae017e7a017749006a\"\n).map(colors_default);\nvar RdPu_default = ramp_default(scheme17);\n\n// ../../node_modules/d3-scale-chromatic/src/sequential-multi/YlGnBu.js\nvar scheme18 = new Array(3).concat(\n \"edf8b17fcdbb2c7fb8\",\n \"ffffcca1dab441b6c4225ea8\",\n \"ffffcca1dab441b6c42c7fb8253494\",\n \"ffffccc7e9b47fcdbb41b6c42c7fb8253494\",\n \"ffffccc7e9b47fcdbb41b6c41d91c0225ea80c2c84\",\n \"ffffd9edf8b1c7e9b47fcdbb41b6c41d91c0225ea80c2c84\",\n \"ffffd9edf8b1c7e9b47fcdbb41b6c41d91c0225ea8253494081d58\"\n).map(colors_default);\nvar YlGnBu_default = ramp_default(scheme18);\n\n// ../../node_modules/d3-scale-chromatic/src/sequential-multi/YlGn.js\nvar scheme19 = new Array(3).concat(\n \"f7fcb9addd8e31a354\",\n \"ffffccc2e69978c679238443\",\n \"ffffccc2e69978c67931a354006837\",\n \"ffffccd9f0a3addd8e78c67931a354006837\",\n \"ffffccd9f0a3addd8e78c67941ab5d238443005a32\",\n \"ffffe5f7fcb9d9f0a3addd8e78c67941ab5d238443005a32\",\n \"ffffe5f7fcb9d9f0a3addd8e78c67941ab5d238443006837004529\"\n).map(colors_default);\nvar YlGn_default = ramp_default(scheme19);\n\n// ../../node_modules/d3-scale-chromatic/src/sequential-multi/YlOrBr.js\nvar scheme20 = new Array(3).concat(\n \"fff7bcfec44fd95f0e\",\n \"ffffd4fed98efe9929cc4c02\",\n \"ffffd4fed98efe9929d95f0e993404\",\n \"ffffd4fee391fec44ffe9929d95f0e993404\",\n \"ffffd4fee391fec44ffe9929ec7014cc4c028c2d04\",\n \"ffffe5fff7bcfee391fec44ffe9929ec7014cc4c028c2d04\",\n \"ffffe5fff7bcfee391fec44ffe9929ec7014cc4c02993404662506\"\n).map(colors_default);\nvar YlOrBr_default = ramp_default(scheme20);\n\n// ../../node_modules/d3-scale-chromatic/src/sequential-multi/YlOrRd.js\nvar scheme21 = new Array(3).concat(\n \"ffeda0feb24cf03b20\",\n \"ffffb2fecc5cfd8d3ce31a1c\",\n \"ffffb2fecc5cfd8d3cf03b20bd0026\",\n \"ffffb2fed976feb24cfd8d3cf03b20bd0026\",\n \"ffffb2fed976feb24cfd8d3cfc4e2ae31a1cb10026\",\n \"ffffccffeda0fed976feb24cfd8d3cfc4e2ae31a1cb10026\",\n \"ffffccffeda0fed976feb24cfd8d3cfc4e2ae31a1cbd0026800026\"\n).map(colors_default);\nvar YlOrRd_default = ramp_default(scheme21);\n\n// ../../node_modules/d3-scale-chromatic/src/sequential-single/Blues.js\nvar scheme22 = new Array(3).concat(\n \"deebf79ecae13182bd\",\n \"eff3ffbdd7e76baed62171b5\",\n \"eff3ffbdd7e76baed63182bd08519c\",\n \"eff3ffc6dbef9ecae16baed63182bd08519c\",\n \"eff3ffc6dbef9ecae16baed64292c62171b5084594\",\n \"f7fbffdeebf7c6dbef9ecae16baed64292c62171b5084594\",\n \"f7fbffdeebf7c6dbef9ecae16baed64292c62171b508519c08306b\"\n).map(colors_default);\nvar Blues_default = ramp_default(scheme22);\n\n// ../../node_modules/d3-scale-chromatic/src/sequential-single/Greens.js\nvar scheme23 = new Array(3).concat(\n \"e5f5e0a1d99b31a354\",\n \"edf8e9bae4b374c476238b45\",\n \"edf8e9bae4b374c47631a354006d2c\",\n \"edf8e9c7e9c0a1d99b74c47631a354006d2c\",\n \"edf8e9c7e9c0a1d99b74c47641ab5d238b45005a32\",\n \"f7fcf5e5f5e0c7e9c0a1d99b74c47641ab5d238b45005a32\",\n \"f7fcf5e5f5e0c7e9c0a1d99b74c47641ab5d238b45006d2c00441b\"\n).map(colors_default);\nvar Greens_default = ramp_default(scheme23);\n\n// ../../node_modules/d3-scale-chromatic/src/sequential-single/Greys.js\nvar scheme24 = new Array(3).concat(\n \"f0f0f0bdbdbd636363\",\n \"f7f7f7cccccc969696525252\",\n \"f7f7f7cccccc969696636363252525\",\n \"f7f7f7d9d9d9bdbdbd969696636363252525\",\n \"f7f7f7d9d9d9bdbdbd969696737373525252252525\",\n \"fffffff0f0f0d9d9d9bdbdbd969696737373525252252525\",\n \"fffffff0f0f0d9d9d9bdbdbd969696737373525252252525000000\"\n).map(colors_default);\nvar Greys_default = ramp_default(scheme24);\n\n// ../../node_modules/d3-scale-chromatic/src/sequential-single/Purples.js\nvar scheme25 = new Array(3).concat(\n \"efedf5bcbddc756bb1\",\n \"f2f0f7cbc9e29e9ac86a51a3\",\n \"f2f0f7cbc9e29e9ac8756bb154278f\",\n \"f2f0f7dadaebbcbddc9e9ac8756bb154278f\",\n \"f2f0f7dadaebbcbddc9e9ac8807dba6a51a34a1486\",\n \"fcfbfdefedf5dadaebbcbddc9e9ac8807dba6a51a34a1486\",\n \"fcfbfdefedf5dadaebbcbddc9e9ac8807dba6a51a354278f3f007d\"\n).map(colors_default);\nvar Purples_default = ramp_default(scheme25);\n\n// ../../node_modules/d3-scale-chromatic/src/sequential-single/Reds.js\nvar scheme26 = new Array(3).concat(\n \"fee0d2fc9272de2d26\",\n \"fee5d9fcae91fb6a4acb181d\",\n \"fee5d9fcae91fb6a4ade2d26a50f15\",\n \"fee5d9fcbba1fc9272fb6a4ade2d26a50f15\",\n \"fee5d9fcbba1fc9272fb6a4aef3b2ccb181d99000d\",\n \"fff5f0fee0d2fcbba1fc9272fb6a4aef3b2ccb181d99000d\",\n \"fff5f0fee0d2fcbba1fc9272fb6a4aef3b2ccb181da50f1567000d\"\n).map(colors_default);\nvar Reds_default = ramp_default(scheme26);\n\n// ../../node_modules/d3-scale-chromatic/src/sequential-single/Oranges.js\nvar scheme27 = new Array(3).concat(\n \"fee6cefdae6be6550d\",\n \"feeddefdbe85fd8d3cd94701\",\n \"feeddefdbe85fd8d3ce6550da63603\",\n \"feeddefdd0a2fdae6bfd8d3ce6550da63603\",\n \"feeddefdd0a2fdae6bfd8d3cf16913d948018c2d04\",\n \"fff5ebfee6cefdd0a2fdae6bfd8d3cf16913d948018c2d04\",\n \"fff5ebfee6cefdd0a2fdae6bfd8d3cf16913d94801a636037f2704\"\n).map(colors_default);\nvar Oranges_default = ramp_default(scheme27);\n\n// ../../node_modules/d3-scale-chromatic/src/sequential-multi/cividis.js\nfunction cividis_default(t) {\n t = Math.max(0, Math.min(1, t));\n return \"rgb(\" + Math.max(0, Math.min(255, Math.round(-4.54 - t * (35.34 - t * (2381.73 - t * (6402.7 - t * (7024.72 - t * 2710.57))))))) + \", \" + Math.max(0, Math.min(255, Math.round(32.49 + t * (170.73 + t * (52.82 - t * (131.46 - t * (176.58 - t * 67.37))))))) + \", \" + Math.max(0, Math.min(255, Math.round(81.24 + t * (442.36 - t * (2482.43 - t * (6167.24 - t * (6614.94 - t * 2475.67))))))) + \")\";\n}\n\n// ../../node_modules/d3-scale-chromatic/src/sequential-multi/cubehelix.js\nvar cubehelix_default2 = cubehelixLong(cubehelix(300, 0.5, 0), cubehelix(-240, 0.5, 1));\n\n// ../../node_modules/d3-scale-chromatic/src/sequential-multi/rainbow.js\nvar warm = cubehelixLong(cubehelix(-100, 0.75, 0.35), cubehelix(80, 1.5, 0.8));\nvar cool = cubehelixLong(cubehelix(260, 0.75, 0.35), cubehelix(80, 1.5, 0.8));\nvar c = cubehelix();\nfunction rainbow_default(t) {\n if (t < 0 || t > 1) t -= Math.floor(t);\n var ts = Math.abs(t - 0.5);\n c.h = 360 * t - 100;\n c.s = 1.5 - 1.5 * ts;\n c.l = 0.8 - 0.9 * ts;\n return c + \"\";\n}\n\n// ../../node_modules/d3-scale-chromatic/src/sequential-multi/sinebow.js\nvar c2 = rgb();\nvar pi_1_3 = Math.PI / 3;\nvar pi_2_3 = Math.PI * 2 / 3;\nfunction sinebow_default(t) {\n var x3;\n t = (0.5 - t) * Math.PI;\n c2.r = 255 * (x3 = Math.sin(t)) * x3;\n c2.g = 255 * (x3 = Math.sin(t + pi_1_3)) * x3;\n c2.b = 255 * (x3 = Math.sin(t + pi_2_3)) * x3;\n return c2 + \"\";\n}\n\n// ../../node_modules/d3-scale-chromatic/src/sequential-multi/turbo.js\nfunction turbo_default(t) {\n t = Math.max(0, Math.min(1, t));\n return \"rgb(\" + Math.max(0, Math.min(255, Math.round(34.61 + t * (1172.33 - t * (10793.56 - t * (33300.12 - t * (38394.49 - t * 14825.05))))))) + \", \" + Math.max(0, Math.min(255, Math.round(23.31 + t * (557.33 + t * (1225.33 - t * (3574.96 - t * (1073.77 + t * 707.56))))))) + \", \" + Math.max(0, Math.min(255, Math.round(27.2 + t * (3211.1 - t * (15327.97 - t * (27814 - t * (22569.18 - t * 6838.66))))))) + \")\";\n}\n\n// ../../node_modules/d3-scale-chromatic/src/sequential-multi/viridis.js\nfunction ramp(range3) {\n var n = range3.length;\n return function(t) {\n return range3[Math.max(0, Math.min(n - 1, Math.floor(t * n)))];\n };\n}\nvar viridis_default = ramp(colors_default(\"44015444025645045745055946075a46085c460a5d460b5e470d60470e6147106347116447136548146748166848176948186a481a6c481b6d481c6e481d6f481f70482071482173482374482475482576482677482878482979472a7a472c7a472d7b472e7c472f7d46307e46327e46337f463480453581453781453882443983443a83443b84433d84433e85423f854240864241864142874144874045884046883f47883f48893e49893e4a893e4c8a3d4d8a3d4e8a3c4f8a3c508b3b518b3b528b3a538b3a548c39558c39568c38588c38598c375a8c375b8d365c8d365d8d355e8d355f8d34608d34618d33628d33638d32648e32658e31668e31678e31688e30698e306a8e2f6b8e2f6c8e2e6d8e2e6e8e2e6f8e2d708e2d718e2c718e2c728e2c738e2b748e2b758e2a768e2a778e2a788e29798e297a8e297b8e287c8e287d8e277e8e277f8e27808e26818e26828e26828e25838e25848e25858e24868e24878e23888e23898e238a8d228b8d228c8d228d8d218e8d218f8d21908d21918c20928c20928c20938c1f948c1f958b1f968b1f978b1f988b1f998a1f9a8a1e9b8a1e9c891e9d891f9e891f9f881fa0881fa1881fa1871fa28720a38620a48621a58521a68522a78522a88423a98324aa8325ab8225ac8226ad8127ad8128ae8029af7f2ab07f2cb17e2db27d2eb37c2fb47c31b57b32b67a34b67935b77937b87838b9773aba763bbb753dbc743fbc7340bd7242be7144bf7046c06f48c16e4ac16d4cc26c4ec36b50c46a52c56954c56856c66758c7655ac8645cc8635ec96260ca6063cb5f65cb5e67cc5c69cd5b6ccd5a6ece5870cf5773d05675d05477d1537ad1517cd2507fd34e81d34d84d44b86d54989d5488bd6468ed64590d74393d74195d84098d83e9bd93c9dd93ba0da39a2da37a5db36a8db34aadc32addc30b0dd2fb2dd2db5de2bb8de29bade28bddf26c0df25c2df23c5e021c8e020cae11fcde11dd0e11cd2e21bd5e21ad8e219dae319dde318dfe318e2e418e5e419e7e419eae51aece51befe51cf1e51df4e61ef6e620f8e621fbe723fde725\"));\nvar magma = ramp(colors_default(\"00000401000501010601010802010902020b02020d03030f03031204041405041606051806051a07061c08071e0907200a08220b09240c09260d0a290e0b2b100b2d110c2f120d31130d34140e36150e38160f3b180f3d19103f1a10421c10441d11471e114920114b21114e22115024125325125527125829115a2a115c2c115f2d11612f116331116533106734106936106b38106c390f6e3b0f703d0f713f0f72400f74420f75440f764510774710784910784a10794c117a4e117b4f127b51127c52137c54137d56147d57157e59157e5a167e5c167f5d177f5f187f601880621980641a80651a80671b80681c816a1c816b1d816d1d816e1e81701f81721f817320817521817621817822817922827b23827c23827e24828025828125818326818426818627818827818928818b29818c29818e2a81902a81912b81932b80942c80962c80982d80992d809b2e7f9c2e7f9e2f7fa02f7fa1307ea3307ea5317ea6317da8327daa337dab337cad347cae347bb0357bb2357bb3367ab5367ab73779b83779ba3878bc3978bd3977bf3a77c03a76c23b75c43c75c53c74c73d73c83e73ca3e72cc3f71cd4071cf4070d0416fd2426fd3436ed5446dd6456cd8456cd9466bdb476adc4869de4968df4a68e04c67e24d66e34e65e44f64e55064e75263e85362e95462ea5661eb5760ec5860ed5a5fee5b5eef5d5ef05f5ef1605df2625df2645cf3655cf4675cf4695cf56b5cf66c5cf66e5cf7705cf7725cf8745cf8765cf9785df9795df97b5dfa7d5efa7f5efa815ffb835ffb8560fb8761fc8961fc8a62fc8c63fc8e64fc9065fd9266fd9467fd9668fd9869fd9a6afd9b6bfe9d6cfe9f6dfea16efea36ffea571fea772fea973feaa74feac76feae77feb078feb27afeb47bfeb67cfeb77efeb97ffebb81febd82febf84fec185fec287fec488fec68afec88cfeca8dfecc8ffecd90fecf92fed194fed395fed597fed799fed89afdda9cfddc9efddea0fde0a1fde2a3fde3a5fde5a7fde7a9fde9aafdebacfcecaefceeb0fcf0b2fcf2b4fcf4b6fcf6b8fcf7b9fcf9bbfcfbbdfcfdbf\"));\nvar inferno = ramp(colors_default(\"00000401000501010601010802010a02020c02020e03021004031204031405041706041907051b08051d09061f0a07220b07240c08260d08290e092b10092d110a30120a32140b34150b37160b39180c3c190c3e1b0c411c0c431e0c451f0c48210c4a230c4c240c4f260c51280b53290b552b0b572d0b592f0a5b310a5c320a5e340a5f3609613809623909633b09643d09653e0966400a67420a68440a68450a69470b6a490b6a4a0c6b4c0c6b4d0d6c4f0d6c510e6c520e6d540f6d550f6d57106e59106e5a116e5c126e5d126e5f136e61136e62146e64156e65156e67166e69166e6a176e6c186e6d186e6f196e71196e721a6e741a6e751b6e771c6d781c6d7a1d6d7c1d6d7d1e6d7f1e6c801f6c82206c84206b85216b87216b88226a8a226a8c23698d23698f24699025689225689326679526679727669827669a28659b29649d29649f2a63a02a63a22b62a32c61a52c60a62d60a82e5fa92e5eab2f5ead305dae305cb0315bb1325ab3325ab43359b63458b73557b93556ba3655bc3754bd3853bf3952c03a51c13a50c33b4fc43c4ec63d4dc73e4cc83f4bca404acb4149cc4248ce4347cf4446d04545d24644d34743d44842d54a41d74b3fd84c3ed94d3dda4e3cdb503bdd513ade5238df5337e05536e15635e25734e35933e45a31e55c30e65d2fe75e2ee8602de9612bea632aeb6429eb6628ec6726ed6925ee6a24ef6c23ef6e21f06f20f1711ff1731df2741cf3761bf37819f47918f57b17f57d15f67e14f68013f78212f78410f8850ff8870ef8890cf98b0bf98c0af98e09fa9008fa9207fa9407fb9606fb9706fb9906fb9b06fb9d07fc9f07fca108fca309fca50afca60cfca80dfcaa0ffcac11fcae12fcb014fcb216fcb418fbb61afbb81dfbba1ffbbc21fbbe23fac026fac228fac42afac62df9c72ff9c932f9cb35f8cd37f8cf3af7d13df7d340f6d543f6d746f5d949f5db4cf4dd4ff4df53f4e156f3e35af3e55df2e661f2e865f2ea69f1ec6df1ed71f1ef75f1f179f2f27df2f482f3f586f3f68af4f88ef5f992f6fa96f8fb9af9fc9dfafda1fcffa4\"));\nvar plasma = ramp(colors_default(\"0d088710078813078916078a19068c1b068d1d068e20068f2206902406912605912805922a05932c05942e05952f059631059733059735049837049938049a3a049a3c049b3e049c3f049c41049d43039e44039e46039f48039f4903a04b03a14c02a14e02a25002a25102a35302a35502a45601a45801a45901a55b01a55c01a65e01a66001a66100a76300a76400a76600a76700a86900a86a00a86c00a86e00a86f00a87100a87201a87401a87501a87701a87801a87a02a87b02a87d03a87e03a88004a88104a78305a78405a78606a68707a68808a68a09a58b0aa58d0ba58e0ca48f0da4910ea3920fa39410a29511a19613a19814a099159f9a169f9c179e9d189d9e199da01a9ca11b9ba21d9aa31e9aa51f99a62098a72197a82296aa2395ab2494ac2694ad2793ae2892b02991b12a90b22b8fb32c8eb42e8db52f8cb6308bb7318ab83289ba3388bb3488bc3587bd3786be3885bf3984c03a83c13b82c23c81c33d80c43e7fc5407ec6417dc7427cc8437bc9447aca457acb4679cc4778cc4977cd4a76ce4b75cf4c74d04d73d14e72d24f71d35171d45270d5536fd5546ed6556dd7566cd8576bd9586ada5a6ada5b69db5c68dc5d67dd5e66de5f65de6164df6263e06363e16462e26561e26660e3685fe4695ee56a5de56b5de66c5ce76e5be76f5ae87059e97158e97257ea7457eb7556eb7655ec7754ed7953ed7a52ee7b51ef7c51ef7e50f07f4ff0804ef1814df1834cf2844bf3854bf3874af48849f48948f58b47f58c46f68d45f68f44f79044f79143f79342f89441f89540f9973ff9983ef99a3efa9b3dfa9c3cfa9e3bfb9f3afba139fba238fca338fca537fca636fca835fca934fdab33fdac33fdae32fdaf31fdb130fdb22ffdb42ffdb52efeb72dfeb82cfeba2cfebb2bfebd2afebe2afec029fdc229fdc328fdc527fdc627fdc827fdca26fdcb26fccd25fcce25fcd025fcd225fbd324fbd524fbd724fad824fada24f9dc24f9dd25f8df25f8e125f7e225f7e425f6e626f6e826f5e926f5eb27f4ed27f3ee27f3f027f2f227f1f426f1f525f0f724f0f921\"));\n\n// ../../node_modules/d3-shape/src/constant.js\nfunction constant_default5(x3) {\n return function constant2() {\n return x3;\n };\n}\n\n// ../../node_modules/d3-shape/src/math.js\nvar cos2 = Math.cos;\nvar min4 = Math.min;\nvar sin2 = Math.sin;\nvar sqrt3 = Math.sqrt;\nvar epsilon7 = 1e-12;\nvar pi3 = Math.PI;\nvar halfPi2 = pi3 / 2;\nvar tau4 = 2 * pi3;\n\n// ../../node_modules/d3-shape/src/path.js\nfunction withPath(shape) {\n let digits = 3;\n shape.digits = function(_) {\n if (!arguments.length) return digits;\n if (_ == null) {\n digits = null;\n } else {\n const d = Math.floor(_);\n if (!(d >= 0)) throw new RangeError(`invalid digits: ${_}`);\n digits = d;\n }\n return shape;\n };\n return () => new Path(digits);\n}\n\n// ../../node_modules/d3-shape/src/array.js\nvar slice2 = Array.prototype.slice;\nfunction array_default(x3) {\n return typeof x3 === \"object\" && \"length\" in x3 ? x3 : Array.from(x3);\n}\n\n// ../../node_modules/d3-shape/src/curve/linear.js\nfunction Linear(context) {\n this._context = context;\n}\nLinear.prototype = {\n areaStart: function() {\n this._line = 0;\n },\n areaEnd: function() {\n this._line = NaN;\n },\n lineStart: function() {\n this._point = 0;\n },\n lineEnd: function() {\n if (this._line || this._line !== 0 && this._point === 1) this._context.closePath();\n this._line = 1 - this._line;\n },\n point: function(x3, y3) {\n x3 = +x3, y3 = +y3;\n switch (this._point) {\n case 0:\n this._point = 1;\n this._line ? this._context.lineTo(x3, y3) : this._context.moveTo(x3, y3);\n break;\n case 1:\n this._point = 2;\n // falls through\n default:\n this._context.lineTo(x3, y3);\n break;\n }\n }\n};\nfunction linear_default(context) {\n return new Linear(context);\n}\n\n// ../../node_modules/d3-shape/src/point.js\nfunction x2(p) {\n return p[0];\n}\nfunction y2(p) {\n return p[1];\n}\n\n// ../../node_modules/d3-shape/src/line.js\nfunction line_default2(x3, y3) {\n var defined2 = constant_default5(true), context = null, curve = linear_default, output = null, path2 = withPath(line3);\n x3 = typeof x3 === \"function\" ? x3 : x3 === void 0 ? x2 : constant_default5(x3);\n y3 = typeof y3 === \"function\" ? y3 : y3 === void 0 ? y2 : constant_default5(y3);\n function line3(data) {\n var i, n = (data = array_default(data)).length, d, defined0 = false, buffer2;\n if (context == null) output = curve(buffer2 = path2());\n for (i = 0; i <= n; ++i) {\n if (!(i < n && defined2(d = data[i], i, data)) === defined0) {\n if (defined0 = !defined0) output.lineStart();\n else output.lineEnd();\n }\n if (defined0) output.point(+x3(d, i, data), +y3(d, i, data));\n }\n if (buffer2) return output = null, buffer2 + \"\" || null;\n }\n line3.x = function(_) {\n return arguments.length ? (x3 = typeof _ === \"function\" ? _ : constant_default5(+_), line3) : x3;\n };\n line3.y = function(_) {\n return arguments.length ? (y3 = typeof _ === \"function\" ? _ : constant_default5(+_), line3) : y3;\n };\n line3.defined = function(_) {\n return arguments.length ? (defined2 = typeof _ === \"function\" ? _ : constant_default5(!!_), line3) : defined2;\n };\n line3.curve = function(_) {\n return arguments.length ? (curve = _, context != null && (output = curve(context)), line3) : curve;\n };\n line3.context = function(_) {\n return arguments.length ? (_ == null ? context = output = null : output = curve(context = _), line3) : context;\n };\n return line3;\n}\n\n// ../../node_modules/d3-shape/src/area.js\nfunction area_default3(x06, y06, y12) {\n var x12 = null, defined2 = constant_default5(true), context = null, curve = linear_default, output = null, path2 = withPath(area3);\n x06 = typeof x06 === \"function\" ? x06 : x06 === void 0 ? x2 : constant_default5(+x06);\n y06 = typeof y06 === \"function\" ? y06 : y06 === void 0 ? constant_default5(0) : constant_default5(+y06);\n y12 = typeof y12 === \"function\" ? y12 : y12 === void 0 ? y2 : constant_default5(+y12);\n function area3(data) {\n var i, j, k2, n = (data = array_default(data)).length, d, defined0 = false, buffer2, x0z = new Array(n), y0z = new Array(n);\n if (context == null) output = curve(buffer2 = path2());\n for (i = 0; i <= n; ++i) {\n if (!(i < n && defined2(d = data[i], i, data)) === defined0) {\n if (defined0 = !defined0) {\n j = i;\n output.areaStart();\n output.lineStart();\n } else {\n output.lineEnd();\n output.lineStart();\n for (k2 = i - 1; k2 >= j; --k2) {\n output.point(x0z[k2], y0z[k2]);\n }\n output.lineEnd();\n output.areaEnd();\n }\n }\n if (defined0) {\n x0z[i] = +x06(d, i, data), y0z[i] = +y06(d, i, data);\n output.point(x12 ? +x12(d, i, data) : x0z[i], y12 ? +y12(d, i, data) : y0z[i]);\n }\n }\n if (buffer2) return output = null, buffer2 + \"\" || null;\n }\n function arealine() {\n return line_default2().defined(defined2).curve(curve).context(context);\n }\n area3.x = function(_) {\n return arguments.length ? (x06 = typeof _ === \"function\" ? _ : constant_default5(+_), x12 = null, area3) : x06;\n };\n area3.x0 = function(_) {\n return arguments.length ? (x06 = typeof _ === \"function\" ? _ : constant_default5(+_), area3) : x06;\n };\n area3.x1 = function(_) {\n return arguments.length ? (x12 = _ == null ? null : typeof _ === \"function\" ? _ : constant_default5(+_), area3) : x12;\n };\n area3.y = function(_) {\n return arguments.length ? (y06 = typeof _ === \"function\" ? _ : constant_default5(+_), y12 = null, area3) : y06;\n };\n area3.y0 = function(_) {\n return arguments.length ? (y06 = typeof _ === \"function\" ? _ : constant_default5(+_), area3) : y06;\n };\n area3.y1 = function(_) {\n return arguments.length ? (y12 = _ == null ? null : typeof _ === \"function\" ? _ : constant_default5(+_), area3) : y12;\n };\n area3.lineX0 = area3.lineY0 = function() {\n return arealine().x(x06).y(y06);\n };\n area3.lineY1 = function() {\n return arealine().x(x06).y(y12);\n };\n area3.lineX1 = function() {\n return arealine().x(x12).y(y06);\n };\n area3.defined = function(_) {\n return arguments.length ? (defined2 = typeof _ === \"function\" ? _ : constant_default5(!!_), area3) : defined2;\n };\n area3.curve = function(_) {\n return arguments.length ? (curve = _, context != null && (output = curve(context)), area3) : curve;\n };\n area3.context = function(_) {\n return arguments.length ? (_ == null ? context = output = null : output = curve(context = _), area3) : context;\n };\n return area3;\n}\n\n// ../../node_modules/d3-shape/src/curve/bump.js\nvar Bump = class {\n constructor(context, x3) {\n this._context = context;\n this._x = x3;\n }\n areaStart() {\n this._line = 0;\n }\n areaEnd() {\n this._line = NaN;\n }\n lineStart() {\n this._point = 0;\n }\n lineEnd() {\n if (this._line || this._line !== 0 && this._point === 1) this._context.closePath();\n this._line = 1 - this._line;\n }\n point(x3, y3) {\n x3 = +x3, y3 = +y3;\n switch (this._point) {\n case 0: {\n this._point = 1;\n if (this._line) this._context.lineTo(x3, y3);\n else this._context.moveTo(x3, y3);\n break;\n }\n case 1:\n this._point = 2;\n // falls through\n default: {\n if (this._x) this._context.bezierCurveTo(this._x0 = (this._x0 + x3) / 2, this._y0, this._x0, y3, x3, y3);\n else this._context.bezierCurveTo(this._x0, this._y0 = (this._y0 + y3) / 2, x3, this._y0, x3, y3);\n break;\n }\n }\n this._x0 = x3, this._y0 = y3;\n }\n};\nfunction bumpX(context) {\n return new Bump(context, true);\n}\nfunction bumpY(context) {\n return new Bump(context, false);\n}\n\n// ../../node_modules/d3-shape/src/symbol/asterisk.js\nvar sqrt32 = sqrt3(3);\nvar asterisk_default = {\n draw(context, size) {\n const r = sqrt3(size + min4(size / 28, 0.75)) * 0.59436;\n const t = r / 2;\n const u4 = t * sqrt32;\n context.moveTo(0, r);\n context.lineTo(0, -r);\n context.moveTo(-u4, -t);\n context.lineTo(u4, t);\n context.moveTo(-u4, t);\n context.lineTo(u4, -t);\n }\n};\n\n// ../../node_modules/d3-shape/src/symbol/circle.js\nvar circle_default2 = {\n draw(context, size) {\n const r = sqrt3(size / pi3);\n context.moveTo(r, 0);\n context.arc(0, 0, r, 0, tau4);\n }\n};\n\n// ../../node_modules/d3-shape/src/symbol/cross.js\nvar cross_default = {\n draw(context, size) {\n const r = sqrt3(size / 5) / 2;\n context.moveTo(-3 * r, -r);\n context.lineTo(-r, -r);\n context.lineTo(-r, -3 * r);\n context.lineTo(r, -3 * r);\n context.lineTo(r, -r);\n context.lineTo(3 * r, -r);\n context.lineTo(3 * r, r);\n context.lineTo(r, r);\n context.lineTo(r, 3 * r);\n context.lineTo(-r, 3 * r);\n context.lineTo(-r, r);\n context.lineTo(-3 * r, r);\n context.closePath();\n }\n};\n\n// ../../node_modules/d3-shape/src/symbol/diamond.js\nvar tan30 = sqrt3(1 / 3);\nvar tan30_2 = tan30 * 2;\nvar diamond_default = {\n draw(context, size) {\n const y3 = sqrt3(size / tan30_2);\n const x3 = y3 * tan30;\n context.moveTo(0, -y3);\n context.lineTo(x3, 0);\n context.lineTo(0, y3);\n context.lineTo(-x3, 0);\n context.closePath();\n }\n};\n\n// ../../node_modules/d3-shape/src/symbol/diamond2.js\nvar diamond2_default = {\n draw(context, size) {\n const r = sqrt3(size) * 0.62625;\n context.moveTo(0, -r);\n context.lineTo(r, 0);\n context.lineTo(0, r);\n context.lineTo(-r, 0);\n context.closePath();\n }\n};\n\n// ../../node_modules/d3-shape/src/symbol/plus.js\nvar plus_default = {\n draw(context, size) {\n const r = sqrt3(size - min4(size / 7, 2)) * 0.87559;\n context.moveTo(-r, 0);\n context.lineTo(r, 0);\n context.moveTo(0, r);\n context.lineTo(0, -r);\n }\n};\n\n// ../../node_modules/d3-shape/src/symbol/square.js\nvar square_default = {\n draw(context, size) {\n const w = sqrt3(size);\n const x3 = -w / 2;\n context.rect(x3, x3, w, w);\n }\n};\n\n// ../../node_modules/d3-shape/src/symbol/square2.js\nvar square2_default = {\n draw(context, size) {\n const r = sqrt3(size) * 0.4431;\n context.moveTo(r, r);\n context.lineTo(r, -r);\n context.lineTo(-r, -r);\n context.lineTo(-r, r);\n context.closePath();\n }\n};\n\n// ../../node_modules/d3-shape/src/symbol/star.js\nvar ka = 0.8908130915292852;\nvar kr = sin2(pi3 / 10) / sin2(7 * pi3 / 10);\nvar kx = sin2(tau4 / 10) * kr;\nvar ky = -cos2(tau4 / 10) * kr;\nvar star_default = {\n draw(context, size) {\n const r = sqrt3(size * ka);\n const x3 = kx * r;\n const y3 = ky * r;\n context.moveTo(0, -r);\n context.lineTo(x3, y3);\n for (let i = 1; i < 5; ++i) {\n const a2 = tau4 * i / 5;\n const c4 = cos2(a2);\n const s2 = sin2(a2);\n context.lineTo(s2 * r, -c4 * r);\n context.lineTo(c4 * x3 - s2 * y3, s2 * x3 + c4 * y3);\n }\n context.closePath();\n }\n};\n\n// ../../node_modules/d3-shape/src/symbol/triangle.js\nvar sqrt33 = sqrt3(3);\nvar triangle_default = {\n draw(context, size) {\n const y3 = -sqrt3(size / (sqrt33 * 3));\n context.moveTo(0, y3 * 2);\n context.lineTo(-sqrt33 * y3, -y3);\n context.lineTo(sqrt33 * y3, -y3);\n context.closePath();\n }\n};\n\n// ../../node_modules/d3-shape/src/symbol/triangle2.js\nvar sqrt34 = sqrt3(3);\nvar triangle2_default = {\n draw(context, size) {\n const s2 = sqrt3(size) * 0.6824;\n const t = s2 / 2;\n const u4 = s2 * sqrt34 / 2;\n context.moveTo(0, -s2);\n context.lineTo(u4, t);\n context.lineTo(-u4, t);\n context.closePath();\n }\n};\n\n// ../../node_modules/d3-shape/src/symbol/wye.js\nvar c3 = -0.5;\nvar s = sqrt3(3) / 2;\nvar k = 1 / sqrt3(12);\nvar a = (k / 2 + 1) * 3;\nvar wye_default = {\n draw(context, size) {\n const r = sqrt3(size / a);\n const x06 = r / 2, y06 = r * k;\n const x12 = x06, y12 = r * k + r;\n const x22 = -x12, y22 = y12;\n context.moveTo(x06, y06);\n context.lineTo(x12, y12);\n context.lineTo(x22, y22);\n context.lineTo(c3 * x06 - s * y06, s * x06 + c3 * y06);\n context.lineTo(c3 * x12 - s * y12, s * x12 + c3 * y12);\n context.lineTo(c3 * x22 - s * y22, s * x22 + c3 * y22);\n context.lineTo(c3 * x06 + s * y06, c3 * y06 - s * x06);\n context.lineTo(c3 * x12 + s * y12, c3 * y12 - s * x12);\n context.lineTo(c3 * x22 + s * y22, c3 * y22 - s * x22);\n context.closePath();\n }\n};\n\n// ../../node_modules/d3-shape/src/symbol/times.js\nvar times_default = {\n draw(context, size) {\n const r = sqrt3(size - min4(size / 6, 1.7)) * 0.6189;\n context.moveTo(-r, -r);\n context.lineTo(r, r);\n context.moveTo(-r, r);\n context.lineTo(r, -r);\n }\n};\n\n// ../../node_modules/d3-shape/src/symbol.js\nvar symbolsFill = [\n circle_default2,\n cross_default,\n diamond_default,\n square_default,\n star_default,\n triangle_default,\n wye_default\n];\nvar symbolsStroke = [\n circle_default2,\n plus_default,\n times_default,\n triangle2_default,\n asterisk_default,\n square2_default,\n diamond2_default\n];\n\n// ../../node_modules/d3-shape/src/noop.js\nfunction noop_default2() {\n}\n\n// ../../node_modules/d3-shape/src/curve/basis.js\nfunction point2(that, x3, y3) {\n that._context.bezierCurveTo(\n (2 * that._x0 + that._x1) / 3,\n (2 * that._y0 + that._y1) / 3,\n (that._x0 + 2 * that._x1) / 3,\n (that._y0 + 2 * that._y1) / 3,\n (that._x0 + 4 * that._x1 + x3) / 6,\n (that._y0 + 4 * that._y1 + y3) / 6\n );\n}\nfunction Basis(context) {\n this._context = context;\n}\nBasis.prototype = {\n areaStart: function() {\n this._line = 0;\n },\n areaEnd: function() {\n this._line = NaN;\n },\n lineStart: function() {\n this._x0 = this._x1 = this._y0 = this._y1 = NaN;\n this._point = 0;\n },\n lineEnd: function() {\n switch (this._point) {\n case 3:\n point2(this, this._x1, this._y1);\n // falls through\n case 2:\n this._context.lineTo(this._x1, this._y1);\n break;\n }\n if (this._line || this._line !== 0 && this._point === 1) this._context.closePath();\n this._line = 1 - this._line;\n },\n point: function(x3, y3) {\n x3 = +x3, y3 = +y3;\n switch (this._point) {\n case 0:\n this._point = 1;\n this._line ? this._context.lineTo(x3, y3) : this._context.moveTo(x3, y3);\n break;\n case 1:\n this._point = 2;\n break;\n case 2:\n this._point = 3;\n this._context.lineTo((5 * this._x0 + this._x1) / 6, (5 * this._y0 + this._y1) / 6);\n // falls through\n default:\n point2(this, x3, y3);\n break;\n }\n this._x0 = this._x1, this._x1 = x3;\n this._y0 = this._y1, this._y1 = y3;\n }\n};\nfunction basis_default2(context) {\n return new Basis(context);\n}\n\n// ../../node_modules/d3-shape/src/curve/basisClosed.js\nfunction BasisClosed(context) {\n this._context = context;\n}\nBasisClosed.prototype = {\n areaStart: noop_default2,\n areaEnd: noop_default2,\n lineStart: function() {\n this._x0 = this._x1 = this._x2 = this._x3 = this._x4 = this._y0 = this._y1 = this._y2 = this._y3 = this._y4 = NaN;\n this._point = 0;\n },\n lineEnd: function() {\n switch (this._point) {\n case 1: {\n this._context.moveTo(this._x2, this._y2);\n this._context.closePath();\n break;\n }\n case 2: {\n this._context.moveTo((this._x2 + 2 * this._x3) / 3, (this._y2 + 2 * this._y3) / 3);\n this._context.lineTo((this._x3 + 2 * this._x2) / 3, (this._y3 + 2 * this._y2) / 3);\n this._context.closePath();\n break;\n }\n case 3: {\n this.point(this._x2, this._y2);\n this.point(this._x3, this._y3);\n this.point(this._x4, this._y4);\n break;\n }\n }\n },\n point: function(x3, y3) {\n x3 = +x3, y3 = +y3;\n switch (this._point) {\n case 0:\n this._point = 1;\n this._x2 = x3, this._y2 = y3;\n break;\n case 1:\n this._point = 2;\n this._x3 = x3, this._y3 = y3;\n break;\n case 2:\n this._point = 3;\n this._x4 = x3, this._y4 = y3;\n this._context.moveTo((this._x0 + 4 * this._x1 + x3) / 6, (this._y0 + 4 * this._y1 + y3) / 6);\n break;\n default:\n point2(this, x3, y3);\n break;\n }\n this._x0 = this._x1, this._x1 = x3;\n this._y0 = this._y1, this._y1 = y3;\n }\n};\nfunction basisClosed_default2(context) {\n return new BasisClosed(context);\n}\n\n// ../../node_modules/d3-shape/src/curve/basisOpen.js\nfunction BasisOpen(context) {\n this._context = context;\n}\nBasisOpen.prototype = {\n areaStart: function() {\n this._line = 0;\n },\n areaEnd: function() {\n this._line = NaN;\n },\n lineStart: function() {\n this._x0 = this._x1 = this._y0 = this._y1 = NaN;\n this._point = 0;\n },\n lineEnd: function() {\n if (this._line || this._line !== 0 && this._point === 3) this._context.closePath();\n this._line = 1 - this._line;\n },\n point: function(x3, y3) {\n x3 = +x3, y3 = +y3;\n switch (this._point) {\n case 0:\n this._point = 1;\n break;\n case 1:\n this._point = 2;\n break;\n case 2:\n this._point = 3;\n var x06 = (this._x0 + 4 * this._x1 + x3) / 6, y06 = (this._y0 + 4 * this._y1 + y3) / 6;\n this._line ? this._context.lineTo(x06, y06) : this._context.moveTo(x06, y06);\n break;\n case 3:\n this._point = 4;\n // falls through\n default:\n point2(this, x3, y3);\n break;\n }\n this._x0 = this._x1, this._x1 = x3;\n this._y0 = this._y1, this._y1 = y3;\n }\n};\nfunction basisOpen_default(context) {\n return new BasisOpen(context);\n}\n\n// ../../node_modules/d3-shape/src/curve/bundle.js\nfunction Bundle(context, beta) {\n this._basis = new Basis(context);\n this._beta = beta;\n}\nBundle.prototype = {\n lineStart: function() {\n this._x = [];\n this._y = [];\n this._basis.lineStart();\n },\n lineEnd: function() {\n var x3 = this._x, y3 = this._y, j = x3.length - 1;\n if (j > 0) {\n var x06 = x3[0], y06 = y3[0], dx = x3[j] - x06, dy = y3[j] - y06, i = -1, t;\n while (++i <= j) {\n t = i / j;\n this._basis.point(\n this._beta * x3[i] + (1 - this._beta) * (x06 + t * dx),\n this._beta * y3[i] + (1 - this._beta) * (y06 + t * dy)\n );\n }\n }\n this._x = this._y = null;\n this._basis.lineEnd();\n },\n point: function(x3, y3) {\n this._x.push(+x3);\n this._y.push(+y3);\n }\n};\nvar bundle_default = function custom(beta) {\n function bundle(context) {\n return beta === 1 ? new Basis(context) : new Bundle(context, beta);\n }\n bundle.beta = function(beta2) {\n return custom(+beta2);\n };\n return bundle;\n}(0.85);\n\n// ../../node_modules/d3-shape/src/curve/cardinal.js\nfunction point3(that, x3, y3) {\n that._context.bezierCurveTo(\n that._x1 + that._k * (that._x2 - that._x0),\n that._y1 + that._k * (that._y2 - that._y0),\n that._x2 + that._k * (that._x1 - x3),\n that._y2 + that._k * (that._y1 - y3),\n that._x2,\n that._y2\n );\n}\nfunction Cardinal(context, tension) {\n this._context = context;\n this._k = (1 - tension) / 6;\n}\nCardinal.prototype = {\n areaStart: function() {\n this._line = 0;\n },\n areaEnd: function() {\n this._line = NaN;\n },\n lineStart: function() {\n this._x0 = this._x1 = this._x2 = this._y0 = this._y1 = this._y2 = NaN;\n this._point = 0;\n },\n lineEnd: function() {\n switch (this._point) {\n case 2:\n this._context.lineTo(this._x2, this._y2);\n break;\n case 3:\n point3(this, this._x1, this._y1);\n break;\n }\n if (this._line || this._line !== 0 && this._point === 1) this._context.closePath();\n this._line = 1 - this._line;\n },\n point: function(x3, y3) {\n x3 = +x3, y3 = +y3;\n switch (this._point) {\n case 0:\n this._point = 1;\n this._line ? this._context.lineTo(x3, y3) : this._context.moveTo(x3, y3);\n break;\n case 1:\n this._point = 2;\n this._x1 = x3, this._y1 = y3;\n break;\n case 2:\n this._point = 3;\n // falls through\n default:\n point3(this, x3, y3);\n break;\n }\n this._x0 = this._x1, this._x1 = this._x2, this._x2 = x3;\n this._y0 = this._y1, this._y1 = this._y2, this._y2 = y3;\n }\n};\nvar cardinal_default = function custom2(tension) {\n function cardinal(context) {\n return new Cardinal(context, tension);\n }\n cardinal.tension = function(tension2) {\n return custom2(+tension2);\n };\n return cardinal;\n}(0);\n\n// ../../node_modules/d3-shape/src/curve/cardinalClosed.js\nfunction CardinalClosed(context, tension) {\n this._context = context;\n this._k = (1 - tension) / 6;\n}\nCardinalClosed.prototype = {\n areaStart: noop_default2,\n areaEnd: noop_default2,\n lineStart: function() {\n this._x0 = this._x1 = this._x2 = this._x3 = this._x4 = this._x5 = this._y0 = this._y1 = this._y2 = this._y3 = this._y4 = this._y5 = NaN;\n this._point = 0;\n },\n lineEnd: function() {\n switch (this._point) {\n case 1: {\n this._context.moveTo(this._x3, this._y3);\n this._context.closePath();\n break;\n }\n case 2: {\n this._context.lineTo(this._x3, this._y3);\n this._context.closePath();\n break;\n }\n case 3: {\n this.point(this._x3, this._y3);\n this.point(this._x4, this._y4);\n this.point(this._x5, this._y5);\n break;\n }\n }\n },\n point: function(x3, y3) {\n x3 = +x3, y3 = +y3;\n switch (this._point) {\n case 0:\n this._point = 1;\n this._x3 = x3, this._y3 = y3;\n break;\n case 1:\n this._point = 2;\n this._context.moveTo(this._x4 = x3, this._y4 = y3);\n break;\n case 2:\n this._point = 3;\n this._x5 = x3, this._y5 = y3;\n break;\n default:\n point3(this, x3, y3);\n break;\n }\n this._x0 = this._x1, this._x1 = this._x2, this._x2 = x3;\n this._y0 = this._y1, this._y1 = this._y2, this._y2 = y3;\n }\n};\nvar cardinalClosed_default = function custom3(tension) {\n function cardinal(context) {\n return new CardinalClosed(context, tension);\n }\n cardinal.tension = function(tension2) {\n return custom3(+tension2);\n };\n return cardinal;\n}(0);\n\n// ../../node_modules/d3-shape/src/curve/cardinalOpen.js\nfunction CardinalOpen(context, tension) {\n this._context = context;\n this._k = (1 - tension) / 6;\n}\nCardinalOpen.prototype = {\n areaStart: function() {\n this._line = 0;\n },\n areaEnd: function() {\n this._line = NaN;\n },\n lineStart: function() {\n this._x0 = this._x1 = this._x2 = this._y0 = this._y1 = this._y2 = NaN;\n this._point = 0;\n },\n lineEnd: function() {\n if (this._line || this._line !== 0 && this._point === 3) this._context.closePath();\n this._line = 1 - this._line;\n },\n point: function(x3, y3) {\n x3 = +x3, y3 = +y3;\n switch (this._point) {\n case 0:\n this._point = 1;\n break;\n case 1:\n this._point = 2;\n break;\n case 2:\n this._point = 3;\n this._line ? this._context.lineTo(this._x2, this._y2) : this._context.moveTo(this._x2, this._y2);\n break;\n case 3:\n this._point = 4;\n // falls through\n default:\n point3(this, x3, y3);\n break;\n }\n this._x0 = this._x1, this._x1 = this._x2, this._x2 = x3;\n this._y0 = this._y1, this._y1 = this._y2, this._y2 = y3;\n }\n};\nvar cardinalOpen_default = function custom4(tension) {\n function cardinal(context) {\n return new CardinalOpen(context, tension);\n }\n cardinal.tension = function(tension2) {\n return custom4(+tension2);\n };\n return cardinal;\n}(0);\n\n// ../../node_modules/d3-shape/src/curve/catmullRom.js\nfunction point4(that, x3, y3) {\n var x12 = that._x1, y12 = that._y1, x22 = that._x2, y22 = that._y2;\n if (that._l01_a > epsilon7) {\n var a2 = 2 * that._l01_2a + 3 * that._l01_a * that._l12_a + that._l12_2a, n = 3 * that._l01_a * (that._l01_a + that._l12_a);\n x12 = (x12 * a2 - that._x0 * that._l12_2a + that._x2 * that._l01_2a) / n;\n y12 = (y12 * a2 - that._y0 * that._l12_2a + that._y2 * that._l01_2a) / n;\n }\n if (that._l23_a > epsilon7) {\n var b = 2 * that._l23_2a + 3 * that._l23_a * that._l12_a + that._l12_2a, m = 3 * that._l23_a * (that._l23_a + that._l12_a);\n x22 = (x22 * b + that._x1 * that._l23_2a - x3 * that._l12_2a) / m;\n y22 = (y22 * b + that._y1 * that._l23_2a - y3 * that._l12_2a) / m;\n }\n that._context.bezierCurveTo(x12, y12, x22, y22, that._x2, that._y2);\n}\nfunction CatmullRom(context, alpha) {\n this._context = context;\n this._alpha = alpha;\n}\nCatmullRom.prototype = {\n areaStart: function() {\n this._line = 0;\n },\n areaEnd: function() {\n this._line = NaN;\n },\n lineStart: function() {\n this._x0 = this._x1 = this._x2 = this._y0 = this._y1 = this._y2 = NaN;\n this._l01_a = this._l12_a = this._l23_a = this._l01_2a = this._l12_2a = this._l23_2a = this._point = 0;\n },\n lineEnd: function() {\n switch (this._point) {\n case 2:\n this._context.lineTo(this._x2, this._y2);\n break;\n case 3:\n this.point(this._x2, this._y2);\n break;\n }\n if (this._line || this._line !== 0 && this._point === 1) this._context.closePath();\n this._line = 1 - this._line;\n },\n point: function(x3, y3) {\n x3 = +x3, y3 = +y3;\n if (this._point) {\n var x23 = this._x2 - x3, y23 = this._y2 - y3;\n this._l23_a = Math.sqrt(this._l23_2a = Math.pow(x23 * x23 + y23 * y23, this._alpha));\n }\n switch (this._point) {\n case 0:\n this._point = 1;\n this._line ? this._context.lineTo(x3, y3) : this._context.moveTo(x3, y3);\n break;\n case 1:\n this._point = 2;\n break;\n case 2:\n this._point = 3;\n // falls through\n default:\n point4(this, x3, y3);\n break;\n }\n this._l01_a = this._l12_a, this._l12_a = this._l23_a;\n this._l01_2a = this._l12_2a, this._l12_2a = this._l23_2a;\n this._x0 = this._x1, this._x1 = this._x2, this._x2 = x3;\n this._y0 = this._y1, this._y1 = this._y2, this._y2 = y3;\n }\n};\nvar catmullRom_default = function custom5(alpha) {\n function catmullRom(context) {\n return alpha ? new CatmullRom(context, alpha) : new Cardinal(context, 0);\n }\n catmullRom.alpha = function(alpha2) {\n return custom5(+alpha2);\n };\n return catmullRom;\n}(0.5);\n\n// ../../node_modules/d3-shape/src/curve/catmullRomClosed.js\nfunction CatmullRomClosed(context, alpha) {\n this._context = context;\n this._alpha = alpha;\n}\nCatmullRomClosed.prototype = {\n areaStart: noop_default2,\n areaEnd: noop_default2,\n lineStart: function() {\n this._x0 = this._x1 = this._x2 = this._x3 = this._x4 = this._x5 = this._y0 = this._y1 = this._y2 = this._y3 = this._y4 = this._y5 = NaN;\n this._l01_a = this._l12_a = this._l23_a = this._l01_2a = this._l12_2a = this._l23_2a = this._point = 0;\n },\n lineEnd: function() {\n switch (this._point) {\n case 1: {\n this._context.moveTo(this._x3, this._y3);\n this._context.closePath();\n break;\n }\n case 2: {\n this._context.lineTo(this._x3, this._y3);\n this._context.closePath();\n break;\n }\n case 3: {\n this.point(this._x3, this._y3);\n this.point(this._x4, this._y4);\n this.point(this._x5, this._y5);\n break;\n }\n }\n },\n point: function(x3, y3) {\n x3 = +x3, y3 = +y3;\n if (this._point) {\n var x23 = this._x2 - x3, y23 = this._y2 - y3;\n this._l23_a = Math.sqrt(this._l23_2a = Math.pow(x23 * x23 + y23 * y23, this._alpha));\n }\n switch (this._point) {\n case 0:\n this._point = 1;\n this._x3 = x3, this._y3 = y3;\n break;\n case 1:\n this._point = 2;\n this._context.moveTo(this._x4 = x3, this._y4 = y3);\n break;\n case 2:\n this._point = 3;\n this._x5 = x3, this._y5 = y3;\n break;\n default:\n point4(this, x3, y3);\n break;\n }\n this._l01_a = this._l12_a, this._l12_a = this._l23_a;\n this._l01_2a = this._l12_2a, this._l12_2a = this._l23_2a;\n this._x0 = this._x1, this._x1 = this._x2, this._x2 = x3;\n this._y0 = this._y1, this._y1 = this._y2, this._y2 = y3;\n }\n};\nvar catmullRomClosed_default = function custom6(alpha) {\n function catmullRom(context) {\n return alpha ? new CatmullRomClosed(context, alpha) : new CardinalClosed(context, 0);\n }\n catmullRom.alpha = function(alpha2) {\n return custom6(+alpha2);\n };\n return catmullRom;\n}(0.5);\n\n// ../../node_modules/d3-shape/src/curve/catmullRomOpen.js\nfunction CatmullRomOpen(context, alpha) {\n this._context = context;\n this._alpha = alpha;\n}\nCatmullRomOpen.prototype = {\n areaStart: function() {\n this._line = 0;\n },\n areaEnd: function() {\n this._line = NaN;\n },\n lineStart: function() {\n this._x0 = this._x1 = this._x2 = this._y0 = this._y1 = this._y2 = NaN;\n this._l01_a = this._l12_a = this._l23_a = this._l01_2a = this._l12_2a = this._l23_2a = this._point = 0;\n },\n lineEnd: function() {\n if (this._line || this._line !== 0 && this._point === 3) this._context.closePath();\n this._line = 1 - this._line;\n },\n point: function(x3, y3) {\n x3 = +x3, y3 = +y3;\n if (this._point) {\n var x23 = this._x2 - x3, y23 = this._y2 - y3;\n this._l23_a = Math.sqrt(this._l23_2a = Math.pow(x23 * x23 + y23 * y23, this._alpha));\n }\n switch (this._point) {\n case 0:\n this._point = 1;\n break;\n case 1:\n this._point = 2;\n break;\n case 2:\n this._point = 3;\n this._line ? this._context.lineTo(this._x2, this._y2) : this._context.moveTo(this._x2, this._y2);\n break;\n case 3:\n this._point = 4;\n // falls through\n default:\n point4(this, x3, y3);\n break;\n }\n this._l01_a = this._l12_a, this._l12_a = this._l23_a;\n this._l01_2a = this._l12_2a, this._l12_2a = this._l23_2a;\n this._x0 = this._x1, this._x1 = this._x2, this._x2 = x3;\n this._y0 = this._y1, this._y1 = this._y2, this._y2 = y3;\n }\n};\nvar catmullRomOpen_default = function custom7(alpha) {\n function catmullRom(context) {\n return alpha ? new CatmullRomOpen(context, alpha) : new CardinalOpen(context, 0);\n }\n catmullRom.alpha = function(alpha2) {\n return custom7(+alpha2);\n };\n return catmullRom;\n}(0.5);\n\n// ../../node_modules/d3-shape/src/curve/linearClosed.js\nfunction LinearClosed(context) {\n this._context = context;\n}\nLinearClosed.prototype = {\n areaStart: noop_default2,\n areaEnd: noop_default2,\n lineStart: function() {\n this._point = 0;\n },\n lineEnd: function() {\n if (this._point) this._context.closePath();\n },\n point: function(x3, y3) {\n x3 = +x3, y3 = +y3;\n if (this._point) this._context.lineTo(x3, y3);\n else this._point = 1, this._context.moveTo(x3, y3);\n }\n};\nfunction linearClosed_default(context) {\n return new LinearClosed(context);\n}\n\n// ../../node_modules/d3-shape/src/curve/monotone.js\nfunction sign2(x3) {\n return x3 < 0 ? -1 : 1;\n}\nfunction slope3(that, x22, y22) {\n var h0 = that._x1 - that._x0, h1 = x22 - that._x1, s0 = (that._y1 - that._y0) / (h0 || h1 < 0 && -0), s1 = (y22 - that._y1) / (h1 || h0 < 0 && -0), p = (s0 * h1 + s1 * h0) / (h0 + h1);\n return (sign2(s0) + sign2(s1)) * Math.min(Math.abs(s0), Math.abs(s1), 0.5 * Math.abs(p)) || 0;\n}\nfunction slope2(that, t) {\n var h = that._x1 - that._x0;\n return h ? (3 * (that._y1 - that._y0) / h - t) / 2 : t;\n}\nfunction point5(that, t03, t13) {\n var x06 = that._x0, y06 = that._y0, x12 = that._x1, y12 = that._y1, dx = (x12 - x06) / 3;\n that._context.bezierCurveTo(x06 + dx, y06 + dx * t03, x12 - dx, y12 - dx * t13, x12, y12);\n}\nfunction MonotoneX(context) {\n this._context = context;\n}\nMonotoneX.prototype = {\n areaStart: function() {\n this._line = 0;\n },\n areaEnd: function() {\n this._line = NaN;\n },\n lineStart: function() {\n this._x0 = this._x1 = this._y0 = this._y1 = this._t0 = NaN;\n this._point = 0;\n },\n lineEnd: function() {\n switch (this._point) {\n case 2:\n this._context.lineTo(this._x1, this._y1);\n break;\n case 3:\n point5(this, this._t0, slope2(this, this._t0));\n break;\n }\n if (this._line || this._line !== 0 && this._point === 1) this._context.closePath();\n this._line = 1 - this._line;\n },\n point: function(x3, y3) {\n var t13 = NaN;\n x3 = +x3, y3 = +y3;\n if (x3 === this._x1 && y3 === this._y1) return;\n switch (this._point) {\n case 0:\n this._point = 1;\n this._line ? this._context.lineTo(x3, y3) : this._context.moveTo(x3, y3);\n break;\n case 1:\n this._point = 2;\n break;\n case 2:\n this._point = 3;\n point5(this, slope2(this, t13 = slope3(this, x3, y3)), t13);\n break;\n default:\n point5(this, this._t0, t13 = slope3(this, x3, y3));\n break;\n }\n this._x0 = this._x1, this._x1 = x3;\n this._y0 = this._y1, this._y1 = y3;\n this._t0 = t13;\n }\n};\nfunction MonotoneY(context) {\n this._context = new ReflectContext(context);\n}\n(MonotoneY.prototype = Object.create(MonotoneX.prototype)).point = function(x3, y3) {\n MonotoneX.prototype.point.call(this, y3, x3);\n};\nfunction ReflectContext(context) {\n this._context = context;\n}\nReflectContext.prototype = {\n moveTo: function(x3, y3) {\n this._context.moveTo(y3, x3);\n },\n closePath: function() {\n this._context.closePath();\n },\n lineTo: function(x3, y3) {\n this._context.lineTo(y3, x3);\n },\n bezierCurveTo: function(x12, y12, x22, y22, x3, y3) {\n this._context.bezierCurveTo(y12, x12, y22, x22, y3, x3);\n }\n};\nfunction monotoneX(context) {\n return new MonotoneX(context);\n}\nfunction monotoneY(context) {\n return new MonotoneY(context);\n}\n\n// ../../node_modules/d3-shape/src/curve/natural.js\nfunction Natural(context) {\n this._context = context;\n}\nNatural.prototype = {\n areaStart: function() {\n this._line = 0;\n },\n areaEnd: function() {\n this._line = NaN;\n },\n lineStart: function() {\n this._x = [];\n this._y = [];\n },\n lineEnd: function() {\n var x3 = this._x, y3 = this._y, n = x3.length;\n if (n) {\n this._line ? this._context.lineTo(x3[0], y3[0]) : this._context.moveTo(x3[0], y3[0]);\n if (n === 2) {\n this._context.lineTo(x3[1], y3[1]);\n } else {\n var px = controlPoints(x3), py = controlPoints(y3);\n for (var i0 = 0, i1 = 1; i1 < n; ++i0, ++i1) {\n this._context.bezierCurveTo(px[0][i0], py[0][i0], px[1][i0], py[1][i0], x3[i1], y3[i1]);\n }\n }\n }\n if (this._line || this._line !== 0 && n === 1) this._context.closePath();\n this._line = 1 - this._line;\n this._x = this._y = null;\n },\n point: function(x3, y3) {\n this._x.push(+x3);\n this._y.push(+y3);\n }\n};\nfunction controlPoints(x3) {\n var i, n = x3.length - 1, m, a2 = new Array(n), b = new Array(n), r = new Array(n);\n a2[0] = 0, b[0] = 2, r[0] = x3[0] + 2 * x3[1];\n for (i = 1; i < n - 1; ++i) a2[i] = 1, b[i] = 4, r[i] = 4 * x3[i] + 2 * x3[i + 1];\n a2[n - 1] = 2, b[n - 1] = 7, r[n - 1] = 8 * x3[n - 1] + x3[n];\n for (i = 1; i < n; ++i) m = a2[i] / b[i - 1], b[i] -= m, r[i] -= m * r[i - 1];\n a2[n - 1] = r[n - 1] / b[n - 1];\n for (i = n - 2; i >= 0; --i) a2[i] = (r[i] - a2[i + 1]) / b[i];\n b[n - 1] = (x3[n] + a2[n - 1]) / 2;\n for (i = 0; i < n - 1; ++i) b[i] = 2 * x3[i + 1] - a2[i + 1];\n return [a2, b];\n}\nfunction natural_default(context) {\n return new Natural(context);\n}\n\n// ../../node_modules/d3-shape/src/curve/step.js\nfunction Step(context, t) {\n this._context = context;\n this._t = t;\n}\nStep.prototype = {\n areaStart: function() {\n this._line = 0;\n },\n areaEnd: function() {\n this._line = NaN;\n },\n lineStart: function() {\n this._x = this._y = NaN;\n this._point = 0;\n },\n lineEnd: function() {\n if (0 < this._t && this._t < 1 && this._point === 2) this._context.lineTo(this._x, this._y);\n if (this._line || this._line !== 0 && this._point === 1) this._context.closePath();\n if (this._line >= 0) this._t = 1 - this._t, this._line = 1 - this._line;\n },\n point: function(x3, y3) {\n x3 = +x3, y3 = +y3;\n switch (this._point) {\n case 0:\n this._point = 1;\n this._line ? this._context.lineTo(x3, y3) : this._context.moveTo(x3, y3);\n break;\n case 1:\n this._point = 2;\n // falls through\n default: {\n if (this._t <= 0) {\n this._context.lineTo(this._x, y3);\n this._context.lineTo(x3, y3);\n } else {\n var x12 = this._x * (1 - this._t) + x3 * this._t;\n this._context.lineTo(x12, this._y);\n this._context.lineTo(x12, y3);\n }\n break;\n }\n }\n this._x = x3, this._y = y3;\n }\n};\nfunction step_default(context) {\n return new Step(context, 0.5);\n}\nfunction stepBefore(context) {\n return new Step(context, 0);\n}\nfunction stepAfter(context) {\n return new Step(context, 1);\n}\n\n// ../../node_modules/d3-zoom/src/constant.js\nvar constant_default6 = (x3) => () => x3;\n\n// ../../node_modules/d3-zoom/src/event.js\nfunction ZoomEvent(type2, {\n sourceEvent,\n target,\n transform: transform3,\n dispatch: dispatch2\n}) {\n Object.defineProperties(this, {\n type: { value: type2, enumerable: true, configurable: true },\n sourceEvent: { value: sourceEvent, enumerable: true, configurable: true },\n target: { value: target, enumerable: true, configurable: true },\n transform: { value: transform3, enumerable: true, configurable: true },\n _: { value: dispatch2 }\n });\n}\n\n// ../../node_modules/d3-zoom/src/transform.js\nfunction Transform2(k2, x3, y3) {\n this.k = k2;\n this.x = x3;\n this.y = y3;\n}\nTransform2.prototype = {\n constructor: Transform2,\n scale: function(k2) {\n return k2 === 1 ? this : new Transform2(this.k * k2, this.x, this.y);\n },\n translate: function(x3, y3) {\n return x3 === 0 & y3 === 0 ? this : new Transform2(this.k, this.x + this.k * x3, this.y + this.k * y3);\n },\n apply: function(point6) {\n return [point6[0] * this.k + this.x, point6[1] * this.k + this.y];\n },\n applyX: function(x3) {\n return x3 * this.k + this.x;\n },\n applyY: function(y3) {\n return y3 * this.k + this.y;\n },\n invert: function(location) {\n return [(location[0] - this.x) / this.k, (location[1] - this.y) / this.k];\n },\n invertX: function(x3) {\n return (x3 - this.x) / this.k;\n },\n invertY: function(y3) {\n return (y3 - this.y) / this.k;\n },\n rescaleX: function(x3) {\n return x3.copy().domain(x3.range().map(this.invertX, this).map(x3.invert, x3));\n },\n rescaleY: function(y3) {\n return y3.copy().domain(y3.range().map(this.invertY, this).map(y3.invert, y3));\n },\n toString: function() {\n return \"translate(\" + this.x + \",\" + this.y + \") scale(\" + this.k + \")\";\n }\n};\nvar identity6 = new Transform2(1, 0, 0);\ntransform.prototype = Transform2.prototype;\nfunction transform(node) {\n while (!node.__zoom) if (!(node = node.parentNode)) return identity6;\n return node.__zoom;\n}\n\n// ../../node_modules/d3-zoom/src/noevent.js\nfunction nopropagation2(event) {\n event.stopImmediatePropagation();\n}\nfunction noevent_default3(event) {\n event.preventDefault();\n event.stopImmediatePropagation();\n}\n\n// ../../node_modules/d3-zoom/src/zoom.js\nfunction defaultFilter2(event) {\n return (!event.ctrlKey || event.type === \"wheel\") && !event.button;\n}\nfunction defaultExtent2() {\n var e = this;\n if (e instanceof SVGElement) {\n e = e.ownerSVGElement || e;\n if (e.hasAttribute(\"viewBox\")) {\n e = e.viewBox.baseVal;\n return [[e.x, e.y], [e.x + e.width, e.y + e.height]];\n }\n return [[0, 0], [e.width.baseVal.value, e.height.baseVal.value]];\n }\n return [[0, 0], [e.clientWidth, e.clientHeight]];\n}\nfunction defaultTransform() {\n return this.__zoom || identity6;\n}\nfunction defaultWheelDelta(event) {\n return -event.deltaY * (event.deltaMode === 1 ? 0.05 : event.deltaMode ? 1 : 2e-3) * (event.ctrlKey ? 10 : 1);\n}\nfunction defaultTouchable2() {\n return navigator.maxTouchPoints || \"ontouchstart\" in this;\n}\nfunction defaultConstrain(transform3, extent4, translateExtent) {\n var dx0 = transform3.invertX(extent4[0][0]) - translateExtent[0][0], dx1 = transform3.invertX(extent4[1][0]) - translateExtent[1][0], dy0 = transform3.invertY(extent4[0][1]) - translateExtent[0][1], dy1 = transform3.invertY(extent4[1][1]) - translateExtent[1][1];\n return transform3.translate(\n dx1 > dx0 ? (dx0 + dx1) / 2 : Math.min(0, dx0) || Math.max(0, dx1),\n dy1 > dy0 ? (dy0 + dy1) / 2 : Math.min(0, dy0) || Math.max(0, dy1)\n );\n}\nfunction zoom_default2() {\n var filter3 = defaultFilter2, extent4 = defaultExtent2, constrain = defaultConstrain, wheelDelta = defaultWheelDelta, touchable = defaultTouchable2, scaleExtent = [0, Infinity], translateExtent = [[-Infinity, -Infinity], [Infinity, Infinity]], duration2 = 250, interpolate = zoom_default, listeners = dispatch_default(\"start\", \"zoom\", \"end\"), touchstarting, touchfirst, touchending, touchDelay = 500, wheelDelay = 150, clickDistance2 = 0, tapDistance = 10;\n function zoom2(selection2) {\n selection2.property(\"__zoom\", defaultTransform).on(\"wheel.zoom\", wheeled, { passive: false }).on(\"mousedown.zoom\", mousedowned).on(\"dblclick.zoom\", dblclicked).filter(touchable).on(\"touchstart.zoom\", touchstarted).on(\"touchmove.zoom\", touchmoved).on(\"touchend.zoom touchcancel.zoom\", touchended).style(\"-webkit-tap-highlight-color\", \"rgba(0,0,0,0)\");\n }\n zoom2.transform = function(collection, transform3, point6, event) {\n var selection2 = collection.selection ? collection.selection() : collection;\n selection2.property(\"__zoom\", defaultTransform);\n if (collection !== selection2) {\n schedule(collection, transform3, point6, event);\n } else {\n selection2.interrupt().each(function() {\n gesture(this, arguments).event(event).start().zoom(null, typeof transform3 === \"function\" ? transform3.apply(this, arguments) : transform3).end();\n });\n }\n };\n zoom2.scaleBy = function(selection2, k2, p, event) {\n zoom2.scaleTo(selection2, function() {\n var k0 = this.__zoom.k, k1 = typeof k2 === \"function\" ? k2.apply(this, arguments) : k2;\n return k0 * k1;\n }, p, event);\n };\n zoom2.scaleTo = function(selection2, k2, p, event) {\n zoom2.transform(selection2, function() {\n var e = extent4.apply(this, arguments), t03 = this.__zoom, p0 = p == null ? centroid3(e) : typeof p === \"function\" ? p.apply(this, arguments) : p, p1 = t03.invert(p0), k1 = typeof k2 === \"function\" ? k2.apply(this, arguments) : k2;\n return constrain(translate(scale3(t03, k1), p0, p1), e, translateExtent);\n }, p, event);\n };\n zoom2.translateBy = function(selection2, x3, y3, event) {\n zoom2.transform(selection2, function() {\n return constrain(this.__zoom.translate(\n typeof x3 === \"function\" ? x3.apply(this, arguments) : x3,\n typeof y3 === \"function\" ? y3.apply(this, arguments) : y3\n ), extent4.apply(this, arguments), translateExtent);\n }, null, event);\n };\n zoom2.translateTo = function(selection2, x3, y3, p, event) {\n zoom2.transform(selection2, function() {\n var e = extent4.apply(this, arguments), t = this.__zoom, p0 = p == null ? centroid3(e) : typeof p === \"function\" ? p.apply(this, arguments) : p;\n return constrain(identity6.translate(p0[0], p0[1]).scale(t.k).translate(\n typeof x3 === \"function\" ? -x3.apply(this, arguments) : -x3,\n typeof y3 === \"function\" ? -y3.apply(this, arguments) : -y3\n ), e, translateExtent);\n }, p, event);\n };\n function scale3(transform3, k2) {\n k2 = Math.max(scaleExtent[0], Math.min(scaleExtent[1], k2));\n return k2 === transform3.k ? transform3 : new Transform2(k2, transform3.x, transform3.y);\n }\n function translate(transform3, p0, p1) {\n var x3 = p0[0] - p1[0] * transform3.k, y3 = p0[1] - p1[1] * transform3.k;\n return x3 === transform3.x && y3 === transform3.y ? transform3 : new Transform2(transform3.k, x3, y3);\n }\n function centroid3(extent5) {\n return [(+extent5[0][0] + +extent5[1][0]) / 2, (+extent5[0][1] + +extent5[1][1]) / 2];\n }\n function schedule(transition2, transform3, point6, event) {\n transition2.on(\"start.zoom\", function() {\n gesture(this, arguments).event(event).start();\n }).on(\"interrupt.zoom end.zoom\", function() {\n gesture(this, arguments).event(event).end();\n }).tween(\"zoom\", function() {\n var that = this, args = arguments, g = gesture(that, args).event(event), e = extent4.apply(that, args), p = point6 == null ? centroid3(e) : typeof point6 === \"function\" ? point6.apply(that, args) : point6, w = Math.max(e[1][0] - e[0][0], e[1][1] - e[0][1]), a2 = that.__zoom, b = typeof transform3 === \"function\" ? transform3.apply(that, args) : transform3, i = interpolate(a2.invert(p).concat(w / a2.k), b.invert(p).concat(w / b.k));\n return function(t) {\n if (t === 1) t = b;\n else {\n var l = i(t), k2 = w / l[2];\n t = new Transform2(k2, p[0] - l[0] * k2, p[1] - l[1] * k2);\n }\n g.zoom(null, t);\n };\n });\n }\n function gesture(that, args, clean) {\n return !clean && that.__zooming || new Gesture(that, args);\n }\n function Gesture(that, args) {\n this.that = that;\n this.args = args;\n this.active = 0;\n this.sourceEvent = null;\n this.extent = extent4.apply(that, args);\n this.taps = 0;\n }\n Gesture.prototype = {\n event: function(event) {\n if (event) this.sourceEvent = event;\n return this;\n },\n start: function() {\n if (++this.active === 1) {\n this.that.__zooming = this;\n this.emit(\"start\");\n }\n return this;\n },\n zoom: function(key, transform3) {\n if (this.mouse && key !== \"mouse\") this.mouse[1] = transform3.invert(this.mouse[0]);\n if (this.touch0 && key !== \"touch\") this.touch0[1] = transform3.invert(this.touch0[0]);\n if (this.touch1 && key !== \"touch\") this.touch1[1] = transform3.invert(this.touch1[0]);\n this.that.__zoom = transform3;\n this.emit(\"zoom\");\n return this;\n },\n end: function() {\n if (--this.active === 0) {\n delete this.that.__zooming;\n this.emit(\"end\");\n }\n return this;\n },\n emit: function(type2) {\n var d = select_default2(this.that).datum();\n listeners.call(\n type2,\n this.that,\n new ZoomEvent(type2, {\n sourceEvent: this.sourceEvent,\n target: zoom2,\n type: type2,\n transform: this.that.__zoom,\n dispatch: listeners\n }),\n d\n );\n }\n };\n function wheeled(event, ...args) {\n if (!filter3.apply(this, arguments)) return;\n var g = gesture(this, args).event(event), t = this.__zoom, k2 = Math.max(scaleExtent[0], Math.min(scaleExtent[1], t.k * Math.pow(2, wheelDelta.apply(this, arguments)))), p = pointer_default(event);\n if (g.wheel) {\n if (g.mouse[0][0] !== p[0] || g.mouse[0][1] !== p[1]) {\n g.mouse[1] = t.invert(g.mouse[0] = p);\n }\n clearTimeout(g.wheel);\n } else if (t.k === k2) return;\n else {\n g.mouse = [p, t.invert(p)];\n interrupt_default(this);\n g.start();\n }\n noevent_default3(event);\n g.wheel = setTimeout(wheelidled, wheelDelay);\n g.zoom(\"mouse\", constrain(translate(scale3(t, k2), g.mouse[0], g.mouse[1]), g.extent, translateExtent));\n function wheelidled() {\n g.wheel = null;\n g.end();\n }\n }\n function mousedowned(event, ...args) {\n if (touchending || !filter3.apply(this, arguments)) return;\n var currentTarget = event.currentTarget, g = gesture(this, args, true).event(event), v2 = select_default2(event.view).on(\"mousemove.zoom\", mousemoved, true).on(\"mouseup.zoom\", mouseupped, true), p = pointer_default(event, currentTarget), x06 = event.clientX, y06 = event.clientY;\n nodrag_default(event.view);\n nopropagation2(event);\n g.mouse = [p, this.__zoom.invert(p)];\n interrupt_default(this);\n g.start();\n function mousemoved(event2) {\n noevent_default3(event2);\n if (!g.moved) {\n var dx = event2.clientX - x06, dy = event2.clientY - y06;\n g.moved = dx * dx + dy * dy > clickDistance2;\n }\n g.event(event2).zoom(\"mouse\", constrain(translate(g.that.__zoom, g.mouse[0] = pointer_default(event2, currentTarget), g.mouse[1]), g.extent, translateExtent));\n }\n function mouseupped(event2) {\n v2.on(\"mousemove.zoom mouseup.zoom\", null);\n yesdrag(event2.view, g.moved);\n noevent_default3(event2);\n g.event(event2).end();\n }\n }\n function dblclicked(event, ...args) {\n if (!filter3.apply(this, arguments)) return;\n var t03 = this.__zoom, p0 = pointer_default(event.changedTouches ? event.changedTouches[0] : event, this), p1 = t03.invert(p0), k1 = t03.k * (event.shiftKey ? 0.5 : 2), t13 = constrain(translate(scale3(t03, k1), p0, p1), extent4.apply(this, args), translateExtent);\n noevent_default3(event);\n if (duration2 > 0) select_default2(this).transition().duration(duration2).call(schedule, t13, p0, event);\n else select_default2(this).call(zoom2.transform, t13, p0, event);\n }\n function touchstarted(event, ...args) {\n if (!filter3.apply(this, arguments)) return;\n var touches = event.touches, n = touches.length, g = gesture(this, args, event.changedTouches.length === n).event(event), started, i, t, p;\n nopropagation2(event);\n for (i = 0; i < n; ++i) {\n t = touches[i], p = pointer_default(t, this);\n p = [p, this.__zoom.invert(p), t.identifier];\n if (!g.touch0) g.touch0 = p, started = true, g.taps = 1 + !!touchstarting;\n else if (!g.touch1 && g.touch0[2] !== p[2]) g.touch1 = p, g.taps = 0;\n }\n if (touchstarting) touchstarting = clearTimeout(touchstarting);\n if (started) {\n if (g.taps < 2) touchfirst = p[0], touchstarting = setTimeout(function() {\n touchstarting = null;\n }, touchDelay);\n interrupt_default(this);\n g.start();\n }\n }\n function touchmoved(event, ...args) {\n if (!this.__zooming) return;\n var g = gesture(this, args).event(event), touches = event.changedTouches, n = touches.length, i, t, p, l;\n noevent_default3(event);\n for (i = 0; i < n; ++i) {\n t = touches[i], p = pointer_default(t, this);\n if (g.touch0 && g.touch0[2] === t.identifier) g.touch0[0] = p;\n else if (g.touch1 && g.touch1[2] === t.identifier) g.touch1[0] = p;\n }\n t = g.that.__zoom;\n if (g.touch1) {\n var p0 = g.touch0[0], l0 = g.touch0[1], p1 = g.touch1[0], l1 = g.touch1[1], dp = (dp = p1[0] - p0[0]) * dp + (dp = p1[1] - p0[1]) * dp, dl = (dl = l1[0] - l0[0]) * dl + (dl = l1[1] - l0[1]) * dl;\n t = scale3(t, Math.sqrt(dp / dl));\n p = [(p0[0] + p1[0]) / 2, (p0[1] + p1[1]) / 2];\n l = [(l0[0] + l1[0]) / 2, (l0[1] + l1[1]) / 2];\n } else if (g.touch0) p = g.touch0[0], l = g.touch0[1];\n else return;\n g.zoom(\"touch\", constrain(translate(t, p, l), g.extent, translateExtent));\n }\n function touchended(event, ...args) {\n if (!this.__zooming) return;\n var g = gesture(this, args).event(event), touches = event.changedTouches, n = touches.length, i, t;\n nopropagation2(event);\n if (touchending) clearTimeout(touchending);\n touchending = setTimeout(function() {\n touchending = null;\n }, touchDelay);\n for (i = 0; i < n; ++i) {\n t = touches[i];\n if (g.touch0 && g.touch0[2] === t.identifier) delete g.touch0;\n else if (g.touch1 && g.touch1[2] === t.identifier) delete g.touch1;\n }\n if (g.touch1 && !g.touch0) g.touch0 = g.touch1, delete g.touch1;\n if (g.touch0) g.touch0[1] = this.__zoom.invert(g.touch0[0]);\n else {\n g.end();\n if (g.taps === 2) {\n t = pointer_default(t, this);\n if (Math.hypot(touchfirst[0] - t[0], touchfirst[1] - t[1]) < tapDistance) {\n var p = select_default2(this).on(\"dblclick.zoom\");\n if (p) p.apply(this, arguments);\n }\n }\n }\n }\n zoom2.wheelDelta = function(_) {\n return arguments.length ? (wheelDelta = typeof _ === \"function\" ? _ : constant_default6(+_), zoom2) : wheelDelta;\n };\n zoom2.filter = function(_) {\n return arguments.length ? (filter3 = typeof _ === \"function\" ? _ : constant_default6(!!_), zoom2) : filter3;\n };\n zoom2.touchable = function(_) {\n return arguments.length ? (touchable = typeof _ === \"function\" ? _ : constant_default6(!!_), zoom2) : touchable;\n };\n zoom2.extent = function(_) {\n return arguments.length ? (extent4 = typeof _ === \"function\" ? _ : constant_default6([[+_[0][0], +_[0][1]], [+_[1][0], +_[1][1]]]), zoom2) : extent4;\n };\n zoom2.scaleExtent = function(_) {\n return arguments.length ? (scaleExtent[0] = +_[0], scaleExtent[1] = +_[1], zoom2) : [scaleExtent[0], scaleExtent[1]];\n };\n zoom2.translateExtent = function(_) {\n return arguments.length ? (translateExtent[0][0] = +_[0][0], translateExtent[1][0] = +_[1][0], translateExtent[0][1] = +_[0][1], translateExtent[1][1] = +_[1][1], zoom2) : [[translateExtent[0][0], translateExtent[0][1]], [translateExtent[1][0], translateExtent[1][1]]];\n };\n zoom2.constrain = function(_) {\n return arguments.length ? (constrain = _, zoom2) : constrain;\n };\n zoom2.duration = function(_) {\n return arguments.length ? (duration2 = +_, zoom2) : duration2;\n };\n zoom2.interpolate = function(_) {\n return arguments.length ? (interpolate = _, zoom2) : interpolate;\n };\n zoom2.on = function() {\n var value = listeners.on.apply(listeners, arguments);\n return value === listeners ? zoom2 : value;\n };\n zoom2.clickDistance = function(_) {\n return arguments.length ? (clickDistance2 = (_ = +_) * _, zoom2) : Math.sqrt(clickDistance2);\n };\n zoom2.tapDistance = function(_) {\n return arguments.length ? (tapDistance = +_, zoom2) : tapDistance;\n };\n return zoom2;\n}\n\n// ../../node_modules/@observablehq/plot/src/defined.js\nfunction defined(x3) {\n return x3 != null && !Number.isNaN(x3);\n}\nfunction ascendingDefined2(a2, b) {\n return +defined(b) - +defined(a2) || ascending(a2, b);\n}\nfunction descendingDefined(a2, b) {\n return +defined(b) - +defined(a2) || descending(a2, b);\n}\nfunction nonempty(x3) {\n return x3 != null && `${x3}` !== \"\";\n}\nfunction finite2(x3) {\n return isFinite(x3) ? x3 : NaN;\n}\nfunction positive(x3) {\n return x3 > 0 && isFinite(x3) ? x3 : NaN;\n}\nfunction negative(x3) {\n return x3 < 0 && isFinite(x3) ? x3 : NaN;\n}\n\n// ../../node_modules/isoformat/src/format.js\nfunction format2(date3, fallback) {\n if (!(date3 instanceof Date)) date3 = /* @__PURE__ */ new Date(+date3);\n if (isNaN(date3)) return typeof fallback === \"function\" ? fallback(date3) : fallback;\n const hours = date3.getUTCHours();\n const minutes = date3.getUTCMinutes();\n const seconds2 = date3.getUTCSeconds();\n const milliseconds2 = date3.getUTCMilliseconds();\n return `${formatYear2(date3.getUTCFullYear(), 4)}-${pad2(date3.getUTCMonth() + 1, 2)}-${pad2(date3.getUTCDate(), 2)}${hours || minutes || seconds2 || milliseconds2 ? `T${pad2(hours, 2)}:${pad2(minutes, 2)}${seconds2 || milliseconds2 ? `:${pad2(seconds2, 2)}${milliseconds2 ? `.${pad2(milliseconds2, 3)}` : ``}` : ``}Z` : ``}`;\n}\nfunction formatYear2(year) {\n return year < 0 ? `-${pad2(-year, 6)}` : year > 9999 ? `+${pad2(year, 6)}` : pad2(year, 4);\n}\nfunction pad2(value, width2) {\n return `${value}`.padStart(width2, \"0\");\n}\n\n// ../../node_modules/isoformat/src/parse.js\nvar re2 = /^(?:[-+]\\d{2})?\\d{4}(?:-\\d{2}(?:-\\d{2})?)?(?:T\\d{2}:\\d{2}(?::\\d{2}(?:\\.\\d{3})?)?(?:Z|[-+]\\d{2}:?\\d{2})?)?$/;\nfunction parse(string2, fallback) {\n if (!re2.test(string2 += \"\")) return typeof fallback === \"function\" ? fallback(string2) : fallback;\n return new Date(string2);\n}\n\n// ../../node_modules/@observablehq/plot/src/order.js\nfunction orderof(values2) {\n if (values2 == null) return;\n const first3 = values2[0];\n const last2 = values2[values2.length - 1];\n return descending(first3, last2);\n}\n\n// ../../node_modules/@observablehq/plot/src/time.js\nvar durationSecond2 = 1e3;\nvar durationMinute2 = durationSecond2 * 60;\nvar durationHour2 = durationMinute2 * 60;\nvar durationDay2 = durationHour2 * 24;\nvar durationWeek2 = durationDay2 * 7;\nvar durationMonth2 = durationDay2 * 30;\nvar durationYear2 = durationDay2 * 365;\nvar tickIntervals = [\n [\"millisecond\", 1],\n [\"2 milliseconds\", 2],\n [\"5 milliseconds\", 5],\n [\"10 milliseconds\", 10],\n [\"20 milliseconds\", 20],\n [\"50 milliseconds\", 50],\n [\"100 milliseconds\", 100],\n [\"200 milliseconds\", 200],\n [\"500 milliseconds\", 500],\n [\"second\", durationSecond2],\n [\"5 seconds\", 5 * durationSecond2],\n [\"15 seconds\", 15 * durationSecond2],\n [\"30 seconds\", 30 * durationSecond2],\n [\"minute\", durationMinute2],\n [\"5 minutes\", 5 * durationMinute2],\n [\"15 minutes\", 15 * durationMinute2],\n [\"30 minutes\", 30 * durationMinute2],\n [\"hour\", durationHour2],\n [\"3 hours\", 3 * durationHour2],\n [\"6 hours\", 6 * durationHour2],\n [\"12 hours\", 12 * durationHour2],\n [\"day\", durationDay2],\n [\"2 days\", 2 * durationDay2],\n [\"week\", durationWeek2],\n [\"2 weeks\", 2 * durationWeek2],\n // https://github.com/d3/d3-time/issues/46\n [\"month\", durationMonth2],\n [\"3 months\", 3 * durationMonth2],\n [\"6 months\", 6 * durationMonth2],\n // https://github.com/d3/d3-time/issues/46\n [\"year\", durationYear2],\n [\"2 years\", 2 * durationYear2],\n [\"5 years\", 5 * durationYear2],\n [\"10 years\", 10 * durationYear2],\n [\"20 years\", 20 * durationYear2],\n [\"50 years\", 50 * durationYear2],\n [\"100 years\", 100 * durationYear2]\n // TODO generalize to longer time scales\n];\nvar durations = /* @__PURE__ */ new Map([\n [\"second\", durationSecond2],\n [\"minute\", durationMinute2],\n [\"hour\", durationHour2],\n [\"day\", durationDay2],\n [\"monday\", durationWeek2],\n [\"tuesday\", durationWeek2],\n [\"wednesday\", durationWeek2],\n [\"thursday\", durationWeek2],\n [\"friday\", durationWeek2],\n [\"saturday\", durationWeek2],\n [\"sunday\", durationWeek2],\n [\"week\", durationWeek2],\n [\"month\", durationMonth2],\n [\"year\", durationYear2]\n]);\nvar timeIntervals = /* @__PURE__ */ new Map([\n [\"second\", second],\n [\"minute\", timeMinute],\n [\"hour\", timeHour],\n [\"day\", timeDay],\n // https://github.com/d3/d3-time/issues/62\n [\"monday\", timeMonday],\n [\"tuesday\", timeTuesday],\n [\"wednesday\", timeWednesday],\n [\"thursday\", timeThursday],\n [\"friday\", timeFriday],\n [\"saturday\", timeSaturday],\n [\"sunday\", timeSunday],\n [\"week\", timeSunday],\n [\"month\", timeMonth],\n [\"year\", timeYear]\n]);\nvar utcIntervals = /* @__PURE__ */ new Map([\n [\"second\", second],\n [\"minute\", utcMinute],\n [\"hour\", utcHour],\n [\"day\", unixDay],\n [\"monday\", utcMonday],\n [\"tuesday\", utcTuesday],\n [\"wednesday\", utcWednesday],\n [\"thursday\", utcThursday],\n [\"friday\", utcFriday],\n [\"saturday\", utcSaturday],\n [\"sunday\", utcSunday],\n [\"week\", utcSunday],\n [\"month\", utcMonth],\n [\"year\", utcYear]\n]);\nvar intervalDuration = Symbol(\"intervalDuration\");\nvar intervalType = Symbol(\"intervalType\");\nfor (const [name2, interval3] of timeIntervals) {\n interval3[intervalDuration] = durations.get(name2);\n interval3[intervalType] = \"time\";\n}\nfor (const [name2, interval3] of utcIntervals) {\n interval3[intervalDuration] = durations.get(name2);\n interval3[intervalType] = \"utc\";\n}\nvar utcFormatIntervals = [\n [\"year\", utcYear, \"utc\"],\n [\"month\", utcMonth, \"utc\"],\n [\"day\", unixDay, \"utc\", 6 * durationMonth2],\n [\"hour\", utcHour, \"utc\", 3 * durationDay2],\n [\"minute\", utcMinute, \"utc\", 6 * durationHour2],\n [\"second\", second, \"utc\", 30 * durationMinute2]\n];\nvar timeFormatIntervals = [\n [\"year\", timeYear, \"time\"],\n [\"month\", timeMonth, \"time\"],\n [\"day\", timeDay, \"time\", 6 * durationMonth2],\n [\"hour\", timeHour, \"time\", 3 * durationDay2],\n [\"minute\", timeMinute, \"time\", 6 * durationHour2],\n [\"second\", second, \"time\", 30 * durationMinute2]\n];\nvar formatIntervals = [\n utcFormatIntervals[0],\n timeFormatIntervals[0],\n utcFormatIntervals[1],\n timeFormatIntervals[1],\n utcFormatIntervals[2],\n timeFormatIntervals[2],\n // Below day, local time typically has an hourly offset from UTC and hence the\n // two are aligned and indistinguishable; therefore, we only consider UTC, and\n // we don’t consider these if the domain only has a single value.\n ...utcFormatIntervals.slice(3)\n];\nfunction parseTimeInterval(input3) {\n let name2 = `${input3}`.toLowerCase();\n if (name2.endsWith(\"s\")) name2 = name2.slice(0, -1);\n let period = 1;\n const match = /^(?:(\\d+)\\s+)/.exec(name2);\n if (match) {\n name2 = name2.slice(match[0].length);\n period = +match[1];\n }\n switch (name2) {\n case \"quarter\":\n name2 = \"month\";\n period *= 3;\n break;\n case \"half\":\n name2 = \"month\";\n period *= 6;\n break;\n }\n let interval3 = utcIntervals.get(name2);\n if (!interval3) throw new Error(`unknown interval: ${input3}`);\n if (period > 1 && !interval3.every) throw new Error(`non-periodic interval: ${name2}`);\n return [name2, period];\n}\nfunction timeInterval2(input3) {\n return asInterval(parseTimeInterval(input3), \"time\");\n}\nfunction utcInterval(input3) {\n return asInterval(parseTimeInterval(input3), \"utc\");\n}\nfunction asInterval([name2, period], type2) {\n let interval3 = (type2 === \"time\" ? timeIntervals : utcIntervals).get(name2);\n if (period > 1) {\n interval3 = interval3.every(period);\n interval3[intervalDuration] = durations.get(name2) * period;\n interval3[intervalType] = type2;\n }\n return interval3;\n}\nfunction generalizeTimeInterval(interval3, n) {\n if (!(n > 1)) return;\n const duration2 = interval3[intervalDuration];\n if (!tickIntervals.some(([, d]) => d === duration2)) return;\n if (duration2 % durationDay2 === 0 && durationDay2 < duration2 && duration2 < durationMonth2) return;\n const [i] = tickIntervals[bisector(([, step]) => Math.log(step)).center(tickIntervals, Math.log(duration2 * n))];\n return (interval3[intervalType] === \"time\" ? timeInterval2 : utcInterval)(i);\n}\nfunction formatTimeInterval(name2, type2, anchor) {\n const format3 = type2 === \"time\" ? timeFormat : utcFormat;\n if (anchor == null) {\n return format3(\n name2 === \"year\" ? \"%Y\" : name2 === \"month\" ? \"%Y-%m\" : name2 === \"day\" ? \"%Y-%m-%d\" : name2 === \"hour\" || name2 === \"minute\" ? \"%Y-%m-%dT%H:%M\" : name2 === \"second\" ? \"%Y-%m-%dT%H:%M:%S\" : \"%Y-%m-%dT%H:%M:%S.%L\"\n );\n }\n const template2 = getTimeTemplate(anchor);\n switch (name2) {\n case \"millisecond\":\n return formatConditional(format3(\".%L\"), format3(\":%M:%S\"), template2);\n case \"second\":\n return formatConditional(format3(\":%S\"), format3(\"%-I:%M\"), template2);\n case \"minute\":\n return formatConditional(format3(\"%-I:%M\"), format3(\"%p\"), template2);\n case \"hour\":\n return formatConditional(format3(\"%-I %p\"), format3(\"%b %-d\"), template2);\n case \"day\":\n return formatConditional(format3(\"%-d\"), format3(\"%b\"), template2);\n case \"month\":\n return formatConditional(format3(\"%b\"), format3(\"%Y\"), template2);\n case \"year\":\n return format3(\"%Y\");\n }\n throw new Error(\"unable to format time ticks\");\n}\nfunction getTimeTemplate(anchor) {\n return anchor === \"left\" || anchor === \"right\" ? (f1, f2) => `\n${f1}\n${f2}` : anchor === \"top\" ? (f1, f2) => `${f2}\n${f1}` : (f1, f2) => `${f1}\n${f2}`;\n}\nfunction getFormatIntervals(type2) {\n return type2 === \"time\" ? timeFormatIntervals : type2 === \"utc\" ? utcFormatIntervals : formatIntervals;\n}\nfunction inferTimeFormat(type2, dates, anchor) {\n const step = max2(pairs2(dates, (a2, b) => Math.abs(b - a2)));\n if (step < 1e3) return formatTimeInterval(\"millisecond\", \"utc\", anchor);\n for (const [name2, interval3, intervalType2, maxStep] of getFormatIntervals(type2)) {\n if (step > maxStep) break;\n if (name2 === \"hour\" && !step) break;\n if (dates.every((d) => interval3.floor(d) >= d)) return formatTimeInterval(name2, intervalType2, anchor);\n }\n}\nfunction formatConditional(format1, format22, template2) {\n return (x3, i, X3) => {\n const f1 = format1(x3, i);\n const f2 = format22(x3, i);\n const j = i - orderof(X3);\n return i !== j && X3[j] !== void 0 && f2 === format22(X3[j], j) ? f1 : template2(f1, f2);\n };\n}\n\n// ../../node_modules/@observablehq/plot/src/options.js\nvar TypedArray2 = Object.getPrototypeOf(Uint8Array);\nvar objectToString = Object.prototype.toString;\nfunction isArray2(value) {\n return value instanceof Array || value instanceof TypedArray2;\n}\nfunction isNumberArray2(value) {\n return value instanceof TypedArray2 && !isBigIntArray(value);\n}\nfunction isNumberType(type2) {\n return type2?.prototype instanceof TypedArray2 && !isBigIntType(type2);\n}\nfunction isBigIntArray(value) {\n return value instanceof BigInt64Array || value instanceof BigUint64Array;\n}\nfunction isBigIntType(type2) {\n return type2 === BigInt64Array || type2 === BigUint64Array;\n}\nvar reindex = Symbol(\"reindex\");\nfunction valueof(data, value, type2) {\n const valueType = typeof value;\n return valueType === \"string\" ? isArrowTable2(data) ? maybeTypedArrowify(data.getChild(value), type2) : maybeTypedMap(data, field2(value), type2) : valueType === \"function\" ? maybeTypedMap(data, value, type2) : valueType === \"number\" || value instanceof Date || valueType === \"boolean\" ? map3(data, constant(value), type2) : typeof value?.transform === \"function\" ? maybeTypedArrayify(value.transform(data), type2) : maybeTake(maybeTypedArrayify(value, type2), data?.[reindex]);\n}\nfunction maybeTake(values2, index2) {\n return values2 != null && index2 ? take(values2, index2) : values2;\n}\nfunction maybeTypedMap(data, f, type2) {\n return map3(data, isNumberType(type2) ? (d, i) => coerceNumber(f(d, i)) : f, type2);\n}\nfunction maybeTypedArrayify(data, type2) {\n return type2 === void 0 ? arrayify2(data) : isArrowVector(data) ? maybeTypedArrowify(data, type2) : data instanceof type2 ? data : type2.from(data, isNumberType(type2) && !isNumberArray2(data) ? coerceNumber : void 0);\n}\nfunction maybeTypedArrowify(vector3, type2) {\n return vector3 == null ? vector3 : (type2 === void 0 || type2 === Array) && isArrowDateType(vector3.type) ? coerceDates(vector3.toArray()) : maybeTypedArrayify(vector3.toArray(), type2);\n}\nvar singleton = [null];\nvar field2 = (name2) => (d) => {\n const v2 = d[name2];\n return v2 === void 0 && d.type === \"Feature\" ? d.properties?.[name2] : v2;\n};\nvar indexOf = { transform: range2 };\nvar identity7 = { transform: (d) => d };\nvar one2 = () => 1;\nvar yes = () => true;\nvar string = (x3) => x3 == null ? x3 : `${x3}`;\nvar number5 = (x3) => x3 == null ? x3 : +x3;\nvar first2 = (x3) => x3 ? x3[0] : void 0;\nvar second2 = (x3) => x3 ? x3[1] : void 0;\nvar third = (x3) => x3 ? x3[2] : void 0;\nvar constant = (x3) => () => x3;\nfunction percentile(reduce) {\n const p = +`${reduce}`.slice(1) / 100;\n return (I, f) => quantile2(I, p, f);\n}\nfunction coerceNumbers(values2) {\n return isNumberArray2(values2) ? values2 : map3(values2, coerceNumber, Float64Array);\n}\nfunction coerceNumber(x3) {\n return x3 == null ? NaN : Number(x3);\n}\nfunction coerceDates(values2) {\n return map3(values2, coerceDate);\n}\nfunction coerceDate(x3) {\n return x3 instanceof Date && !isNaN(x3) ? x3 : typeof x3 === \"string\" ? parse(x3) : x3 == null || isNaN(x3 = Number(x3)) ? void 0 : new Date(x3);\n}\nfunction maybeColorChannel(value, defaultValue) {\n if (value === void 0) value = defaultValue;\n return value === null ? [void 0, \"none\"] : isColor(value) ? [void 0, value] : [value, void 0];\n}\nfunction maybeNumberChannel(value, defaultValue) {\n if (value === void 0) value = defaultValue;\n return value === null || typeof value === \"number\" ? [void 0, value] : [value, void 0];\n}\nfunction maybeKeyword(input3, name2, allowed) {\n if (input3 != null) return keyword(input3, name2, allowed);\n}\nfunction keyword(input3, name2, allowed) {\n const i = `${input3}`.toLowerCase();\n if (!allowed.includes(i)) throw new Error(`invalid ${name2}: ${input3}`);\n return i;\n}\nfunction dataify(data) {\n return isArrowTable2(data) ? data : arrayify2(data);\n}\nfunction arrayify2(values2) {\n if (values2 == null || isArray2(values2)) return values2;\n if (isArrowVector(values2)) return maybeTypedArrowify(values2);\n switch (values2.type) {\n case \"FeatureCollection\":\n return values2.features;\n case \"GeometryCollection\":\n return values2.geometries;\n case \"Feature\":\n case \"LineString\":\n case \"MultiLineString\":\n case \"MultiPoint\":\n case \"MultiPolygon\":\n case \"Point\":\n case \"Polygon\":\n case \"Sphere\":\n return [values2];\n }\n return Array.from(values2);\n}\nfunction map3(values2, f, type2 = Array) {\n return values2 == null ? values2 : values2 instanceof type2 ? values2.map(f) : type2.from(values2, f);\n}\nfunction slice3(values2, type2 = Array) {\n return values2 instanceof type2 ? values2.slice() : type2.from(values2);\n}\nfunction hasX({ x: x3, x1: x12, x2: x22 }) {\n return x3 !== void 0 || x12 !== void 0 || x22 !== void 0;\n}\nfunction hasY({ y: y3, y1: y12, y2: y22 }) {\n return y3 !== void 0 || y12 !== void 0 || y22 !== void 0;\n}\nfunction hasXY(options) {\n return hasX(options) || hasY(options) || options.interval !== void 0;\n}\nfunction isObject(option) {\n return option?.toString === objectToString;\n}\nfunction isScaleOptions(option) {\n return isObject(option) && (option.type !== void 0 || option.domain !== void 0);\n}\nfunction isOptions(option) {\n return isObject(option) && typeof option.transform !== \"function\";\n}\nfunction isDomainSort(sort3) {\n return isOptions(sort3) && sort3.value === void 0 && sort3.channel === void 0;\n}\nfunction maybeZero(x3, x12, x22, x32 = identity7) {\n if (x12 === void 0 && x22 === void 0) {\n x12 = 0, x22 = x3 === void 0 ? x32 : x3;\n } else if (x12 === void 0) {\n x12 = x3 === void 0 ? 0 : x3;\n } else if (x22 === void 0) {\n x22 = x3 === void 0 ? 0 : x3;\n }\n return [x12, x22];\n}\nfunction maybeTuple(x3, y3) {\n return x3 === void 0 && y3 === void 0 ? [first2, second2] : [x3, y3];\n}\nfunction maybeZ({ z, fill, stroke } = {}) {\n if (z === void 0) [z] = maybeColorChannel(fill);\n if (z === void 0) [z] = maybeColorChannel(stroke);\n return z;\n}\nfunction lengthof(data) {\n return isArray2(data) ? data.length : data?.numRows;\n}\nfunction range2(data) {\n const n = lengthof(data);\n const r = new Uint32Array(n);\n for (let i = 0; i < n; ++i) r[i] = i;\n return r;\n}\nfunction take(values2, index2) {\n return isArray2(values2) ? map3(index2, (i) => values2[i], values2.constructor) : map3(index2, (i) => values2.at(i));\n}\nfunction taker(f) {\n return f.length === 1 ? (index2, values2) => f(take(values2, index2)) : f;\n}\nfunction subarray(I, i, j) {\n return I.subarray ? I.subarray(i, j) : I.slice(i, j);\n}\nfunction keyof2(value) {\n return value !== null && typeof value === \"object\" ? value.valueOf() : value;\n}\nfunction maybeInput(key, options) {\n if (options[key] !== void 0) return options[key];\n switch (key) {\n case \"x1\":\n case \"x2\":\n key = \"x\";\n break;\n case \"y1\":\n case \"y2\":\n key = \"y\";\n break;\n }\n return options[key];\n}\nfunction column2(source) {\n let value;\n return [\n {\n transform: () => value,\n label: labelof(source)\n },\n (v2) => value = v2\n ];\n}\nfunction maybeColumn(source) {\n return source == null ? [source] : column2(source);\n}\nfunction labelof(value, defaultValue) {\n return typeof value === \"string\" ? value : value && value.label !== void 0 ? value.label : defaultValue;\n}\nfunction mid(x12, x22) {\n return {\n transform(data) {\n const X13 = x12.transform(data);\n const X23 = x22.transform(data);\n return isTemporal(X13) || isTemporal(X23) ? map3(X13, (_, i) => new Date((+X13[i] + +X23[i]) / 2)) : map3(X13, (_, i) => (+X13[i] + +X23[i]) / 2, Float64Array);\n },\n label: x12.label\n };\n}\nfunction maybeApplyInterval(V, scale3) {\n const t = maybeIntervalTransform(scale3?.interval, scale3?.type);\n return t ? map3(V, t) : V;\n}\nfunction maybeIntervalTransform(interval3, type2) {\n const i = maybeInterval(interval3, type2);\n return i && ((v2) => defined(v2) ? i.floor(v2) : v2);\n}\nfunction maybeInterval(interval3, type2) {\n if (interval3 == null) return;\n if (typeof interval3 === \"number\") return numberInterval(interval3);\n if (typeof interval3 === \"string\") return (type2 === \"time\" ? timeInterval2 : utcInterval)(interval3);\n if (typeof interval3.floor !== \"function\") throw new Error(\"invalid interval; missing floor method\");\n if (typeof interval3.offset !== \"function\") throw new Error(\"invalid interval; missing offset method\");\n return interval3;\n}\nfunction numberInterval(interval3) {\n interval3 = +interval3;\n if (0 < interval3 && interval3 < 1 && Number.isInteger(1 / interval3)) interval3 = -1 / interval3;\n const n = Math.abs(interval3);\n return interval3 < 0 ? {\n floor: (d) => Math.floor(d * n) / n,\n offset: (d, s2 = 1) => (d * n + Math.floor(s2)) / n,\n range: (lo, hi) => range(Math.ceil(lo * n), hi * n).map((x3) => x3 / n)\n } : {\n floor: (d) => Math.floor(d / n) * n,\n offset: (d, s2 = 1) => d + n * Math.floor(s2),\n range: (lo, hi) => range(Math.ceil(lo / n), hi / n).map((x3) => x3 * n)\n };\n}\nfunction maybeRangeInterval(interval3, type2) {\n interval3 = maybeInterval(interval3, type2);\n if (interval3 && typeof interval3.range !== \"function\") throw new Error(\"invalid interval: missing range method\");\n return interval3;\n}\nfunction maybeNiceInterval(interval3, type2) {\n interval3 = maybeRangeInterval(interval3, type2);\n if (interval3 && typeof interval3.ceil !== \"function\") throw new Error(\"invalid interval: missing ceil method\");\n return interval3;\n}\nfunction isTimeInterval(t) {\n return isInterval(t) && typeof t?.floor === \"function\" && t.floor() instanceof Date;\n}\nfunction isInterval(t) {\n return typeof t?.range === \"function\";\n}\nfunction maybeValue(value) {\n return value === void 0 || isOptions(value) ? value : { value };\n}\nfunction numberChannel(source) {\n return source == null ? null : {\n transform: (data) => valueof(data, source, Float64Array),\n label: labelof(source)\n };\n}\nfunction isTuples(data) {\n if (!isIterable(data)) return false;\n for (const d of data) {\n if (d == null) continue;\n return typeof d === \"object\" && \"0\" in d && \"1\" in d;\n }\n}\nfunction isIterable(value) {\n return value && typeof value[Symbol.iterator] === \"function\";\n}\nfunction isTextual(values2) {\n for (const value of values2) {\n if (value == null) continue;\n return typeof value !== \"object\" || value instanceof Date;\n }\n}\nfunction isOrdinal(values2) {\n for (const value of values2) {\n if (value == null) continue;\n const type2 = typeof value;\n return type2 === \"string\" || type2 === \"boolean\";\n }\n}\nfunction isTemporal(values2) {\n for (const value of values2) {\n if (value == null) continue;\n return value instanceof Date;\n }\n}\nfunction isTemporalString(values2) {\n for (const value of values2) {\n if (value == null) continue;\n return typeof value === \"string\" && isNaN(value) && parse(value);\n }\n}\nfunction isNumericString(values2) {\n for (const value of values2) {\n if (value == null) continue;\n if (typeof value !== \"string\") return false;\n if (!value.trim()) continue;\n return !isNaN(value);\n }\n}\nfunction isNumeric(values2) {\n for (const value of values2) {\n if (value == null) continue;\n return typeof value === \"number\";\n }\n}\nfunction isEvery(values2, is) {\n let every;\n for (const value of values2) {\n if (value == null) continue;\n if (!is(value)) return false;\n every = true;\n }\n return every;\n}\nvar namedColors = new Set(\"none,currentcolor,transparent,aliceblue,antiquewhite,aqua,aquamarine,azure,beige,bisque,black,blanchedalmond,blue,blueviolet,brown,burlywood,cadetblue,chartreuse,chocolate,coral,cornflowerblue,cornsilk,crimson,cyan,darkblue,darkcyan,darkgoldenrod,darkgray,darkgreen,darkgrey,darkkhaki,darkmagenta,darkolivegreen,darkorange,darkorchid,darkred,darksalmon,darkseagreen,darkslateblue,darkslategray,darkslategrey,darkturquoise,darkviolet,deeppink,deepskyblue,dimgray,dimgrey,dodgerblue,firebrick,floralwhite,forestgreen,fuchsia,gainsboro,ghostwhite,gold,goldenrod,gray,green,greenyellow,grey,honeydew,hotpink,indianred,indigo,ivory,khaki,lavender,lavenderblush,lawngreen,lemonchiffon,lightblue,lightcoral,lightcyan,lightgoldenrodyellow,lightgray,lightgreen,lightgrey,lightpink,lightsalmon,lightseagreen,lightskyblue,lightslategray,lightslategrey,lightsteelblue,lightyellow,lime,limegreen,linen,magenta,maroon,mediumaquamarine,mediumblue,mediumorchid,mediumpurple,mediumseagreen,mediumslateblue,mediumspringgreen,mediumturquoise,mediumvioletred,midnightblue,mintcream,mistyrose,moccasin,navajowhite,navy,oldlace,olive,olivedrab,orange,orangered,orchid,palegoldenrod,palegreen,paleturquoise,palevioletred,papayawhip,peachpuff,peru,pink,plum,powderblue,purple,rebeccapurple,red,rosybrown,royalblue,saddlebrown,salmon,sandybrown,seagreen,seashell,sienna,silver,skyblue,slateblue,slategray,slategrey,snow,springgreen,steelblue,tan,teal,thistle,tomato,turquoise,violet,wheat,white,whitesmoke,yellow\".split(\",\"));\nfunction isColor(value) {\n if (typeof value !== \"string\") return false;\n value = value.toLowerCase().trim();\n return /^#[0-9a-f]{3,8}$/.test(value) || // hex rgb, rgba, rrggbb, rrggbbaa\n /^(?:url|var|rgb|rgba|hsl|hsla|hwb|lab|lch|oklab|oklch|color|color-mix)\\(.*\\)$/.test(value) || // , CSS variable, color, etc.\n namedColors.has(value);\n}\nfunction isOpacity(value) {\n return typeof value === \"number\" && (0 <= value && value <= 1 || isNaN(value));\n}\nfunction isNoneish(value) {\n return value == null || isNone(value);\n}\nfunction isNone(value) {\n return /^\\s*none\\s*$/i.test(value);\n}\nfunction isRound(value) {\n return /^\\s*round\\s*$/i.test(value);\n}\nfunction maybeAnchor(value, name2) {\n return maybeKeyword(value, name2, [\n \"middle\",\n \"top-left\",\n \"top\",\n \"top-right\",\n \"right\",\n \"bottom-right\",\n \"bottom\",\n \"bottom-left\",\n \"left\"\n ]);\n}\nfunction maybeFrameAnchor(value = \"middle\") {\n return maybeAnchor(value, \"frameAnchor\");\n}\nfunction inherit2(options = {}, ...rest) {\n let o = options;\n for (const defaults22 of rest) {\n for (const key in defaults22) {\n if (o[key] === void 0) {\n const value = defaults22[key];\n if (o === options) o = { ...o, [key]: value };\n else o[key] = value;\n }\n }\n }\n return o;\n}\nfunction named2(things) {\n console.warn(\"named iterables are deprecated; please use an object instead\");\n const names = /* @__PURE__ */ new Set();\n return Object.fromEntries(\n Array.from(things, (thing) => {\n const { name: name2 } = thing;\n if (name2 == null) throw new Error(\"missing name\");\n const key = `${name2}`;\n if (key === \"__proto__\") throw new Error(`illegal name: ${key}`);\n if (names.has(key)) throw new Error(`duplicate name: ${key}`);\n names.add(key);\n return [name2, thing];\n })\n );\n}\nfunction maybeNamed(things) {\n return isIterable(things) ? named2(things) : things;\n}\nfunction maybeClip(clip) {\n if (clip === true) clip = \"frame\";\n else if (clip === false) clip = null;\n else if (clip != null) clip = keyword(clip, \"clip\", [\"frame\", \"sphere\"]);\n return clip;\n}\nfunction isArrowTable2(value) {\n return value && typeof value.getChild === \"function\" && typeof value.toArray === \"function\" && value.schema && Array.isArray(value.schema.fields);\n}\nfunction isArrowVector(value) {\n return value && typeof value.toArray === \"function\" && value.type;\n}\nfunction isArrowDateType(type2) {\n return type2 && (type2.typeId === 8 || // date\n type2.typeId === 10) && // timestamp\n type2.unit === 1;\n}\n\n// ../../node_modules/@observablehq/plot/src/scales/index.js\nvar position = Symbol(\"position\");\nvar color2 = Symbol(\"color\");\nvar radius = Symbol(\"radius\");\nvar length3 = Symbol(\"length\");\nvar opacity = Symbol(\"opacity\");\nvar symbol = Symbol(\"symbol\");\nvar projection2 = Symbol(\"projection\");\nvar registry = /* @__PURE__ */ new Map([\n [\"x\", position],\n [\"y\", position],\n [\"fx\", position],\n [\"fy\", position],\n [\"r\", radius],\n [\"color\", color2],\n [\"opacity\", opacity],\n [\"symbol\", symbol],\n [\"length\", length3],\n [\"projection\", projection2]\n]);\nfunction isPosition(kind) {\n return kind === position || kind === projection2;\n}\nfunction hasNumericRange(kind) {\n return kind === position || kind === radius || kind === length3 || kind === opacity;\n}\n\n// ../../node_modules/@observablehq/plot/src/symbol.js\nvar sqrt35 = Math.sqrt(3);\nvar sqrt4_3 = 2 / sqrt35;\nvar symbolHexagon = {\n draw(context, size) {\n const rx = Math.sqrt(size / Math.PI), ry = rx * sqrt4_3, hy = ry / 2;\n context.moveTo(0, ry);\n context.lineTo(rx, hy);\n context.lineTo(rx, -hy);\n context.lineTo(0, -ry);\n context.lineTo(-rx, -hy);\n context.lineTo(-rx, hy);\n context.closePath();\n }\n};\nvar symbols = /* @__PURE__ */ new Map([\n [\"asterisk\", asterisk_default],\n [\"circle\", circle_default2],\n [\"cross\", cross_default],\n [\"diamond\", diamond_default],\n [\"diamond2\", diamond2_default],\n [\"hexagon\", symbolHexagon],\n [\"plus\", plus_default],\n [\"square\", square_default],\n [\"square2\", square2_default],\n [\"star\", star_default],\n [\"times\", times_default],\n [\"triangle\", triangle_default],\n [\"triangle2\", triangle2_default],\n [\"wye\", wye_default]\n]);\nfunction isSymbolObject(value) {\n return value && typeof value.draw === \"function\";\n}\nfunction isSymbol(value) {\n if (isSymbolObject(value)) return true;\n if (typeof value !== \"string\") return false;\n return symbols.has(value.toLowerCase());\n}\nfunction maybeSymbol(symbol2) {\n if (symbol2 == null || isSymbolObject(symbol2)) return symbol2;\n const value = symbols.get(`${symbol2}`.toLowerCase());\n if (value) return value;\n throw new Error(`invalid symbol: ${symbol2}`);\n}\nfunction maybeSymbolChannel(symbol2) {\n if (symbol2 == null || isSymbolObject(symbol2)) return [void 0, symbol2];\n if (typeof symbol2 === \"string\") {\n const value = symbols.get(`${symbol2}`.toLowerCase());\n if (value) return [void 0, value];\n }\n return [symbol2, void 0];\n}\n\n// ../../node_modules/@observablehq/plot/src/transforms/basic.js\nfunction basic({ filter: f1, sort: s1, reverse: r1, transform: t13, initializer: i1, ...options } = {}, transform3) {\n if (t13 === void 0) {\n if (f1 != null) t13 = filterTransform(f1);\n if (s1 != null && !isDomainSort(s1)) t13 = composeTransform(t13, sortTransform(s1));\n if (r1) t13 = composeTransform(t13, reverseTransform);\n }\n if (transform3 != null && i1 != null) throw new Error(\"transforms cannot be applied after initializers\");\n return {\n ...options,\n ...(s1 === null || isDomainSort(s1)) && { sort: s1 },\n transform: composeTransform(t13, transform3)\n };\n}\nfunction initializer({ filter: f1, sort: s1, reverse: r1, initializer: i1, ...options } = {}, initializer2) {\n if (i1 === void 0) {\n if (f1 != null) i1 = filterTransform(f1);\n if (s1 != null && !isDomainSort(s1)) i1 = composeInitializer(i1, sortTransform(s1));\n if (r1) i1 = composeInitializer(i1, reverseTransform);\n }\n return {\n ...options,\n ...(s1 === null || isDomainSort(s1)) && { sort: s1 },\n initializer: composeInitializer(i1, initializer2)\n };\n}\nfunction composeTransform(t13, t22) {\n if (t13 == null) return t22 === null ? void 0 : t22;\n if (t22 == null) return t13 === null ? void 0 : t13;\n return function(data, facets, plotOptions) {\n ({ data, facets } = t13.call(this, data, facets, plotOptions));\n return t22.call(this, dataify(data), facets, plotOptions);\n };\n}\nfunction composeInitializer(i1, i2) {\n if (i1 == null) return i2 === null ? void 0 : i2;\n if (i2 == null) return i1 === null ? void 0 : i1;\n return function(data, facets, channels, ...args) {\n let c1, d1, f1, c22, d2, f2;\n ({ data: d1 = data, facets: f1 = facets, channels: c1 } = i1.call(this, data, facets, channels, ...args));\n ({ data: d2 = d1, facets: f2 = f1, channels: c22 } = i2.call(this, d1, f1, { ...channels, ...c1 }, ...args));\n return { data: d2, facets: f2, channels: { ...c1, ...c22 } };\n };\n}\nfunction apply(options, t) {\n return (options.initializer != null ? initializer : basic)(options, t);\n}\nfunction filter2(test, options) {\n return apply(options, filterTransform(test));\n}\nfunction filterTransform(value) {\n return (data, facets) => {\n const V = valueof(data, value);\n return { data, facets: facets.map((I) => I.filter((i) => V[i])) };\n };\n}\nfunction reverse2({ sort: sort3, ...options } = {}) {\n return {\n ...apply(options, reverseTransform),\n sort: isDomainSort(sort3) ? sort3 : null\n };\n}\nfunction reverseTransform(data, facets) {\n return { data, facets: facets.map((I) => I.slice().reverse()) };\n}\nfunction shuffle({ seed, sort: sort3, ...options } = {}) {\n return {\n ...apply(options, sortValue(seed == null ? Math.random : lcg(seed))),\n sort: isDomainSort(sort3) ? sort3 : null\n };\n}\nfunction sort2(order, { sort: sort3, ...options } = {}) {\n return {\n ...(isOptions(order) && order.channel !== void 0 ? initializer : apply)(options, sortTransform(order)),\n sort: isDomainSort(sort3) ? sort3 : null\n };\n}\nfunction sortTransform(value) {\n return (typeof value === \"function\" && value.length !== 1 ? sortData : sortValue)(value);\n}\nfunction sortData(compare) {\n return (data, facets) => {\n const compareData = isArray2(data) ? (i, j) => compare(data[i], data[j]) : (i, j) => compare(data.get(i), data.get(j));\n return { data, facets: facets.map((I) => I.slice().sort(compareData)) };\n };\n}\nfunction sortValue(value) {\n let channel, order;\n ({ channel, value, order } = { ...maybeValue(value) });\n const negate2 = channel?.startsWith(\"-\");\n if (negate2) channel = channel.slice(1);\n if (order === void 0) order = negate2 ? descendingDefined : ascendingDefined2;\n if (typeof order !== \"function\") {\n switch (`${order}`.toLowerCase()) {\n case \"ascending\":\n order = ascendingDefined2;\n break;\n case \"descending\":\n order = descendingDefined;\n break;\n default:\n throw new Error(`invalid order: ${order}`);\n }\n }\n return (data, facets, channels) => {\n let V;\n if (channel === void 0) {\n V = valueof(data, value);\n } else {\n if (channels === void 0) throw new Error(\"channel sort requires an initializer\");\n V = channels[channel];\n if (!V) return {};\n V = V.value;\n }\n const compareValue = (i, j) => order(V[i], V[j]);\n return { data, facets: facets.map((I) => I.slice().sort(compareValue)) };\n };\n}\n\n// ../../node_modules/@observablehq/plot/src/transforms/group.js\nfunction groupZ(outputs, options) {\n return groupn(null, null, outputs, options);\n}\nfunction groupX(outputs = { y: \"count\" }, options = {}) {\n const { x: x3 = identity7 } = options;\n if (x3 == null) throw new Error(\"missing channel: x\");\n return groupn(x3, null, outputs, options);\n}\nfunction groupY(outputs = { x: \"count\" }, options = {}) {\n const { y: y3 = identity7 } = options;\n if (y3 == null) throw new Error(\"missing channel: y\");\n return groupn(null, y3, outputs, options);\n}\nfunction group2(outputs = { fill: \"count\" }, options = {}) {\n let { x: x3, y: y3 } = options;\n [x3, y3] = maybeTuple(x3, y3);\n if (x3 == null) throw new Error(\"missing channel: x\");\n if (y3 == null) throw new Error(\"missing channel: y\");\n return groupn(x3, y3, outputs, options);\n}\nfunction groupn(x3, y3, {\n data: reduceData = reduceIdentity,\n filter: filter3,\n sort: sort3,\n reverse: reverse3,\n ...outputs\n // output channel definitions\n} = {}, inputs = {}) {\n outputs = maybeGroupOutputs(outputs, inputs);\n reduceData = maybeGroupReduce(reduceData, identity7);\n sort3 = sort3 == null ? void 0 : maybeGroupOutput(\"sort\", sort3, inputs);\n filter3 = filter3 == null ? void 0 : maybeGroupEvaluator(\"filter\", filter3, inputs);\n const [GX, setGX] = maybeColumn(x3);\n const [GY, setGY] = maybeColumn(y3);\n const {\n z,\n fill,\n stroke,\n x1: x12,\n x2: x22,\n // consumed if x is an output\n y1: y12,\n y2: y22,\n // consumed if y is an output\n ...options\n } = inputs;\n const [GZ, setGZ] = maybeColumn(z);\n const [vfill] = maybeColorChannel(fill);\n const [vstroke] = maybeColorChannel(stroke);\n const [GF, setGF] = maybeColumn(vfill);\n const [GS, setGS] = maybeColumn(vstroke);\n return {\n ...\"z\" in inputs && { z: GZ || z },\n ...\"fill\" in inputs && { fill: GF || fill },\n ...\"stroke\" in inputs && { stroke: GS || stroke },\n ...basic(options, (data, facets, plotOptions) => {\n const X3 = maybeApplyInterval(valueof(data, x3), plotOptions?.x);\n const Y3 = maybeApplyInterval(valueof(data, y3), plotOptions?.y);\n const Z = valueof(data, z);\n const F = valueof(data, vfill);\n const S = valueof(data, vstroke);\n const G = maybeSubgroup(outputs, { z: Z, fill: F, stroke: S });\n const groupFacets = [];\n const groupData = [];\n const GX2 = X3 && setGX([]);\n const GY2 = Y3 && setGY([]);\n const GZ2 = Z && setGZ([]);\n const GF2 = F && setGF([]);\n const GS2 = S && setGS([]);\n let i = 0;\n for (const o of outputs) o.initialize(data);\n if (sort3) sort3.initialize(data);\n if (filter3) filter3.initialize(data);\n for (const facet of facets) {\n const groupFacet = [];\n for (const o of outputs) o.scope(\"facet\", facet);\n if (sort3) sort3.scope(\"facet\", facet);\n if (filter3) filter3.scope(\"facet\", facet);\n for (const [f, I] of maybeGroup(facet, G)) {\n for (const [y4, gg] of maybeGroup(I, Y3)) {\n for (const [x4, g] of maybeGroup(gg, X3)) {\n const extent4 = { data };\n if (X3) extent4.x = x4;\n if (Y3) extent4.y = y4;\n if (G) extent4.z = f;\n if (filter3 && !filter3.reduce(g, extent4)) continue;\n groupFacet.push(i++);\n groupData.push(reduceData.reduceIndex(g, data, extent4));\n if (X3) GX2.push(x4);\n if (Y3) GY2.push(y4);\n if (Z) GZ2.push(G === Z ? f : Z[g[0]]);\n if (F) GF2.push(G === F ? f : F[g[0]]);\n if (S) GS2.push(G === S ? f : S[g[0]]);\n for (const o of outputs) o.reduce(g, extent4);\n if (sort3) sort3.reduce(g, extent4);\n }\n }\n }\n groupFacets.push(groupFacet);\n }\n maybeSort(groupFacets, sort3, reverse3);\n return { data: groupData, facets: groupFacets };\n }),\n ...!hasOutput(outputs, \"x\") && (GX ? { x: GX } : { x1: x12, x2: x22 }),\n ...!hasOutput(outputs, \"y\") && (GY ? { y: GY } : { y1: y12, y2: y22 }),\n ...Object.fromEntries(outputs.map(({ name: name2, output }) => [name2, output]))\n };\n}\nfunction hasOutput(outputs, ...names) {\n for (const { name: name2 } of outputs) {\n if (names.includes(name2)) {\n return true;\n }\n }\n return false;\n}\nfunction maybeOutputs(outputs, inputs, asOutput = maybeOutput) {\n const entries = Object.entries(outputs);\n if (inputs.title != null && outputs.title === void 0) entries.push([\"title\", reduceTitle]);\n if (inputs.href != null && outputs.href === void 0) entries.push([\"href\", reduceFirst]);\n return entries.filter(([, reduce]) => reduce !== void 0).map(([name2, reduce]) => reduce === null ? nullOutput(name2) : asOutput(name2, reduce, inputs));\n}\nfunction maybeOutput(name2, reduce, inputs, asEvaluator = maybeEvaluator) {\n let scale3;\n if (isObject(reduce) && \"reduce\" in reduce) scale3 = reduce.scale, reduce = reduce.reduce;\n const evaluator = asEvaluator(name2, reduce, inputs);\n const [output, setOutput] = column2(evaluator.label);\n let O;\n return {\n name: name2,\n output: scale3 === void 0 ? output : { value: output, scale: scale3 },\n initialize(data) {\n evaluator.initialize(data);\n O = setOutput([]);\n },\n scope(scope, I) {\n evaluator.scope(scope, I);\n },\n reduce(I, extent4) {\n O.push(evaluator.reduce(I, extent4));\n }\n };\n}\nfunction nullOutput(name2) {\n return { name: name2, initialize() {\n }, scope() {\n }, reduce() {\n } };\n}\nfunction maybeEvaluator(name2, reduce, inputs, asReduce = maybeReduce) {\n const input3 = maybeInput(name2, inputs);\n const reducer2 = asReduce(reduce, input3);\n let V, context;\n return {\n label: labelof(reducer2 === reduceCount ? null : input3, reducer2.label),\n initialize(data) {\n V = input3 === void 0 ? data : valueof(data, input3);\n if (reducer2.scope === \"data\") {\n context = reducer2.reduceIndex(range2(data), V);\n }\n },\n scope(scope, I) {\n if (reducer2.scope === scope) {\n context = reducer2.reduceIndex(I, V);\n }\n },\n reduce(I, extent4) {\n return reducer2.scope == null ? reducer2.reduceIndex(I, V, extent4) : reducer2.reduceIndex(I, V, context, extent4);\n }\n };\n}\nfunction maybeGroup(I, X3) {\n return X3 ? group(I, (i) => X3[i]) : [[, I]];\n}\nfunction maybeReduce(reduce, value, fallback = invalidReduce) {\n if (reduce == null) return fallback(reduce);\n if (typeof reduce.reduceIndex === \"function\") return reduce;\n if (typeof reduce.reduce === \"function\" && isObject(reduce)) return reduceReduce(reduce);\n if (typeof reduce === \"function\") return reduceFunction(reduce);\n if (/^p\\d{2}$/i.test(reduce)) return reduceAccessor(percentile(reduce));\n switch (`${reduce}`.toLowerCase()) {\n case \"first\":\n return reduceFirst;\n case \"last\":\n return reduceLast;\n case \"identity\":\n return reduceIdentity;\n case \"count\":\n return reduceCount;\n case \"distinct\":\n return reduceDistinct;\n case \"sum\":\n return value == null ? reduceCount : reduceSum;\n case \"proportion\":\n return reduceProportion(value, \"data\");\n case \"proportion-facet\":\n return reduceProportion(value, \"facet\");\n case \"deviation\":\n return reduceAccessor(deviation);\n case \"min\":\n return reduceAccessor(min2);\n case \"min-index\":\n return reduceAccessor(minIndex);\n case \"max\":\n return reduceAccessor(max2);\n case \"max-index\":\n return reduceAccessor(maxIndex);\n case \"mean\":\n return reduceMaybeTemporalAccessor(mean2);\n case \"median\":\n return reduceMaybeTemporalAccessor(median2);\n case \"variance\":\n return reduceAccessor(variance2);\n case \"mode\":\n return reduceAccessor(mode2);\n }\n return fallback(reduce);\n}\nfunction invalidReduce(reduce) {\n throw new Error(`invalid reduce: ${reduce}`);\n}\nfunction maybeGroupOutputs(outputs, inputs) {\n return maybeOutputs(outputs, inputs, maybeGroupOutput);\n}\nfunction maybeGroupOutput(name2, reduce, inputs) {\n return maybeOutput(name2, reduce, inputs, maybeGroupEvaluator);\n}\nfunction maybeGroupEvaluator(name2, reduce, inputs) {\n return maybeEvaluator(name2, reduce, inputs, maybeGroupReduce);\n}\nfunction maybeGroupReduce(reduce, value) {\n return maybeReduce(reduce, value, maybeGroupReduceFallback);\n}\nfunction maybeGroupReduceFallback(reduce) {\n switch (`${reduce}`.toLowerCase()) {\n case \"x\":\n return reduceX;\n case \"y\":\n return reduceY;\n case \"z\":\n return reduceZ;\n }\n throw new Error(`invalid group reduce: ${reduce}`);\n}\nfunction maybeSubgroup(outputs, inputs) {\n for (const name2 in inputs) {\n const value = inputs[name2];\n if (value !== void 0 && !outputs.some((o) => o.name === name2)) {\n return value;\n }\n }\n}\nfunction maybeSort(facets, sort3, reverse3) {\n if (sort3) {\n const S = sort3.output.transform();\n const compare = (i, j) => ascendingDefined2(S[i], S[j]);\n facets.forEach((f) => f.sort(compare));\n }\n if (reverse3) {\n facets.forEach((f) => f.reverse());\n }\n}\nfunction reduceReduce(reduce) {\n console.warn(\"deprecated reduce interface; implement reduceIndex instead.\");\n return { ...reduce, reduceIndex: reduce.reduce.bind(reduce) };\n}\nfunction reduceFunction(f) {\n return {\n reduceIndex(I, X3, extent4) {\n return f(take(X3, I), extent4);\n }\n };\n}\nfunction reduceAccessor(f) {\n return {\n reduceIndex(I, X3) {\n return f(I, (i) => X3[i]);\n }\n };\n}\nfunction reduceMaybeTemporalAccessor(f) {\n return {\n reduceIndex(I, X3) {\n const x3 = f(I, (i) => X3[i]);\n return isTemporal(X3) ? new Date(x3) : x3;\n }\n };\n}\nvar reduceIdentity = {\n reduceIndex(I, X3) {\n return take(X3, I);\n }\n};\nvar reduceFirst = {\n reduceIndex(I, X3) {\n return X3[I[0]];\n }\n};\nvar reduceTitle = {\n reduceIndex(I, X3) {\n const n = 5;\n const groups2 = sort(\n rollup(\n I,\n (V) => V.length,\n (i) => X3[i]\n ),\n second2\n );\n const top2 = groups2.slice(-n).reverse();\n if (top2.length < groups2.length) {\n const bottom2 = groups2.slice(0, 1 - n);\n top2[n - 1] = [`\\u2026 ${bottom2.length.toLocaleString(\"en-US\")} more`, sum2(bottom2, second2)];\n }\n return top2.map(([key, value]) => `${key} (${value.toLocaleString(\"en-US\")})`).join(\"\\n\");\n }\n};\nvar reduceLast = {\n reduceIndex(I, X3) {\n return X3[I[I.length - 1]];\n }\n};\nvar reduceCount = {\n label: \"Frequency\",\n reduceIndex(I) {\n return I.length;\n }\n};\nvar reduceDistinct = {\n label: \"Distinct\",\n reduceIndex(I, X3) {\n const s2 = new InternSet();\n for (const i of I) s2.add(X3[i]);\n return s2.size;\n }\n};\nvar reduceSum = reduceAccessor(sum2);\nfunction reduceProportion(value, scope) {\n return value == null ? { scope, label: \"Frequency\", reduceIndex: (I, V, basis2 = 1) => I.length / basis2 } : { scope, reduceIndex: (I, V, basis2 = 1) => sum2(I, (i) => V[i]) / basis2 };\n}\nvar reduceX = {\n reduceIndex(I, X3, { x: x3 }) {\n return x3;\n }\n};\nvar reduceY = {\n reduceIndex(I, X3, { y: y3 }) {\n return y3;\n }\n};\nvar reduceZ = {\n reduceIndex(I, X3, { z }) {\n return z;\n }\n};\nfunction find2(test) {\n if (typeof test !== \"function\") throw new Error(`invalid test function: ${test}`);\n return {\n reduceIndex(I, V, { data }) {\n return V[I.find(isArray2(data) ? (i) => test(data[i], i, data) : (i) => test(data.get(i), i, data))];\n }\n };\n}\n\n// ../../node_modules/@observablehq/plot/src/channel.js\nfunction createChannel(data, { scale: scale3, type: type2, value, filter: filter3, hint, label: label2 = labelof(value) }, name2) {\n if (hint === void 0 && typeof value?.transform === \"function\") hint = value.hint;\n const cs = inferChannelScale(name2, {\n scale: scale3,\n type: type2,\n value: valueof(data, value),\n label: label2,\n filter: filter3,\n hint\n });\n return cs;\n}\nfunction createChannels(channels, data) {\n return Object.fromEntries(\n Object.entries(channels).map(([name2, channel]) => [name2, createChannel(data, channel, name2)])\n );\n}\nfunction valueObject(channels, scales2) {\n const values2 = Object.fromEntries(\n Object.entries(channels).map(([name2, { scale: scaleName, value }]) => {\n const scale3 = scaleName == null ? null : scales2[scaleName];\n return [name2, scale3 == null ? value : map3(value, scale3)];\n })\n );\n values2.channels = channels;\n return values2;\n}\nfunction inferChannelScale(name2, channel) {\n const { scale: scale3, value } = channel;\n if (scale3 === true || scale3 === \"auto\") {\n switch (name2) {\n case \"fill\":\n case \"stroke\":\n case \"color\":\n channel.scale = scale3 !== true && isEvery(value, isColor) ? null : \"color\";\n channel.defaultScale = \"color\";\n break;\n case \"fillOpacity\":\n case \"strokeOpacity\":\n case \"opacity\":\n channel.scale = scale3 !== true && isEvery(value, isOpacity) ? null : \"opacity\";\n channel.defaultScale = \"opacity\";\n break;\n case \"symbol\":\n if (scale3 !== true && isEvery(value, isSymbol)) {\n channel.scale = null;\n channel.value = map3(value, maybeSymbol);\n } else {\n channel.scale = \"symbol\";\n }\n channel.defaultScale = \"symbol\";\n break;\n default:\n channel.scale = registry.has(name2) ? name2 : null;\n break;\n }\n } else if (scale3 === false) {\n channel.scale = null;\n } else if (scale3 != null && !registry.has(scale3)) {\n throw new Error(`unknown scale: ${scale3}`);\n }\n return channel;\n}\nfunction channelDomain(data, facets, channels, facetChannels, options) {\n const { order: defaultOrder, reverse: defaultReverse, reduce: defaultReduce = true, limit: defaultLimit } = options;\n for (const x3 in options) {\n if (!registry.has(x3)) continue;\n let { value: y3, order = defaultOrder, reverse: reverse3 = defaultReverse, reduce = defaultReduce, limit = defaultLimit } = maybeValue(options[x3]);\n const negate2 = y3?.startsWith(\"-\");\n if (negate2) y3 = y3.slice(1);\n order = order === void 0 ? negate2 !== (y3 === \"width\" || y3 === \"height\") ? descendingGroup : ascendingGroup : maybeOrder(order);\n if (reduce == null || reduce === false) continue;\n const X3 = x3 === \"fx\" || x3 === \"fy\" ? reindexFacetChannel(facets, facetChannels[x3]) : findScaleChannel(channels, x3);\n if (!X3) throw new Error(`missing channel for scale: ${x3}`);\n const XV = X3.value;\n const [lo = 0, hi = Infinity] = isIterable(limit) ? limit : limit < 0 ? [limit] : [0, limit];\n if (y3 == null) {\n X3.domain = () => {\n let domain = Array.from(new InternSet(XV));\n if (reverse3) domain = domain.reverse();\n if (lo !== 0 || hi !== Infinity) domain = domain.slice(lo, hi);\n return domain;\n };\n } else {\n const YV = y3 === \"data\" ? data : y3 === \"height\" ? difference(channels, \"y1\", \"y2\") : y3 === \"width\" ? difference(channels, \"x1\", \"x2\") : values(channels, y3, y3 === \"y\" ? \"y2\" : y3 === \"x\" ? \"x2\" : void 0);\n const reducer2 = maybeReduce(reduce === true ? \"max\" : reduce, YV);\n X3.domain = () => {\n let domain = rollups(\n range2(XV),\n (I) => reducer2.reduceIndex(I, YV),\n (i) => XV[i]\n );\n if (order) domain.sort(order);\n if (reverse3) domain.reverse();\n if (lo !== 0 || hi !== Infinity) domain = domain.slice(lo, hi);\n return domain.map(first2);\n };\n }\n }\n}\nfunction findScaleChannel(channels, scale3) {\n for (const name2 in channels) {\n const channel = channels[name2];\n if (channel.scale === scale3) return channel;\n }\n}\nfunction reindexFacetChannel(facets, channel) {\n const originalFacets = facets.original;\n if (originalFacets === facets) return channel;\n const V1 = channel.value;\n const V2 = channel.value = [];\n for (let i = 0; i < originalFacets.length; ++i) {\n const vi = V1[originalFacets[i][0]];\n for (const j of facets[i]) V2[j] = vi;\n }\n return channel;\n}\nfunction difference(channels, k1, k2) {\n const X13 = values(channels, k1);\n const X23 = values(channels, k2);\n return map3(X23, (x22, i) => Math.abs(x22 - X13[i]), Float64Array);\n}\nfunction values(channels, name2, alias) {\n let channel = channels[name2];\n if (!channel && alias !== void 0) channel = channels[alias];\n if (channel) return channel.value;\n throw new Error(`missing channel: ${name2}`);\n}\nfunction maybeOrder(order) {\n if (order == null || typeof order === \"function\") return order;\n switch (`${order}`.toLowerCase()) {\n case \"ascending\":\n return ascendingGroup;\n case \"descending\":\n return descendingGroup;\n }\n throw new Error(`invalid order: ${order}`);\n}\nfunction ascendingGroup([ak, av], [bk, bv]) {\n return ascendingDefined2(av, bv) || ascendingDefined2(ak, bk);\n}\nfunction descendingGroup([ak, av], [bk, bv]) {\n return descendingDefined(av, bv) || ascendingDefined2(ak, bk);\n}\nfunction getSource(channels, key) {\n let channel = channels[key];\n if (!channel) return;\n while (channel.source) channel = channel.source;\n return channel.source === null ? null : channel;\n}\n\n// ../../node_modules/@observablehq/plot/src/scales/schemes.js\nvar categoricalSchemes = /* @__PURE__ */ new Map([\n [\"accent\", Accent_default],\n [\"category10\", category10_default],\n [\"dark2\", Dark2_default],\n [\"observable10\", observable10_default],\n [\"paired\", Paired_default],\n [\"pastel1\", Pastel1_default],\n [\"pastel2\", Pastel2_default],\n [\"set1\", Set1_default],\n [\"set2\", Set2_default],\n [\"set3\", Set3_default],\n [\"tableau10\", Tableau10_default]\n]);\nfunction isCategoricalScheme(scheme28) {\n return scheme28 != null && categoricalSchemes.has(`${scheme28}`.toLowerCase());\n}\nvar ordinalSchemes = new Map([\n ...categoricalSchemes,\n // diverging\n [\"brbg\", scheme112(scheme, BrBG_default)],\n [\"prgn\", scheme112(scheme2, PRGn_default)],\n [\"piyg\", scheme112(scheme3, PiYG_default)],\n [\"puor\", scheme112(scheme4, PuOr_default)],\n [\"rdbu\", scheme112(scheme5, RdBu_default)],\n [\"rdgy\", scheme112(scheme6, RdGy_default)],\n [\"rdylbu\", scheme112(scheme7, RdYlBu_default)],\n [\"rdylgn\", scheme112(scheme8, RdYlGn_default)],\n [\"spectral\", scheme112(scheme9, Spectral_default)],\n // reversed diverging (for temperature data)\n [\"burd\", scheme11r(scheme5, RdBu_default)],\n [\"buylrd\", scheme11r(scheme7, RdYlBu_default)],\n // sequential (single-hue)\n [\"blues\", scheme92(scheme22, Blues_default)],\n [\"greens\", scheme92(scheme23, Greens_default)],\n [\"greys\", scheme92(scheme24, Greys_default)],\n [\"oranges\", scheme92(scheme27, Oranges_default)],\n [\"purples\", scheme92(scheme25, Purples_default)],\n [\"reds\", scheme92(scheme26, Reds_default)],\n // sequential (multi-hue)\n [\"turbo\", schemei(turbo_default)],\n [\"viridis\", schemei(viridis_default)],\n [\"magma\", schemei(magma)],\n [\"inferno\", schemei(inferno)],\n [\"plasma\", schemei(plasma)],\n [\"cividis\", schemei(cividis_default)],\n [\"cubehelix\", schemei(cubehelix_default2)],\n [\"warm\", schemei(warm)],\n [\"cool\", schemei(cool)],\n [\"bugn\", scheme92(scheme10, BuGn_default)],\n [\"bupu\", scheme92(scheme11, BuPu_default)],\n [\"gnbu\", scheme92(scheme12, GnBu_default)],\n [\"orrd\", scheme92(scheme13, OrRd_default)],\n [\"pubu\", scheme92(scheme15, PuBu_default)],\n [\"pubugn\", scheme92(scheme14, PuBuGn_default)],\n [\"purd\", scheme92(scheme16, PuRd_default)],\n [\"rdpu\", scheme92(scheme17, RdPu_default)],\n [\"ylgn\", scheme92(scheme19, YlGn_default)],\n [\"ylgnbu\", scheme92(scheme18, YlGnBu_default)],\n [\"ylorbr\", scheme92(scheme20, YlOrBr_default)],\n [\"ylorrd\", scheme92(scheme21, YlOrRd_default)],\n // cyclical\n [\"rainbow\", schemeicyclical(rainbow_default)],\n [\"sinebow\", schemeicyclical(sinebow_default)]\n]);\nfunction scheme92(scheme28, interpolate) {\n return ({ length: n }) => {\n if (n === 1) return [scheme28[3][1]];\n if (n === 2) return [scheme28[3][1], scheme28[3][2]];\n n = Math.max(3, Math.floor(n));\n return n > 9 ? quantize_default(interpolate, n) : scheme28[n];\n };\n}\nfunction scheme112(scheme28, interpolate) {\n return ({ length: n }) => {\n if (n === 2) return [scheme28[3][0], scheme28[3][2]];\n n = Math.max(3, Math.floor(n));\n return n > 11 ? quantize_default(interpolate, n) : scheme28[n];\n };\n}\nfunction scheme11r(scheme28, interpolate) {\n return ({ length: n }) => {\n if (n === 2) return [scheme28[3][2], scheme28[3][0]];\n n = Math.max(3, Math.floor(n));\n return n > 11 ? quantize_default((t) => interpolate(1 - t), n) : scheme28[n].slice().reverse();\n };\n}\nfunction schemei(interpolate) {\n return ({ length: n }) => quantize_default(interpolate, Math.max(2, Math.floor(n)));\n}\nfunction schemeicyclical(interpolate) {\n return ({ length: n }) => quantize_default(interpolate, Math.floor(n) + 1).slice(0, -1);\n}\nfunction ordinalScheme(scheme28) {\n const s2 = `${scheme28}`.toLowerCase();\n if (!ordinalSchemes.has(s2)) throw new Error(`unknown ordinal scheme: ${s2}`);\n return ordinalSchemes.get(s2);\n}\nfunction ordinalRange(scheme28, length4) {\n const s2 = ordinalScheme(scheme28);\n const r = typeof s2 === \"function\" ? s2({ length: length4 }) : s2;\n return r.length !== length4 ? r.slice(0, length4) : r;\n}\nfunction maybeBooleanRange(domain, scheme28 = \"greys\") {\n const range3 = /* @__PURE__ */ new Set();\n const [f, t] = ordinalRange(scheme28, 2);\n for (const value of domain) {\n if (value == null) continue;\n if (value === true) range3.add(t);\n else if (value === false) range3.add(f);\n else return;\n }\n return [...range3];\n}\nvar quantitativeSchemes = /* @__PURE__ */ new Map([\n // diverging\n [\"brbg\", BrBG_default],\n [\"prgn\", PRGn_default],\n [\"piyg\", PiYG_default],\n [\"puor\", PuOr_default],\n [\"rdbu\", RdBu_default],\n [\"rdgy\", RdGy_default],\n [\"rdylbu\", RdYlBu_default],\n [\"rdylgn\", RdYlGn_default],\n [\"spectral\", Spectral_default],\n // reversed diverging (for temperature data)\n [\"burd\", (t) => RdBu_default(1 - t)],\n [\"buylrd\", (t) => RdYlBu_default(1 - t)],\n // sequential (single-hue)\n [\"blues\", Blues_default],\n [\"greens\", Greens_default],\n [\"greys\", Greys_default],\n [\"purples\", Purples_default],\n [\"reds\", Reds_default],\n [\"oranges\", Oranges_default],\n // sequential (multi-hue)\n [\"turbo\", turbo_default],\n [\"viridis\", viridis_default],\n [\"magma\", magma],\n [\"inferno\", inferno],\n [\"plasma\", plasma],\n [\"cividis\", cividis_default],\n [\"cubehelix\", cubehelix_default2],\n [\"warm\", warm],\n [\"cool\", cool],\n [\"bugn\", BuGn_default],\n [\"bupu\", BuPu_default],\n [\"gnbu\", GnBu_default],\n [\"orrd\", OrRd_default],\n [\"pubugn\", PuBuGn_default],\n [\"pubu\", PuBu_default],\n [\"purd\", PuRd_default],\n [\"rdpu\", RdPu_default],\n [\"ylgnbu\", YlGnBu_default],\n [\"ylgn\", YlGn_default],\n [\"ylorbr\", YlOrBr_default],\n [\"ylorrd\", YlOrRd_default],\n // cyclical\n [\"rainbow\", rainbow_default],\n [\"sinebow\", sinebow_default]\n]);\nfunction quantitativeScheme(scheme28) {\n const s2 = `${scheme28}`.toLowerCase();\n if (!quantitativeSchemes.has(s2)) throw new Error(`unknown quantitative scheme: ${s2}`);\n return quantitativeSchemes.get(s2);\n}\nvar divergingSchemes = /* @__PURE__ */ new Set([\n \"brbg\",\n \"prgn\",\n \"piyg\",\n \"puor\",\n \"rdbu\",\n \"rdgy\",\n \"rdylbu\",\n \"rdylgn\",\n \"spectral\",\n \"burd\",\n \"buylrd\"\n]);\nfunction isDivergingScheme(scheme28) {\n return scheme28 != null && divergingSchemes.has(`${scheme28}`.toLowerCase());\n}\n\n// ../../node_modules/@observablehq/plot/src/scales/quantitative.js\nvar flip = (i) => (t) => i(1 - t);\nvar unit2 = [0, 1];\nvar interpolators = /* @__PURE__ */ new Map([\n // numbers\n [\"number\", number_default],\n // color spaces\n [\"rgb\", rgb_default],\n [\"hsl\", hsl_default],\n [\"hcl\", hcl_default],\n [\"lab\", lab2]\n]);\nfunction maybeInterpolator(interpolate) {\n const i = `${interpolate}`.toLowerCase();\n if (!interpolators.has(i)) throw new Error(`unknown interpolator: ${i}`);\n return interpolators.get(i);\n}\nfunction createScaleQ(key, scale3, channels, {\n type: type2,\n nice: nice3,\n clamp,\n zero: zero3,\n domain = inferAutoDomain(key, channels),\n unknown,\n round: round2,\n scheme: scheme28,\n interval: interval3,\n range: range3 = registry.get(key) === radius ? inferRadialRange(channels, domain) : registry.get(key) === length3 ? inferLengthRange(channels, domain) : registry.get(key) === opacity ? unit2 : void 0,\n interpolate = registry.get(key) === color2 ? scheme28 == null && range3 !== void 0 ? rgb_default : quantitativeScheme(scheme28 !== void 0 ? scheme28 : type2 === \"cyclical\" ? \"rainbow\" : \"turbo\") : round2 ? round_default : number_default,\n reverse: reverse3\n}) {\n interval3 = maybeRangeInterval(interval3, type2);\n if (type2 === \"cyclical\" || type2 === \"sequential\") type2 = \"linear\";\n if (typeof interpolate !== \"function\") interpolate = maybeInterpolator(interpolate);\n reverse3 = !!reverse3;\n if (range3 !== void 0) {\n const n = (domain = arrayify2(domain)).length;\n const m = (range3 = arrayify2(range3)).length;\n if (n !== m) {\n if (interpolate.length === 1) throw new Error(\"invalid piecewise interpolator\");\n interpolate = piecewise(interpolate, range3);\n range3 = void 0;\n }\n }\n if (interpolate.length === 1) {\n if (reverse3) {\n interpolate = flip(interpolate);\n reverse3 = false;\n }\n if (range3 === void 0) {\n range3 = Float64Array.from(domain, (_, i) => i / (domain.length - 1));\n if (range3.length === 2) range3 = unit2;\n }\n scale3.interpolate((range3 === unit2 ? constant : interpolatePiecewise)(interpolate));\n } else {\n scale3.interpolate(interpolate);\n }\n if (zero3) {\n const [min5, max4] = extent(domain);\n if (min5 > 0 || max4 < 0) {\n domain = slice3(domain);\n const o = orderof(domain) || 1;\n if (o === Math.sign(min5)) domain[0] = 0;\n else domain[domain.length - 1] = 0;\n }\n }\n if (reverse3) domain = reverse(domain);\n scale3.domain(domain).unknown(unknown);\n if (nice3) scale3.nice(maybeNice(nice3, type2)), domain = scale3.domain();\n if (range3 !== void 0) scale3.range(range3);\n if (clamp) scale3.clamp(clamp);\n return { type: type2, domain, range: range3, scale: scale3, interpolate, interval: interval3 };\n}\nfunction maybeNice(nice3, type2) {\n return nice3 === true ? void 0 : typeof nice3 === \"number\" ? nice3 : maybeNiceInterval(nice3, type2);\n}\nfunction createScaleLinear(key, channels, options) {\n return createScaleQ(key, linear2(), channels, options);\n}\nfunction createScaleSqrt(key, channels, options) {\n return createScalePow(key, channels, { ...options, exponent: 0.5 });\n}\nfunction createScalePow(key, channels, { exponent = 1, ...options }) {\n return createScaleQ(key, pow3().exponent(exponent), channels, { ...options, type: \"pow\" });\n}\nfunction createScaleLog(key, channels, { base = 10, domain = inferLogDomain(channels), ...options }) {\n return createScaleQ(key, log2().base(base), channels, { ...options, domain });\n}\nfunction createScaleSymlog(key, channels, { constant: constant2 = 1, ...options }) {\n return createScaleQ(key, symlog().constant(constant2), channels, options);\n}\nfunction createScaleQuantile(key, channels, {\n range: range3,\n quantiles = range3 === void 0 ? 5 : (range3 = [...range3]).length,\n // deprecated; use n instead\n n = quantiles,\n scheme: scheme28 = \"rdylbu\",\n domain = inferQuantileDomain(channels),\n unknown,\n interpolate,\n reverse: reverse3\n}) {\n if (range3 === void 0) {\n range3 = interpolate !== void 0 ? quantize_default(interpolate, n) : registry.get(key) === color2 ? ordinalRange(scheme28, n) : void 0;\n }\n if (domain.length > 0) {\n domain = quantile3(domain, range3 === void 0 ? { length: n } : range3).quantiles();\n }\n return createScaleThreshold(key, channels, { domain, range: range3, reverse: reverse3, unknown });\n}\nfunction createScaleQuantize(key, channels, {\n range: range3,\n n = range3 === void 0 ? 5 : (range3 = [...range3]).length,\n scheme: scheme28 = \"rdylbu\",\n domain = inferAutoDomain(key, channels),\n unknown,\n interpolate,\n reverse: reverse3\n}) {\n const [min5, max4] = extent(domain);\n let thresholds;\n if (range3 === void 0) {\n thresholds = ticks(min5, max4, n);\n if (thresholds[0] <= min5) thresholds.splice(0, 1);\n if (thresholds[thresholds.length - 1] >= max4) thresholds.pop();\n n = thresholds.length + 1;\n range3 = interpolate !== void 0 ? quantize_default(interpolate, n) : registry.get(key) === color2 ? ordinalRange(scheme28, n) : void 0;\n } else {\n thresholds = quantize_default(number_default(min5, max4), n + 1).slice(1, -1);\n if (min5 instanceof Date) thresholds = thresholds.map((x3) => new Date(x3));\n }\n if (orderof(arrayify2(domain)) < 0) thresholds.reverse();\n return createScaleThreshold(key, channels, { domain: thresholds, range: range3, reverse: reverse3, unknown });\n}\nfunction createScaleThreshold(key, channels, {\n domain = [0],\n // explicit thresholds in ascending order\n unknown,\n scheme: scheme28 = \"rdylbu\",\n interpolate,\n range: range3 = interpolate !== void 0 ? quantize_default(interpolate, domain.length + 1) : registry.get(key) === color2 ? ordinalRange(scheme28, domain.length + 1) : void 0,\n reverse: reverse3\n}) {\n domain = arrayify2(domain);\n const sign3 = orderof(domain);\n if (!isNaN(sign3) && !isOrdered(domain, sign3)) throw new Error(`the ${key} scale has a non-monotonic domain`);\n if (reverse3) range3 = reverse(range3);\n return {\n type: \"threshold\",\n scale: threshold(sign3 < 0 ? reverse(domain) : domain, range3 === void 0 ? [] : range3).unknown(unknown),\n domain,\n range: range3\n };\n}\nfunction isOrdered(domain, sign3) {\n for (let i = 1, n = domain.length, d = domain[0]; i < n; ++i) {\n const s2 = descending(d, d = domain[i]);\n if (s2 !== 0 && s2 !== sign3) return false;\n }\n return true;\n}\nfunction createScaleIdentity(key) {\n return { type: \"identity\", scale: hasNumericRange(registry.get(key)) ? identity5() : (d) => d };\n}\nfunction inferDomain(channels, f = finite2) {\n return channels.length ? [\n min2(channels, ({ value }) => value === void 0 ? value : min2(value, f)),\n max2(channels, ({ value }) => value === void 0 ? value : max2(value, f))\n ] : [0, 1];\n}\nfunction inferAutoDomain(key, channels) {\n const type2 = registry.get(key);\n return (type2 === radius || type2 === opacity || type2 === length3 ? inferZeroDomain : inferDomain)(channels);\n}\nfunction inferZeroDomain(channels) {\n return [0, channels.length ? max2(channels, ({ value }) => value === void 0 ? value : max2(value, finite2)) : 1];\n}\nfunction inferRadialRange(channels, domain) {\n const hint = channels.find(({ radius: radius2 }) => radius2 !== void 0);\n if (hint !== void 0) return [0, hint.radius];\n const h25 = quantile2(channels, 0.5, ({ value }) => value === void 0 ? NaN : quantile2(value, 0.25, positive));\n const range3 = domain.map((d) => 3 * Math.sqrt(d / h25));\n const k2 = 30 / max2(range3);\n return k2 < 1 ? range3.map((r) => r * k2) : range3;\n}\nfunction inferLengthRange(channels, domain) {\n const h50 = median2(channels, ({ value }) => value === void 0 ? NaN : median2(value, Math.abs));\n const range3 = domain.map((d) => 12 * d / h50);\n const k2 = 60 / max2(range3);\n return k2 < 1 ? range3.map((r) => r * k2) : range3;\n}\nfunction inferLogDomain(channels) {\n for (const { value } of channels) {\n if (value !== void 0) {\n for (let v2 of value) {\n if (v2 > 0) return inferDomain(channels, positive);\n if (v2 < 0) return inferDomain(channels, negative);\n }\n }\n }\n return [1, 10];\n}\nfunction inferQuantileDomain(channels) {\n const domain = [];\n for (const { value } of channels) {\n if (value === void 0) continue;\n for (const v2 of value) domain.push(v2);\n }\n return domain;\n}\nfunction interpolatePiecewise(interpolate) {\n return (i, j) => (t) => interpolate(i + t * (j - i));\n}\n\n// ../../node_modules/@observablehq/plot/src/warnings.js\nvar warnings = 0;\nvar lastMessage;\nfunction consumeWarnings() {\n const w = warnings;\n warnings = 0;\n lastMessage = void 0;\n return w;\n}\nfunction warn(message) {\n if (message === lastMessage) return;\n lastMessage = message;\n console.warn(message);\n ++warnings;\n}\n\n// ../../node_modules/@observablehq/plot/src/scales/diverging.js\nfunction createScaleD(key, scale3, transform3, channels, {\n type: type2,\n nice: nice3,\n clamp,\n domain = inferDomain(channels),\n unknown,\n pivot = 0,\n scheme: scheme28,\n range: range3,\n symmetric = true,\n interpolate = registry.get(key) === color2 ? scheme28 == null && range3 !== void 0 ? rgb_default : quantitativeScheme(scheme28 !== void 0 ? scheme28 : \"rdbu\") : number_default,\n reverse: reverse3\n}) {\n pivot = +pivot;\n domain = arrayify2(domain);\n let [min5, max4] = domain;\n if (domain.length > 2) warn(`Warning: the diverging ${key} scale domain contains extra elements.`);\n if (descending(min5, max4) < 0) [min5, max4] = [max4, min5], reverse3 = !reverse3;\n min5 = Math.min(min5, pivot);\n max4 = Math.max(max4, pivot);\n if (typeof interpolate !== \"function\") {\n interpolate = maybeInterpolator(interpolate);\n }\n if (range3 !== void 0) {\n interpolate = interpolate.length === 1 ? interpolatePiecewise(interpolate)(...range3) : piecewise(interpolate, range3);\n }\n if (reverse3) interpolate = flip(interpolate);\n if (symmetric) {\n const mid2 = transform3.apply(pivot);\n const mindelta = mid2 - transform3.apply(min5);\n const maxdelta = transform3.apply(max4) - mid2;\n if (mindelta < maxdelta) min5 = transform3.invert(mid2 - maxdelta);\n else if (mindelta > maxdelta) max4 = transform3.invert(mid2 + mindelta);\n }\n scale3.domain([min5, pivot, max4]).unknown(unknown).interpolator(interpolate);\n if (clamp) scale3.clamp(clamp);\n if (nice3) scale3.nice(nice3);\n return { type: type2, domain: [min5, max4], pivot, interpolate, scale: scale3 };\n}\nfunction createScaleDiverging(key, channels, options) {\n return createScaleD(key, diverging(), transformIdentity, channels, options);\n}\nfunction createScaleDivergingSqrt(key, channels, options) {\n return createScaleDivergingPow(key, channels, { ...options, exponent: 0.5 });\n}\nfunction createScaleDivergingPow(key, channels, { exponent = 1, ...options }) {\n return createScaleD(key, divergingPow().exponent(exponent = +exponent), transformPow2(exponent), channels, {\n ...options,\n type: \"diverging-pow\"\n });\n}\nfunction createScaleDivergingLog(key, channels, { base = 10, pivot = 1, domain = inferDomain(channels, pivot < 0 ? negative : positive), ...options }) {\n return createScaleD(key, divergingLog().base(base = +base), transformLog2, channels, {\n domain,\n pivot,\n ...options\n });\n}\nfunction createScaleDivergingSymlog(key, channels, { constant: constant2 = 1, ...options }) {\n return createScaleD(\n key,\n divergingSymlog().constant(constant2 = +constant2),\n transformSymlog2(constant2),\n channels,\n options\n );\n}\nvar transformIdentity = {\n apply(x3) {\n return x3;\n },\n invert(x3) {\n return x3;\n }\n};\nvar transformLog2 = {\n apply: Math.log,\n invert: Math.exp\n};\nvar transformSqrt2 = {\n apply(x3) {\n return Math.sign(x3) * Math.sqrt(Math.abs(x3));\n },\n invert(x3) {\n return Math.sign(x3) * (x3 * x3);\n }\n};\nfunction transformPow2(exponent) {\n return exponent === 0.5 ? transformSqrt2 : {\n apply(x3) {\n return Math.sign(x3) * Math.pow(Math.abs(x3), exponent);\n },\n invert(x3) {\n return Math.sign(x3) * Math.pow(Math.abs(x3), 1 / exponent);\n }\n };\n}\nfunction transformSymlog2(constant2) {\n return {\n apply(x3) {\n return Math.sign(x3) * Math.log1p(Math.abs(x3 / constant2));\n },\n invert(x3) {\n return Math.sign(x3) * Math.expm1(Math.abs(x3)) * constant2;\n }\n };\n}\n\n// ../../node_modules/@observablehq/plot/src/scales/temporal.js\nfunction createScaleT(key, scale3, channels, options) {\n return createScaleQ(key, scale3, channels, options);\n}\nfunction createScaleTime(key, channels, options) {\n return createScaleT(key, time2(), channels, options);\n}\nfunction createScaleUtc(key, channels, options) {\n return createScaleT(key, utcTime(), channels, options);\n}\n\n// ../../node_modules/@observablehq/plot/src/scales/ordinal.js\nvar ordinalImplicit = Symbol(\"ordinal\");\nfunction createScaleO(key, scale3, channels, { type: type2, interval: interval3, domain, range: range3, reverse: reverse3, hint }) {\n interval3 = maybeRangeInterval(interval3, type2);\n if (domain === void 0) domain = inferDomain2(channels, interval3, key);\n if (type2 === \"categorical\" || type2 === ordinalImplicit) type2 = \"ordinal\";\n if (reverse3) domain = reverse(domain);\n domain = scale3.domain(domain).domain();\n if (range3 !== void 0) {\n if (typeof range3 === \"function\") range3 = range3(domain);\n scale3.range(range3);\n }\n return { type: type2, domain, range: range3, scale: scale3, hint, interval: interval3 };\n}\nfunction createScaleOrdinal(key, channels, { type: type2, interval: interval3, domain, range: range3, scheme: scheme28, unknown, ...options }) {\n interval3 = maybeRangeInterval(interval3, type2);\n if (domain === void 0) domain = inferDomain2(channels, interval3, key);\n let hint;\n if (registry.get(key) === symbol) {\n hint = inferSymbolHint(channels);\n range3 = range3 === void 0 ? inferSymbolRange(hint) : map3(range3, maybeSymbol);\n } else if (registry.get(key) === color2) {\n if (range3 === void 0 && (type2 === \"ordinal\" || type2 === ordinalImplicit)) {\n range3 = maybeBooleanRange(domain, scheme28);\n if (range3 !== void 0) scheme28 = void 0;\n }\n if (scheme28 === void 0 && range3 === void 0) {\n scheme28 = type2 === \"ordinal\" ? \"turbo\" : \"observable10\";\n }\n if (scheme28 !== void 0) {\n if (range3 !== void 0) {\n const interpolate = quantitativeScheme(scheme28);\n const t03 = range3[0], d = range3[1] - range3[0];\n range3 = ({ length: n }) => quantize_default((t) => interpolate(t03 + d * t), n);\n } else {\n range3 = ordinalScheme(scheme28);\n }\n }\n }\n if (unknown === implicit) {\n throw new Error(`implicit unknown on ${key} scale is not supported`);\n }\n return createScaleO(key, ordinal().unknown(unknown), channels, { ...options, type: type2, domain, range: range3, hint });\n}\nfunction createScalePoint(key, channels, { align: align3 = 0.5, padding: padding2 = 0.5, ...options }) {\n return maybeRound(point().align(align3).padding(padding2), channels, options, key);\n}\nfunction createScaleBand(key, channels, {\n align: align3 = 0.5,\n padding: padding2 = 0.1,\n paddingInner = padding2,\n paddingOuter = key === \"fx\" || key === \"fy\" ? 0 : padding2,\n ...options\n}) {\n return maybeRound(\n band().align(align3).paddingInner(paddingInner).paddingOuter(paddingOuter),\n channels,\n options,\n key\n );\n}\nfunction maybeRound(scale3, channels, options, key) {\n let { round: round2 } = options;\n if (round2 !== void 0) scale3.round(round2 = !!round2);\n scale3 = createScaleO(key, scale3, channels, options);\n scale3.round = round2;\n return scale3;\n}\nfunction inferDomain2(channels, interval3, key) {\n const values2 = new InternSet();\n for (const { value, domain } of channels) {\n if (domain !== void 0) return domain();\n if (value === void 0) continue;\n for (const v2 of value) values2.add(v2);\n }\n if (interval3 !== void 0) {\n const [min5, max4] = extent(values2).map(interval3.floor, interval3);\n return interval3.range(min5, interval3.offset(max4));\n }\n if (values2.size > 1e4 && registry.get(key) === position) {\n throw new Error(`implicit ordinal domain of ${key} scale has more than 10,000 values`);\n }\n return sort(values2, ascendingDefined2);\n}\nfunction inferHint(channels, key) {\n let value;\n for (const { hint } of channels) {\n const candidate = hint?.[key];\n if (candidate === void 0) continue;\n if (value === void 0) value = candidate;\n else if (value !== candidate) return;\n }\n return value;\n}\nfunction inferSymbolHint(channels) {\n return {\n fill: inferHint(channels, \"fill\"),\n stroke: inferHint(channels, \"stroke\")\n };\n}\nfunction inferSymbolRange(hint) {\n return isNoneish(hint.fill) ? symbolsStroke : symbolsFill;\n}\n\n// ../../node_modules/@observablehq/plot/src/scales.js\nfunction createScales(channelsByScale, {\n label: globalLabel,\n inset: globalInset = 0,\n insetTop: globalInsetTop = globalInset,\n insetRight: globalInsetRight = globalInset,\n insetBottom: globalInsetBottom = globalInset,\n insetLeft: globalInsetLeft = globalInset,\n round: round2,\n nice: nice3,\n clamp,\n zero: zero3,\n align: align3,\n padding: padding2,\n projection: projection3,\n facet: { label: facetLabel2 = globalLabel } = {},\n ...options\n} = {}) {\n const scales2 = {};\n for (const [key, channels] of channelsByScale) {\n const scaleOptions = options[key];\n const scale3 = createScale(key, channels, {\n round: registry.get(key) === position ? round2 : void 0,\n // only for position\n nice: nice3,\n clamp,\n zero: zero3,\n align: align3,\n padding: padding2,\n projection: projection3,\n ...scaleOptions\n });\n if (scale3) {\n let {\n label: label2 = key === \"fx\" || key === \"fy\" ? facetLabel2 : globalLabel,\n percent,\n transform: transform3,\n inset: inset2,\n insetTop = inset2 !== void 0 ? inset2 : key === \"y\" ? globalInsetTop : 0,\n // not fy\n insetRight = inset2 !== void 0 ? inset2 : key === \"x\" ? globalInsetRight : 0,\n // not fx\n insetBottom = inset2 !== void 0 ? inset2 : key === \"y\" ? globalInsetBottom : 0,\n // not fy\n insetLeft = inset2 !== void 0 ? inset2 : key === \"x\" ? globalInsetLeft : 0\n // not fx\n } = scaleOptions || {};\n if (transform3 == null) transform3 = void 0;\n else if (typeof transform3 !== \"function\") throw new Error(\"invalid scale transform; not a function\");\n scale3.percent = !!percent;\n scale3.label = label2 === void 0 ? inferScaleLabel(channels, scale3) : label2;\n scale3.transform = transform3;\n if (key === \"x\" || key === \"fx\") {\n scale3.insetLeft = +insetLeft;\n scale3.insetRight = +insetRight;\n } else if (key === \"y\" || key === \"fy\") {\n scale3.insetTop = +insetTop;\n scale3.insetBottom = +insetBottom;\n }\n scales2[key] = scale3;\n }\n }\n return scales2;\n}\nfunction createScaleFunctions(descriptors) {\n const scales2 = {};\n const scaleFunctions = { scales: scales2 };\n for (const [key, descriptor] of Object.entries(descriptors)) {\n const { scale: scale3, type: type2, interval: interval3, label: label2 } = descriptor;\n scales2[key] = exposeScale(descriptor);\n scaleFunctions[key] = scale3;\n scale3.type = type2;\n if (interval3 != null) scale3.interval = interval3;\n if (label2 != null) scale3.label = label2;\n }\n return scaleFunctions;\n}\nfunction autoScaleRange(scales2, dimensions) {\n const { x: x3, y: y3, fx, fy } = scales2;\n const superdimensions = fx || fy ? outerDimensions(dimensions) : dimensions;\n if (fx) autoScaleRangeX(fx, superdimensions);\n if (fy) autoScaleRangeY(fy, superdimensions);\n const subdimensions = fx || fy ? innerDimensions(scales2, dimensions) : dimensions;\n if (x3) autoScaleRangeX(x3, subdimensions);\n if (y3) autoScaleRangeY(y3, subdimensions);\n}\nfunction inferScaleLabel(channels = [], scale3) {\n let label2;\n for (const { label: l } of channels) {\n if (l === void 0) continue;\n if (label2 === void 0) label2 = l;\n else if (label2 !== l) return;\n }\n if (label2 === void 0) return;\n if (!isOrdinalScale(scale3) && scale3.percent) label2 = `${label2} (%)`;\n return { inferred: true, toString: () => label2 };\n}\nfunction inferScaleOrder(scale3) {\n return Math.sign(orderof(scale3.domain())) * Math.sign(orderof(scale3.range()));\n}\nfunction outerDimensions(dimensions) {\n const {\n marginTop: marginTop2,\n marginRight: marginRight2,\n marginBottom: marginBottom2,\n marginLeft: marginLeft2,\n width: width2,\n height: height2,\n facet: {\n marginTop: facetMarginTop2,\n marginRight: facetMarginRight2,\n marginBottom: facetMarginBottom2,\n marginLeft: facetMarginLeft2\n }\n } = dimensions;\n return {\n marginTop: Math.max(marginTop2, facetMarginTop2),\n marginRight: Math.max(marginRight2, facetMarginRight2),\n marginBottom: Math.max(marginBottom2, facetMarginBottom2),\n marginLeft: Math.max(marginLeft2, facetMarginLeft2),\n width: width2,\n height: height2\n };\n}\nfunction innerDimensions({ fx, fy }, dimensions) {\n const { marginTop: marginTop2, marginRight: marginRight2, marginBottom: marginBottom2, marginLeft: marginLeft2, width: width2, height: height2 } = outerDimensions(dimensions);\n return {\n marginTop: marginTop2,\n marginRight: marginRight2,\n marginBottom: marginBottom2,\n marginLeft: marginLeft2,\n width: fx ? fx.scale.bandwidth() + marginLeft2 + marginRight2 : width2,\n height: fy ? fy.scale.bandwidth() + marginTop2 + marginBottom2 : height2,\n facet: { width: width2, height: height2 }\n };\n}\nfunction autoScaleRangeX(scale3, dimensions) {\n if (scale3.range === void 0) {\n const { insetLeft, insetRight } = scale3;\n const { width: width2, marginLeft: marginLeft2 = 0, marginRight: marginRight2 = 0 } = dimensions;\n const left2 = marginLeft2 + insetLeft;\n const right2 = width2 - marginRight2 - insetRight;\n scale3.range = [left2, Math.max(left2, right2)];\n if (!isOrdinalScale(scale3)) scale3.range = piecewiseRange(scale3);\n scale3.scale.range(scale3.range);\n }\n autoScaleRound(scale3);\n}\nfunction autoScaleRangeY(scale3, dimensions) {\n if (scale3.range === void 0) {\n const { insetTop, insetBottom } = scale3;\n const { height: height2, marginTop: marginTop2 = 0, marginBottom: marginBottom2 = 0 } = dimensions;\n const top2 = marginTop2 + insetTop;\n const bottom2 = height2 - marginBottom2 - insetBottom;\n scale3.range = [Math.max(top2, bottom2), top2];\n if (!isOrdinalScale(scale3)) scale3.range = piecewiseRange(scale3);\n else scale3.range.reverse();\n scale3.scale.range(scale3.range);\n }\n autoScaleRound(scale3);\n}\nfunction autoScaleRound(scale3) {\n if (scale3.round === void 0 && isBandScale(scale3) && roundError(scale3) <= 30) {\n scale3.scale.round(true);\n }\n}\nfunction roundError({ scale: scale3 }) {\n const n = scale3.domain().length;\n const [start2, stop] = scale3.range();\n const paddingInner = scale3.paddingInner ? scale3.paddingInner() : 1;\n const paddingOuter = scale3.paddingOuter ? scale3.paddingOuter() : scale3.padding();\n const m = n - paddingInner;\n const step = Math.abs(stop - start2) / Math.max(1, m + paddingOuter * 2);\n return (step - Math.floor(step)) * m;\n}\nfunction piecewiseRange(scale3) {\n const length4 = scale3.scale.domain().length + isThresholdScale(scale3);\n if (!(length4 > 2)) return scale3.range;\n const [start2, end] = scale3.range;\n return Array.from({ length: length4 }, (_, i) => start2 + i / (length4 - 1) * (end - start2));\n}\nfunction normalizeScale(key, scale3, hint) {\n return createScale(key, hint === void 0 ? void 0 : [{ hint }], { ...scale3 });\n}\nfunction createScale(key, channels = [], options = {}) {\n const type2 = inferScaleType(key, channels, options);\n if (options.type === void 0 && options.domain === void 0 && options.range === void 0 && options.interval == null && key !== \"fx\" && key !== \"fy\" && isOrdinalScale({ type: type2 })) {\n const values2 = channels.map(({ value }) => value).filter((value) => value !== void 0);\n if (values2.some(isTemporal))\n warn(\n `Warning: some data associated with the ${key} scale are dates. Dates are typically associated with a \"utc\" or \"time\" scale rather than a \"${formatScaleType(\n type2\n )}\" scale. If you are using a bar mark, you probably want a rect mark with the interval option instead; if you are using a group transform, you probably want a bin transform instead. If you want to treat this data as ordinal, you can specify the interval of the ${key} scale (e.g., d3.utcDay), or you can suppress this warning by setting the type of the ${key} scale to \"${formatScaleType(\n type2\n )}\".`\n );\n else if (values2.some(isTemporalString))\n warn(\n `Warning: some data associated with the ${key} scale are strings that appear to be dates (e.g., YYYY-MM-DD). If these strings represent dates, you should parse them to Date objects. Dates are typically associated with a \"utc\" or \"time\" scale rather than a \"${formatScaleType(\n type2\n )}\" scale. If you are using a bar mark, you probably want a rect mark with the interval option instead; if you are using a group transform, you probably want a bin transform instead. If you want to treat this data as ordinal, you can suppress this warning by setting the type of the ${key} scale to \"${formatScaleType(\n type2\n )}\".`\n );\n else if (values2.some(isNumericString))\n warn(\n `Warning: some data associated with the ${key} scale are strings that appear to be numbers. If these strings represent numbers, you should parse or coerce them to numbers. Numbers are typically associated with a \"linear\" scale rather than a \"${formatScaleType(\n type2\n )}\" scale. If you want to treat this data as ordinal, you can specify the interval of the ${key} scale (e.g., 1 for integers), or you can suppress this warning by setting the type of the ${key} scale to \"${formatScaleType(\n type2\n )}\".`\n );\n }\n options.type = type2;\n switch (type2) {\n case \"diverging\":\n case \"diverging-sqrt\":\n case \"diverging-pow\":\n case \"diverging-log\":\n case \"diverging-symlog\":\n case \"cyclical\":\n case \"sequential\":\n case \"linear\":\n case \"sqrt\":\n case \"threshold\":\n case \"quantile\":\n case \"pow\":\n case \"log\":\n case \"symlog\":\n options = coerceType(channels, options, coerceNumbers);\n break;\n case \"identity\":\n switch (registry.get(key)) {\n case position:\n options = coerceType(channels, options, coerceNumbers);\n break;\n case symbol:\n options = coerceType(channels, options, coerceSymbols);\n break;\n }\n break;\n case \"utc\":\n case \"time\":\n options = coerceType(channels, options, coerceDates);\n break;\n }\n switch (type2) {\n case \"diverging\":\n return createScaleDiverging(key, channels, options);\n case \"diverging-sqrt\":\n return createScaleDivergingSqrt(key, channels, options);\n case \"diverging-pow\":\n return createScaleDivergingPow(key, channels, options);\n case \"diverging-log\":\n return createScaleDivergingLog(key, channels, options);\n case \"diverging-symlog\":\n return createScaleDivergingSymlog(key, channels, options);\n case \"categorical\":\n case \"ordinal\":\n case ordinalImplicit:\n return createScaleOrdinal(key, channels, options);\n case \"cyclical\":\n case \"sequential\":\n case \"linear\":\n return createScaleLinear(key, channels, options);\n case \"sqrt\":\n return createScaleSqrt(key, channels, options);\n case \"threshold\":\n return createScaleThreshold(key, channels, options);\n case \"quantile\":\n return createScaleQuantile(key, channels, options);\n case \"quantize\":\n return createScaleQuantize(key, channels, options);\n case \"pow\":\n return createScalePow(key, channels, options);\n case \"log\":\n return createScaleLog(key, channels, options);\n case \"symlog\":\n return createScaleSymlog(key, channels, options);\n case \"utc\":\n return createScaleUtc(key, channels, options);\n case \"time\":\n return createScaleTime(key, channels, options);\n case \"point\":\n return createScalePoint(key, channels, options);\n case \"band\":\n return createScaleBand(key, channels, options);\n case \"identity\":\n return createScaleIdentity(key);\n case void 0:\n return;\n default:\n throw new Error(`unknown scale type: ${type2}`);\n }\n}\nfunction formatScaleType(type2) {\n return typeof type2 === \"symbol\" ? type2.description : type2;\n}\nfunction maybeScaleType(type2) {\n return typeof type2 === \"string\" ? `${type2}`.toLowerCase() : type2;\n}\nvar typeProjection = { toString: () => \"projection\" };\nfunction inferScaleType(key, channels, { type: type2, domain, range: range3, scheme: scheme28, pivot, projection: projection3 }) {\n type2 = maybeScaleType(type2);\n if (key === \"fx\" || key === \"fy\") return \"band\";\n if ((key === \"x\" || key === \"y\") && projection3 != null) type2 = typeProjection;\n for (const channel of channels) {\n const t = maybeScaleType(channel.type);\n if (t === void 0) continue;\n else if (type2 === void 0) type2 = t;\n else if (type2 !== t) throw new Error(`scale incompatible with channel: ${type2} !== ${t}`);\n }\n if (type2 === typeProjection) return;\n if (type2 !== void 0) return type2;\n if (domain === void 0 && !channels.some(({ value }) => value !== void 0)) return;\n const kind = registry.get(key);\n if (kind === radius) return \"sqrt\";\n if (kind === opacity || kind === length3) return \"linear\";\n if (kind === symbol) return \"ordinal\";\n if ((domain || range3 || []).length > 2) return asOrdinalType(kind);\n if (domain !== void 0) {\n if (isOrdinal(domain)) return asOrdinalType(kind);\n if (isTemporal(domain)) return \"utc\";\n } else {\n const values2 = channels.map(({ value }) => value).filter((value) => value !== void 0);\n if (values2.some(isOrdinal)) return asOrdinalType(kind);\n if (values2.some(isTemporal)) return \"utc\";\n }\n if (kind === color2) {\n if (pivot != null || isDivergingScheme(scheme28)) return \"diverging\";\n if (isCategoricalScheme(scheme28)) return \"categorical\";\n }\n return \"linear\";\n}\nfunction asOrdinalType(kind) {\n switch (kind) {\n case position:\n return \"point\";\n case color2:\n return ordinalImplicit;\n default:\n return \"ordinal\";\n }\n}\nfunction isOrdinalScale({ type: type2 }) {\n return type2 === \"ordinal\" || type2 === \"point\" || type2 === \"band\" || type2 === ordinalImplicit;\n}\nfunction isThresholdScale({ type: type2 }) {\n return type2 === \"threshold\";\n}\nfunction isBandScale({ type: type2 }) {\n return type2 === \"point\" || type2 === \"band\";\n}\nfunction isCollapsed(scale3) {\n if (scale3 === void 0) return true;\n const domain = scale3.domain();\n const value = scale3(domain[0]);\n for (let i = 1, n = domain.length; i < n; ++i) {\n if (scale3(domain[i]) - value) {\n return false;\n }\n }\n return true;\n}\nfunction coerceType(channels, { domain, ...options }, coerceValues) {\n for (const c4 of channels) {\n if (c4.value !== void 0) {\n if (domain === void 0) domain = c4.value?.domain;\n c4.value = coerceValues(c4.value);\n }\n }\n return {\n domain: domain === void 0 ? domain : coerceValues(domain),\n ...options\n };\n}\nfunction coerceSymbols(values2) {\n return map3(values2, maybeSymbol);\n}\nfunction scale2(options = {}) {\n let scale3;\n for (const key in options) {\n if (!registry.has(key)) continue;\n if (!isScaleOptions(options[key])) continue;\n if (scale3 !== void 0) throw new Error(\"ambiguous scale definition; multiple scales found\");\n scale3 = exposeScale(normalizeScale(key, options[key]));\n }\n if (scale3 === void 0) throw new Error(\"invalid scale definition; no scale found\");\n return scale3;\n}\nfunction exposeScales(scales2) {\n return (key) => {\n if (!registry.has(key = `${key}`)) throw new Error(`unknown scale: ${key}`);\n return scales2[key];\n };\n}\nfunction exposeScale({ scale: scale3, type: type2, domain, range: range3, interpolate, interval: interval3, transform: transform3, percent, pivot }) {\n if (type2 === \"identity\") return { type: \"identity\", apply: (d) => d, invert: (d) => d };\n const unknown = scale3.unknown ? scale3.unknown() : void 0;\n return {\n type: type2,\n domain: slice3(domain),\n // defensive copy\n ...range3 !== void 0 && { range: slice3(range3) },\n // defensive copy\n ...transform3 !== void 0 && { transform: transform3 },\n ...percent && { percent },\n // only exposed if truthy\n ...unknown !== void 0 && { unknown },\n ...interval3 !== void 0 && { interval: interval3 },\n // quantitative\n ...interpolate !== void 0 && { interpolate },\n ...scale3.clamp && { clamp: scale3.clamp() },\n // diverging (always asymmetric; we never want to apply the symmetric transform twice)\n ...pivot !== void 0 && { pivot, symmetric: false },\n // log, diverging-log\n ...scale3.base && { base: scale3.base() },\n // pow, diverging-pow\n ...scale3.exponent && { exponent: scale3.exponent() },\n // symlog, diverging-symlog\n ...scale3.constant && { constant: scale3.constant() },\n // band, point\n ...scale3.align && { align: scale3.align(), round: scale3.round() },\n ...scale3.padding && (scale3.paddingInner ? { paddingInner: scale3.paddingInner(), paddingOuter: scale3.paddingOuter() } : { padding: scale3.padding() }),\n ...scale3.bandwidth && { bandwidth: scale3.bandwidth(), step: scale3.step() },\n // utilities\n apply: (t) => scale3(t),\n ...scale3.invert && { invert: (t) => scale3.invert(t) }\n };\n}\n\n// ../../node_modules/@observablehq/plot/src/facet.js\nfunction createFacets(channelsByScale, options) {\n const { fx, fy } = createScales(channelsByScale, options);\n const fxDomain2 = fx?.scale.domain();\n const fyDomain2 = fy?.scale.domain();\n return fxDomain2 && fyDomain2 ? cross(fxDomain2, fyDomain2).map(([x3, y3], i) => ({ x: x3, y: y3, i })) : fxDomain2 ? fxDomain2.map((x3, i) => ({ x: x3, i })) : fyDomain2 ? fyDomain2.map((y3, i) => ({ y: y3, i })) : void 0;\n}\nfunction recreateFacets(facets, { x: X3, y: Y3 }) {\n X3 &&= facetIndex(X3);\n Y3 &&= facetIndex(Y3);\n return facets.filter(\n X3 && Y3 ? (f) => X3.has(f.x) && Y3.has(f.y) : X3 ? (f) => X3.has(f.x) : (f) => Y3.has(f.y)\n ).sort(\n X3 && Y3 ? (a2, b) => X3.get(a2.x) - X3.get(b.x) || Y3.get(a2.y) - Y3.get(b.y) : X3 ? (a2, b) => X3.get(a2.x) - X3.get(b.x) : (a2, b) => Y3.get(a2.y) - Y3.get(b.y)\n );\n}\nfunction facetGroups(data, { fx, fy }) {\n const I = range2(data);\n const FX = fx?.value;\n const FY = fy?.value;\n return fx && fy ? rollup(\n I,\n (G) => (G.fx = FX[G[0]], G.fy = FY[G[0]], G),\n (i) => FX[i],\n (i) => FY[i]\n ) : fx ? rollup(\n I,\n (G) => (G.fx = FX[G[0]], G),\n (i) => FX[i]\n ) : rollup(\n I,\n (G) => (G.fy = FY[G[0]], G),\n (i) => FY[i]\n );\n}\nfunction facetTranslator(fx, fy, { marginTop: marginTop2, marginLeft: marginLeft2 }) {\n return fx && fy ? ({ x: x3, y: y3 }) => `translate(${fx(x3) - marginLeft2},${fy(y3) - marginTop2})` : fx ? ({ x: x3 }) => `translate(${fx(x3) - marginLeft2},0)` : ({ y: y3 }) => `translate(0,${fy(y3) - marginTop2})`;\n}\nfunction facetExclude(index2) {\n const ex = [];\n const e = new Uint32Array(sum2(index2, (d) => d.length));\n for (const i of index2) {\n let n = 0;\n for (const j of index2) {\n if (i === j) continue;\n e.set(j, n);\n n += j.length;\n }\n ex.push(e.slice(0, n));\n }\n return ex;\n}\nvar facetAnchors = /* @__PURE__ */ new Map([\n [\"top\", facetAnchorTop],\n [\"right\", facetAnchorRight],\n [\"bottom\", facetAnchorBottom],\n [\"left\", facetAnchorLeft],\n [\"top-left\", and2(facetAnchorTop, facetAnchorLeft)],\n [\"top-right\", and2(facetAnchorTop, facetAnchorRight)],\n [\"bottom-left\", and2(facetAnchorBottom, facetAnchorLeft)],\n [\"bottom-right\", and2(facetAnchorBottom, facetAnchorRight)],\n [\"top-empty\", facetAnchorTopEmpty],\n [\"right-empty\", facetAnchorRightEmpty],\n [\"bottom-empty\", facetAnchorBottomEmpty],\n [\"left-empty\", facetAnchorLeftEmpty],\n [\"empty\", facetAnchorEmpty]\n]);\nfunction maybeFacetAnchor(facetAnchor) {\n if (facetAnchor == null) return null;\n const anchor = facetAnchors.get(`${facetAnchor}`.toLowerCase());\n if (anchor) return anchor;\n throw new Error(`invalid facet anchor: ${facetAnchor}`);\n}\nvar indexCache = /* @__PURE__ */ new WeakMap();\nfunction facetIndex(V) {\n let I = indexCache.get(V);\n if (!I) indexCache.set(V, I = new InternMap(map3(V, (v2, i) => [v2, i])));\n return I;\n}\nfunction facetIndexOf(V, v2) {\n return facetIndex(V).get(v2);\n}\nfunction facetFind(facets, x3, y3) {\n x3 = keyof2(x3);\n y3 = keyof2(y3);\n return facets.find((f) => Object.is(keyof2(f.x), x3) && Object.is(keyof2(f.y), y3));\n}\nfunction facetEmpty(facets, x3, y3) {\n return facetFind(facets, x3, y3)?.empty;\n}\nfunction facetAnchorTop(facets, { y: Y3 }, { y: y3 }) {\n return Y3 ? facetIndexOf(Y3, y3) === 0 : true;\n}\nfunction facetAnchorBottom(facets, { y: Y3 }, { y: y3 }) {\n return Y3 ? facetIndexOf(Y3, y3) === Y3.length - 1 : true;\n}\nfunction facetAnchorLeft(facets, { x: X3 }, { x: x3 }) {\n return X3 ? facetIndexOf(X3, x3) === 0 : true;\n}\nfunction facetAnchorRight(facets, { x: X3 }, { x: x3 }) {\n return X3 ? facetIndexOf(X3, x3) === X3.length - 1 : true;\n}\nfunction facetAnchorTopEmpty(facets, { y: Y3 }, { x: x3, y: y3, empty: empty4 }) {\n if (empty4) return false;\n if (!Y3) return;\n const i = facetIndexOf(Y3, y3);\n if (i > 0) return facetEmpty(facets, x3, Y3[i - 1]);\n}\nfunction facetAnchorBottomEmpty(facets, { y: Y3 }, { x: x3, y: y3, empty: empty4 }) {\n if (empty4) return false;\n if (!Y3) return;\n const i = facetIndexOf(Y3, y3);\n if (i < Y3.length - 1) return facetEmpty(facets, x3, Y3[i + 1]);\n}\nfunction facetAnchorLeftEmpty(facets, { x: X3 }, { x: x3, y: y3, empty: empty4 }) {\n if (empty4) return false;\n if (!X3) return;\n const i = facetIndexOf(X3, x3);\n if (i > 0) return facetEmpty(facets, X3[i - 1], y3);\n}\nfunction facetAnchorRightEmpty(facets, { x: X3 }, { x: x3, y: y3, empty: empty4 }) {\n if (empty4) return false;\n if (!X3) return;\n const i = facetIndexOf(X3, x3);\n if (i < X3.length - 1) return facetEmpty(facets, X3[i + 1], y3);\n}\nfunction facetAnchorEmpty(facets, channels, { empty: empty4 }) {\n return empty4;\n}\nfunction and2(a2, b) {\n return function() {\n return a2.apply(null, arguments) && b.apply(null, arguments);\n };\n}\nfunction facetFilter(facets, { channels: { fx, fy }, groups: groups2 }) {\n return fx && fy ? facets.map(({ x: x3, y: y3 }) => groups2.get(x3)?.get(y3) ?? []) : fx ? facets.map(({ x: x3 }) => groups2.get(x3) ?? []) : facets.map(({ y: y3 }) => groups2.get(y3) ?? []);\n}\n\n// ../../node_modules/@observablehq/plot/src/projection.js\nvar pi4 = Math.PI;\nvar tau5 = 2 * pi4;\nvar defaultAspectRatio = 0.618;\nfunction createProjection({\n projection: projection3,\n inset: globalInset = 0,\n insetTop = globalInset,\n insetRight = globalInset,\n insetBottom = globalInset,\n insetLeft = globalInset\n} = {}, dimensions) {\n if (projection3 == null) return;\n if (typeof projection3.stream === \"function\") return projection3;\n let options;\n let domain;\n let clip = \"frame\";\n if (isObject(projection3)) {\n let inset2;\n ({\n type: projection3,\n domain,\n inset: inset2,\n insetTop = inset2 !== void 0 ? inset2 : insetTop,\n insetRight = inset2 !== void 0 ? inset2 : insetRight,\n insetBottom = inset2 !== void 0 ? inset2 : insetBottom,\n insetLeft = inset2 !== void 0 ? inset2 : insetLeft,\n clip = clip,\n ...options\n } = projection3);\n if (projection3 == null) return;\n }\n if (typeof projection3 !== \"function\") ({ type: projection3 } = namedProjection(projection3));\n const { width: width2, height: height2, marginLeft: marginLeft2, marginRight: marginRight2, marginTop: marginTop2, marginBottom: marginBottom2 } = dimensions;\n const dx = width2 - marginLeft2 - marginRight2 - insetLeft - insetRight;\n const dy = height2 - marginTop2 - marginBottom2 - insetTop - insetBottom;\n projection3 = projection3?.({ width: dx, height: dy, clip, ...options });\n if (projection3 == null) return;\n clip = maybePostClip(clip, marginLeft2, marginTop2, width2 - marginRight2, height2 - marginBottom2);\n let tx = marginLeft2 + insetLeft;\n let ty = marginTop2 + insetTop;\n let transform3;\n if (domain != null) {\n const [[x06, y06], [x12, y12]] = path_default(projection3).bounds(domain);\n const k2 = Math.min(dx / (x12 - x06), dy / (y12 - y06));\n if (k2 > 0) {\n tx -= (k2 * (x06 + x12) - dx) / 2;\n ty -= (k2 * (y06 + y12) - dy) / 2;\n transform3 = transform_default({\n point(x3, y3) {\n this.stream.point(x3 * k2 + tx, y3 * k2 + ty);\n }\n });\n } else {\n warn(`Warning: the projection could not be fit to the specified domain; using the default scale.`);\n }\n }\n transform3 ??= tx === 0 && ty === 0 ? identity8() : transform_default({\n point(x3, y3) {\n this.stream.point(x3 + tx, y3 + ty);\n }\n });\n return { stream: (s2) => projection3.stream(transform3.stream(clip(s2))) };\n}\nfunction namedProjection(projection3) {\n switch (`${projection3}`.toLowerCase()) {\n case \"albers-usa\":\n return scaleProjection(albersUsa_default, 0.7463, 0.4673);\n case \"albers\":\n return conicProjection2(albers_default, 0.7463, 0.4673);\n case \"azimuthal-equal-area\":\n return scaleProjection(azimuthalEqualArea_default, 4, 4);\n case \"azimuthal-equidistant\":\n return scaleProjection(azimuthalEquidistant_default, tau5, tau5);\n case \"conic-conformal\":\n return conicProjection2(conicConformal_default, tau5, tau5);\n case \"conic-equal-area\":\n return conicProjection2(conicEqualArea_default, 6.1702, 2.9781);\n case \"conic-equidistant\":\n return conicProjection2(conicEquidistant_default, 7.312, 3.6282);\n case \"equal-earth\":\n return scaleProjection(equalEarth_default, 5.4133, 2.6347);\n case \"equirectangular\":\n return scaleProjection(equirectangular_default, tau5, pi4);\n case \"gnomonic\":\n return scaleProjection(gnomonic_default, 3.4641, 3.4641);\n case \"identity\":\n return { type: identity8 };\n case \"reflect-y\":\n return { type: reflectY };\n case \"mercator\":\n return scaleProjection(mercator_default, tau5, tau5);\n case \"orthographic\":\n return scaleProjection(orthographic_default, 2, 2);\n case \"stereographic\":\n return scaleProjection(stereographic_default, 2, 2);\n case \"transverse-mercator\":\n return scaleProjection(transverseMercator_default, tau5, tau5);\n default:\n throw new Error(`unknown projection type: ${projection3}`);\n }\n}\nfunction maybePostClip(clip, x12, y12, x22, y22) {\n if (clip === false || clip == null || typeof clip === \"number\") return (s2) => s2;\n if (clip === true) clip = \"frame\";\n switch (`${clip}`.toLowerCase()) {\n case \"frame\":\n return clipRectangle(x12, y12, x22, y22);\n default:\n throw new Error(`unknown projection clip type: ${clip}`);\n }\n}\nfunction scaleProjection(createProjection2, kx2, ky2) {\n return {\n type: ({ width: width2, height: height2, rotate, precision = 0.15, clip }) => {\n const projection3 = createProjection2();\n if (precision != null) projection3.precision?.(precision);\n if (rotate != null) projection3.rotate?.(rotate);\n if (typeof clip === \"number\") projection3.clipAngle?.(clip);\n if (width2 != null) {\n projection3.scale(Math.min(width2 / kx2, height2 / ky2));\n projection3.translate([width2 / 2, height2 / 2]);\n }\n return projection3;\n },\n aspectRatio: ky2 / kx2\n };\n}\nfunction conicProjection2(createProjection2, kx2, ky2) {\n const { type: type2, aspectRatio: aspectRatio2 } = scaleProjection(createProjection2, kx2, ky2);\n return {\n type: (options) => {\n const { parallels, domain, width: width2, height: height2 } = options;\n const projection3 = type2(options);\n if (parallels != null) {\n projection3.parallels(parallels);\n if (domain === void 0 && width2 != null) {\n projection3.fitSize([width2, height2], { type: \"Sphere\" });\n }\n }\n return projection3;\n },\n aspectRatio: aspectRatio2\n };\n}\nvar identity8 = constant({ stream: (stream) => stream });\nvar reflectY = constant(\n transform_default({\n point(x3, y3) {\n this.stream.point(x3, -y3);\n }\n })\n);\nfunction project(cx, cy, values2, projection3) {\n const x3 = values2[cx];\n const y3 = values2[cy];\n const n = x3.length;\n const X3 = values2[cx] = new Float64Array(n).fill(NaN);\n const Y3 = values2[cy] = new Float64Array(n).fill(NaN);\n let i;\n const stream = projection3.stream({\n point(x4, y4) {\n X3[i] = x4;\n Y3[i] = y4;\n }\n });\n for (i = 0; i < n; ++i) {\n stream.point(x3[i], y3[i]);\n }\n}\nfunction hasProjection({ projection: projection3 } = {}) {\n if (projection3 == null) return false;\n if (typeof projection3.stream === \"function\") return true;\n if (isObject(projection3)) projection3 = projection3.type;\n return projection3 != null;\n}\nfunction projectionAspectRatio(projection3) {\n if (typeof projection3?.stream === \"function\") return defaultAspectRatio;\n if (isObject(projection3)) {\n let domain, options;\n ({ domain, type: projection3, ...options } = projection3);\n if (domain != null && projection3 != null) {\n const type2 = typeof projection3 === \"string\" ? namedProjection(projection3).type : projection3;\n const [[x06, y06], [x12, y12]] = path_default(type2({ ...options, width: 100, height: 100 })).bounds(domain);\n const r = (y12 - y06) / (x12 - x06);\n return r && isFinite(r) ? r < 0.2 ? 0.2 : r > 5 ? 5 : r : defaultAspectRatio;\n }\n }\n if (projection3 == null) return;\n if (typeof projection3 !== \"function\") {\n const { aspectRatio: aspectRatio2 } = namedProjection(projection3);\n if (aspectRatio2) return aspectRatio2;\n }\n return defaultAspectRatio;\n}\nfunction applyPosition(channels, scales2, { projection: projection3 }) {\n const { x: x3, y: y3 } = channels;\n let position3 = {};\n if (x3) position3.x = x3;\n if (y3) position3.y = y3;\n position3 = valueObject(position3, scales2);\n if (projection3 && x3?.scale === \"x\" && y3?.scale === \"y\") project(\"x\", \"y\", position3, projection3);\n if (x3) position3.x = coerceNumbers(position3.x);\n if (y3) position3.y = coerceNumbers(position3.y);\n return position3;\n}\nfunction getGeometryChannels(channel) {\n const X3 = [];\n const Y3 = [];\n const x3 = { scale: \"x\", value: X3 };\n const y3 = { scale: \"y\", value: Y3 };\n const sink = {\n point(x4, y4) {\n X3.push(x4);\n Y3.push(y4);\n },\n lineStart() {\n },\n lineEnd() {\n },\n polygonStart() {\n },\n polygonEnd() {\n },\n sphere() {\n }\n };\n for (const object of channel.value) stream_default(object, sink);\n return [x3, y3];\n}\n\n// ../../node_modules/@observablehq/plot/src/context.js\nfunction createContext(options = {}) {\n const { document: document2 = typeof window !== \"undefined\" ? window.document : void 0, clip } = options;\n return { document: document2, clip: maybeClip(clip) };\n}\nfunction create4(name2, { document: document2 }) {\n return select_default2(creator_default(name2).call(document2.documentElement));\n}\n\n// ../../node_modules/@observablehq/plot/src/memoize.js\nvar unset = Symbol(\"unset\");\nfunction memoize1(compute) {\n return (compute.length === 1 ? memoize1Arg : memoize1Args)(compute);\n}\nfunction memoize1Arg(compute) {\n let cacheValue;\n let cacheKey = unset;\n return (key) => {\n if (!Object.is(cacheKey, key)) {\n cacheKey = key;\n cacheValue = compute(key);\n }\n return cacheValue;\n };\n}\nfunction memoize1Args(compute) {\n let cacheValue, cacheKeys;\n return (...keys) => {\n if (cacheKeys?.length !== keys.length || cacheKeys.some((k2, i) => !Object.is(k2, keys[i]))) {\n cacheKeys = keys;\n cacheValue = compute(...keys);\n }\n return cacheValue;\n };\n}\n\n// ../../node_modules/@observablehq/plot/src/format.js\nvar numberFormat = memoize1((locale3) => {\n return new Intl.NumberFormat(locale3);\n});\nvar monthFormat = memoize1((locale3, month) => {\n return new Intl.DateTimeFormat(locale3, { timeZone: \"UTC\", ...month && { month } });\n});\nvar weekdayFormat = memoize1((locale3, weekday) => {\n return new Intl.DateTimeFormat(locale3, { timeZone: \"UTC\", ...weekday && { weekday } });\n});\nfunction formatNumber(locale3 = \"en-US\") {\n const format3 = numberFormat(locale3);\n return (i) => i != null && !isNaN(i) ? format3.format(i) : void 0;\n}\nfunction formatMonth(locale3 = \"en-US\", format3 = \"short\") {\n const fmt = monthFormat(locale3, format3);\n return (i) => i != null && !isNaN(i = +new Date(Date.UTC(2e3, +i))) ? fmt.format(i) : void 0;\n}\nfunction formatWeekday(locale3 = \"en-US\", format3 = \"short\") {\n const fmt = weekdayFormat(locale3, format3);\n return (i) => i != null && !isNaN(i = +new Date(Date.UTC(2001, 0, +i))) ? fmt.format(i) : void 0;\n}\nfunction formatIsoDate(date3) {\n return format2(date3, \"Invalid Date\");\n}\nfunction formatAuto(locale3 = \"en-US\") {\n const number7 = formatNumber(locale3);\n return (v2) => (v2 instanceof Date ? formatIsoDate : typeof v2 === \"number\" ? number7 : string)(v2);\n}\nvar formatDefault = formatAuto();\n\n// ../../node_modules/@observablehq/plot/src/style.js\nvar offset = (typeof window !== \"undefined\" ? window.devicePixelRatio > 1 : typeof it === \"undefined\") ? 0 : 0.5;\nvar nextClipId = 0;\nvar nextPatternId = 0;\nfunction getClipId() {\n return `plot-clip-${++nextClipId}`;\n}\nfunction getPatternId() {\n return `plot-pattern-${++nextPatternId}`;\n}\nfunction styles(mark2, {\n title,\n href,\n ariaLabel: variaLabel,\n ariaDescription,\n ariaHidden,\n target,\n fill,\n fillOpacity,\n stroke,\n strokeWidth,\n strokeOpacity,\n strokeLinejoin,\n strokeLinecap,\n strokeMiterlimit,\n strokeDasharray,\n strokeDashoffset,\n opacity: opacity2,\n mixBlendMode,\n imageFilter,\n paintOrder,\n pointerEvents,\n shapeRendering,\n channels\n}, {\n ariaLabel: cariaLabel,\n fill: defaultFill = \"currentColor\",\n fillOpacity: defaultFillOpacity,\n stroke: defaultStroke = \"none\",\n strokeOpacity: defaultStrokeOpacity,\n strokeWidth: defaultStrokeWidth,\n strokeLinecap: defaultStrokeLinecap,\n strokeLinejoin: defaultStrokeLinejoin,\n strokeMiterlimit: defaultStrokeMiterlimit,\n paintOrder: defaultPaintOrder\n}) {\n if (defaultFill === null) {\n fill = null;\n fillOpacity = null;\n }\n if (defaultStroke === null) {\n stroke = null;\n strokeOpacity = null;\n }\n if (isNoneish(defaultFill)) {\n if (!isNoneish(defaultStroke) && (!isNoneish(fill) || channels?.fill)) defaultStroke = \"none\";\n } else {\n if (isNoneish(defaultStroke) && (!isNoneish(stroke) || channels?.stroke)) defaultFill = \"none\";\n }\n const [vfill, cfill] = maybeColorChannel(fill, defaultFill);\n const [vfillOpacity, cfillOpacity] = maybeNumberChannel(fillOpacity, defaultFillOpacity);\n const [vstroke, cstroke] = maybeColorChannel(stroke, defaultStroke);\n const [vstrokeOpacity, cstrokeOpacity] = maybeNumberChannel(strokeOpacity, defaultStrokeOpacity);\n const [vopacity, copacity] = maybeNumberChannel(opacity2);\n if (!isNone(cstroke)) {\n if (strokeWidth === void 0) strokeWidth = defaultStrokeWidth;\n if (strokeLinecap === void 0) strokeLinecap = defaultStrokeLinecap;\n if (strokeLinejoin === void 0) strokeLinejoin = defaultStrokeLinejoin;\n if (strokeMiterlimit === void 0 && !isRound(strokeLinejoin)) strokeMiterlimit = defaultStrokeMiterlimit;\n if (!isNone(cfill) && paintOrder === void 0) paintOrder = defaultPaintOrder;\n }\n const [vstrokeWidth, cstrokeWidth] = maybeNumberChannel(strokeWidth);\n if (defaultFill !== null) {\n mark2.fill = impliedString(cfill, \"currentColor\");\n mark2.fillOpacity = impliedNumber(cfillOpacity, 1);\n }\n if (defaultStroke !== null) {\n mark2.stroke = impliedString(cstroke, \"none\");\n mark2.strokeWidth = impliedNumber(cstrokeWidth, 1);\n mark2.strokeOpacity = impliedNumber(cstrokeOpacity, 1);\n mark2.strokeLinejoin = impliedString(strokeLinejoin, \"miter\");\n mark2.strokeLinecap = impliedString(strokeLinecap, \"butt\");\n mark2.strokeMiterlimit = impliedNumber(strokeMiterlimit, 4);\n mark2.strokeDasharray = impliedString(strokeDasharray, \"none\");\n mark2.strokeDashoffset = impliedString(strokeDashoffset, \"0\");\n }\n mark2.target = string(target);\n mark2.ariaLabel = string(cariaLabel);\n mark2.ariaDescription = string(ariaDescription);\n mark2.ariaHidden = string(ariaHidden);\n mark2.opacity = impliedNumber(copacity, 1);\n mark2.mixBlendMode = impliedString(mixBlendMode, \"normal\");\n mark2.imageFilter = impliedString(imageFilter, \"none\");\n mark2.paintOrder = impliedString(paintOrder, \"normal\");\n mark2.pointerEvents = impliedString(pointerEvents, \"auto\");\n mark2.shapeRendering = impliedString(shapeRendering, \"auto\");\n return {\n title: { value: title, optional: true, filter: null },\n href: { value: href, optional: true, filter: null },\n ariaLabel: { value: variaLabel, optional: true, filter: null },\n fill: { value: vfill, scale: \"auto\", optional: true },\n fillOpacity: { value: vfillOpacity, scale: \"auto\", optional: true },\n stroke: { value: vstroke, scale: \"auto\", optional: true },\n strokeOpacity: { value: vstrokeOpacity, scale: \"auto\", optional: true },\n strokeWidth: { value: vstrokeWidth, optional: true },\n opacity: { value: vopacity, scale: \"auto\", optional: true }\n };\n}\nfunction applyTitle(selection2, L) {\n if (L)\n selection2.filter((i) => nonempty(L[i])).append(\"title\").call(applyText, L);\n}\nfunction applyTitleGroup(selection2, L) {\n if (L)\n selection2.filter(([i]) => nonempty(L[i])).append(\"title\").call(applyTextGroup, L);\n}\nfunction applyText(selection2, T) {\n if (T) selection2.text((i) => formatDefault(T[i]));\n}\nfunction applyTextGroup(selection2, T) {\n if (T) selection2.text(([i]) => formatDefault(T[i]));\n}\nfunction applyChannelStyles(selection2, { target, tip: tip2 }, {\n ariaLabel: AL,\n title: T,\n fill: F,\n fillOpacity: FO,\n stroke: S,\n strokeOpacity: SO,\n strokeWidth: SW,\n opacity: O,\n href: H\n}) {\n if (AL) applyAttr(selection2, \"aria-label\", (i) => AL[i]);\n if (F) applyAttr(selection2, \"fill\", (i) => F[i]);\n if (FO) applyAttr(selection2, \"fill-opacity\", (i) => FO[i]);\n if (S) applyAttr(selection2, \"stroke\", (i) => S[i]);\n if (SO) applyAttr(selection2, \"stroke-opacity\", (i) => SO[i]);\n if (SW) applyAttr(selection2, \"stroke-width\", (i) => SW[i]);\n if (O) applyAttr(selection2, \"opacity\", (i) => O[i]);\n if (H) applyHref(selection2, (i) => H[i], target);\n if (!tip2) applyTitle(selection2, T);\n}\nfunction applyGroupedChannelStyles(selection2, { target, tip: tip2 }, {\n ariaLabel: AL,\n title: T,\n fill: F,\n fillOpacity: FO,\n stroke: S,\n strokeOpacity: SO,\n strokeWidth: SW,\n opacity: O,\n href: H\n}) {\n if (AL) applyAttr(selection2, \"aria-label\", ([i]) => AL[i]);\n if (F) applyAttr(selection2, \"fill\", ([i]) => F[i]);\n if (FO) applyAttr(selection2, \"fill-opacity\", ([i]) => FO[i]);\n if (S) applyAttr(selection2, \"stroke\", ([i]) => S[i]);\n if (SO) applyAttr(selection2, \"stroke-opacity\", ([i]) => SO[i]);\n if (SW) applyAttr(selection2, \"stroke-width\", ([i]) => SW[i]);\n if (O) applyAttr(selection2, \"opacity\", ([i]) => O[i]);\n if (H) applyHref(selection2, ([i]) => H[i], target);\n if (!tip2) applyTitleGroup(selection2, T);\n}\nfunction groupAesthetics({\n ariaLabel: AL,\n title: T,\n fill: F,\n fillOpacity: FO,\n stroke: S,\n strokeOpacity: SO,\n strokeWidth: SW,\n opacity: O,\n href: H\n}, { tip: tip2 }) {\n return [AL, tip2 ? void 0 : T, F, FO, S, SO, SW, O, H].filter((c4) => c4 !== void 0);\n}\nfunction groupZ2(I, Z, z) {\n const G = group(I, (i) => Z[i]);\n if (z === void 0 && G.size > 1 + I.length >> 1) {\n warn(\n `Warning: the implicit z channel has high cardinality. This may occur when the fill or stroke channel is associated with quantitative data rather than ordinal or categorical data. You can suppress this warning by setting the z option explicitly; if this data represents a single series, set z to null.`\n );\n }\n return G.values();\n}\nfunction* groupIndex(I, position3, mark2, channels) {\n const { z } = mark2;\n const { z: Z } = channels;\n const A5 = groupAesthetics(channels, mark2);\n const C3 = [...position3, ...A5];\n for (const G of Z ? groupZ2(I, Z, z) : [I]) {\n let Ag;\n let Gg;\n out: for (const i of G) {\n for (const c4 of C3) {\n if (!defined(c4[i])) {\n if (Gg) Gg.push(-1);\n continue out;\n }\n }\n if (Ag === void 0) {\n if (Gg) yield Gg;\n Ag = A5.map((c4) => keyof2(c4[i])), Gg = [i];\n continue;\n }\n Gg.push(i);\n for (let j = 0; j < A5.length; ++j) {\n const k2 = keyof2(A5[j][i]);\n if (k2 !== Ag[j]) {\n yield Gg;\n Ag = A5.map((c4) => keyof2(c4[i])), Gg = [i];\n continue out;\n }\n }\n }\n if (Gg) yield Gg;\n }\n}\nfunction applyClip(selection2, mark2, dimensions, context) {\n let clipUrl;\n const { clip = context.clip } = mark2;\n switch (clip) {\n case \"frame\": {\n selection2 = create4(\"svg:g\", context).each(function() {\n this.appendChild(selection2.node());\n selection2.node = () => this;\n });\n clipUrl = getFrameClip(context, dimensions);\n break;\n }\n case \"sphere\": {\n clipUrl = getProjectionClip(context);\n break;\n }\n }\n applyAttr(selection2, \"aria-label\", mark2.ariaLabel);\n applyAttr(selection2, \"aria-description\", mark2.ariaDescription);\n applyAttr(selection2, \"aria-hidden\", mark2.ariaHidden);\n applyAttr(selection2, \"clip-path\", clipUrl);\n}\nfunction memoizeClip(clip) {\n const cache = /* @__PURE__ */ new WeakMap();\n return (context, dimensions) => {\n let url = cache.get(context);\n if (!url) {\n const id2 = getClipId();\n select_default2(context.ownerSVGElement).append(\"clipPath\").attr(\"id\", id2).call(clip, context, dimensions);\n cache.set(context, url = `url(#${id2})`);\n }\n return url;\n };\n}\nvar getFrameClip = memoizeClip((clipPath, context, dimensions) => {\n const { width: width2, height: height2, marginLeft: marginLeft2, marginRight: marginRight2, marginTop: marginTop2, marginBottom: marginBottom2 } = dimensions;\n clipPath.append(\"rect\").attr(\"x\", marginLeft2).attr(\"y\", marginTop2).attr(\"width\", width2 - marginRight2 - marginLeft2).attr(\"height\", height2 - marginTop2 - marginBottom2);\n});\nvar getProjectionClip = memoizeClip((clipPath, context) => {\n const { projection: projection3 } = context;\n if (!projection3) throw new Error(`the \"sphere\" clip option requires a projection`);\n clipPath.append(\"path\").attr(\"d\", path_default(projection3)({ type: \"Sphere\" }));\n});\nfunction applyIndirectStyles(selection2, mark2, dimensions, context) {\n applyClip(selection2, mark2, dimensions, context);\n applyAttr(selection2, \"class\", mark2.className);\n applyAttr(selection2, \"fill\", mark2.fill);\n applyAttr(selection2, \"fill-opacity\", mark2.fillOpacity);\n applyAttr(selection2, \"stroke\", mark2.stroke);\n applyAttr(selection2, \"stroke-width\", mark2.strokeWidth);\n applyAttr(selection2, \"stroke-opacity\", mark2.strokeOpacity);\n applyAttr(selection2, \"stroke-linejoin\", mark2.strokeLinejoin);\n applyAttr(selection2, \"stroke-linecap\", mark2.strokeLinecap);\n applyAttr(selection2, \"stroke-miterlimit\", mark2.strokeMiterlimit);\n applyAttr(selection2, \"stroke-dasharray\", mark2.strokeDasharray);\n applyAttr(selection2, \"stroke-dashoffset\", mark2.strokeDashoffset);\n applyAttr(selection2, \"shape-rendering\", mark2.shapeRendering);\n applyAttr(selection2, \"filter\", mark2.imageFilter);\n applyAttr(selection2, \"paint-order\", mark2.paintOrder);\n const { pointerEvents = context.pointerSticky === false ? \"none\" : void 0 } = mark2;\n applyAttr(selection2, \"pointer-events\", pointerEvents);\n}\nfunction applyDirectStyles(selection2, mark2) {\n applyStyle(selection2, \"mix-blend-mode\", mark2.mixBlendMode);\n applyAttr(selection2, \"opacity\", mark2.opacity);\n}\nfunction applyHref(selection2, href, target) {\n selection2.each(function(i) {\n const h = href(i);\n if (h != null) {\n const a2 = this.ownerDocument.createElementNS(namespaces_default.svg, \"a\");\n a2.setAttribute(\"fill\", \"inherit\");\n a2.setAttributeNS(namespaces_default.xlink, \"href\", h);\n if (target != null) a2.setAttribute(\"target\", target);\n this.parentNode.insertBefore(a2, this).appendChild(this);\n }\n });\n}\nfunction applyAttr(selection2, name2, value) {\n if (value != null) selection2.attr(name2, value);\n}\nfunction applyStyle(selection2, name2, value) {\n if (value != null) selection2.style(name2, value);\n}\nfunction applyTransform(selection2, mark2, { x: x3, y: y3 }, tx = offset, ty = offset) {\n tx += mark2.dx;\n ty += mark2.dy;\n if (x3?.bandwidth) tx += x3.bandwidth() / 2;\n if (y3?.bandwidth) ty += y3.bandwidth() / 2;\n if (tx || ty) selection2.attr(\"transform\", `translate(${tx},${ty})`);\n}\nfunction impliedString(value, impliedValue) {\n if ((value = string(value)) !== impliedValue) return value;\n}\nfunction impliedNumber(value, impliedValue) {\n if ((value = number5(value)) !== impliedValue) return value;\n}\nvar validClassName = /^-?([_a-z]|[\\240-\\377]|\\\\[0-9a-f]{1,6}(\\r\\n|[ \\t\\r\\n\\f])?|\\\\[^\\r\\n\\f0-9a-f])([_a-z0-9-]|[\\240-\\377]|\\\\[0-9a-f]{1,6}(\\r\\n|[ \\t\\r\\n\\f])?|\\\\[^\\r\\n\\f0-9a-f])*$/i;\nfunction maybeClassName(name2) {\n if (name2 === void 0) return \"plot-d6a7b5\";\n name2 = `${name2}`;\n if (!validClassName.test(name2)) throw new Error(`invalid class name: ${name2}`);\n return name2;\n}\nfunction applyInlineStyles(selection2, style2) {\n if (typeof style2 === \"string\") {\n selection2.property(\"style\", style2);\n } else if (style2 != null) {\n for (const element of selection2) {\n Object.assign(element.style, style2);\n }\n }\n}\nfunction applyFrameAnchor({ frameAnchor }, { width: width2, height: height2, marginTop: marginTop2, marginRight: marginRight2, marginBottom: marginBottom2, marginLeft: marginLeft2 }) {\n return [\n /left$/.test(frameAnchor) ? marginLeft2 : /right$/.test(frameAnchor) ? width2 - marginRight2 : (marginLeft2 + width2 - marginRight2) / 2,\n /^top/.test(frameAnchor) ? marginTop2 : /^bottom/.test(frameAnchor) ? height2 - marginBottom2 : (marginTop2 + height2 - marginBottom2) / 2\n ];\n}\n\n// ../../node_modules/@observablehq/plot/src/mark.js\nvar Mark = class {\n constructor(data, channels = {}, options = {}, defaults22) {\n const {\n facet = \"auto\",\n facetAnchor,\n fx,\n fy,\n sort: sort3,\n dx = 0,\n dy = 0,\n margin: margin2 = 0,\n marginTop: marginTop2 = margin2,\n marginRight: marginRight2 = margin2,\n marginBottom: marginBottom2 = margin2,\n marginLeft: marginLeft2 = margin2,\n className,\n clip = defaults22?.clip,\n channels: extraChannels,\n tip: tip2,\n render\n } = options;\n this.data = data;\n this.sort = isDomainSort(sort3) ? sort3 : null;\n this.initializer = initializer(options).initializer;\n this.transform = this.initializer ? options.transform : basic(options).transform;\n if (facet === null || facet === false) {\n this.facet = null;\n } else {\n this.facet = keyword(facet === true ? \"include\" : facet, \"facet\", [\"auto\", \"include\", \"exclude\", \"super\"]);\n this.fx = data === singleton && typeof fx === \"string\" ? [fx] : fx;\n this.fy = data === singleton && typeof fy === \"string\" ? [fy] : fy;\n }\n this.facetAnchor = maybeFacetAnchor(facetAnchor);\n channels = maybeNamed(channels);\n if (extraChannels !== void 0) channels = { ...maybeChannels(extraChannels), ...channels };\n if (defaults22 !== void 0) channels = { ...styles(this, options, defaults22), ...channels };\n this.channels = Object.fromEntries(\n Object.entries(channels).map(([name2, channel]) => {\n if (isOptions(channel.value)) {\n const { value, label: label2 = channel.label, scale: scale3 = channel.scale } = channel.value;\n channel = { ...channel, label: label2, scale: scale3, value };\n }\n if (data === singleton && typeof channel.value === \"string\") {\n const { value } = channel;\n channel = { ...channel, value: [value] };\n }\n return [name2, channel];\n }).filter(([name2, { value, optional: optional2 }]) => {\n if (value != null) return true;\n if (optional2) return false;\n throw new Error(`missing channel value: ${name2}`);\n })\n );\n this.dx = +dx;\n this.dy = +dy;\n this.marginTop = +marginTop2;\n this.marginRight = +marginRight2;\n this.marginBottom = +marginBottom2;\n this.marginLeft = +marginLeft2;\n this.clip = maybeClip(clip);\n this.tip = maybeTip(tip2);\n this.className = className ? maybeClassName(className) : null;\n if (this.facet === \"super\") {\n if (fx || fy) throw new Error(`super-faceting cannot use fx or fy`);\n for (const name2 in this.channels) {\n const { scale: scale3 } = channels[name2];\n if (scale3 !== \"x\" && scale3 !== \"y\") continue;\n throw new Error(`super-faceting cannot use x or y`);\n }\n }\n if (render != null) {\n this.render = composeRender(render, this.render);\n }\n }\n initialize(facets, facetChannels, plotOptions) {\n let data = dataify(this.data);\n if (facets === void 0 && data != null) facets = [range2(data)];\n const originalFacets = facets;\n if (this.transform != null) ({ facets, data } = this.transform(data, facets, plotOptions)), data = dataify(data);\n if (facets !== void 0) facets.original = originalFacets;\n const channels = createChannels(this.channels, data);\n if (this.sort != null) channelDomain(data, facets, channels, facetChannels, this.sort);\n return { data, facets, channels };\n }\n filter(index2, channels, values2) {\n for (const name2 in channels) {\n const { filter: filter3 = defined } = channels[name2];\n if (filter3 !== null) {\n const value = values2[name2];\n index2 = index2.filter((i) => filter3(value[i]));\n }\n }\n return index2;\n }\n // If there is a projection, and there are paired x and y channels associated\n // with the x and y scale respectively (and not already in screen coordinates\n // as with an initializer), then apply the projection, replacing the x and y\n // values. Note that the x and y scales themselves don’t exist if there is a\n // projection, but whether the channels are associated with scales still\n // determines whether the projection should apply; think of the projection as\n // a combination xy-scale.\n project(channels, values2, context) {\n for (const cx in channels) {\n if (channels[cx].scale === \"x\" && /^x|x$/.test(cx)) {\n const cy = cx.replace(/^x|x$/, \"y\");\n if (cy in channels && channels[cy].scale === \"y\") {\n project(cx, cy, values2, context.projection);\n }\n }\n }\n }\n scale(channels, scales2, context) {\n const values2 = valueObject(channels, scales2);\n if (context.projection) this.project(channels, values2, context);\n return values2;\n }\n};\nfunction marks(...marks2) {\n marks2.plot = Mark.prototype.plot;\n return marks2;\n}\nfunction composeRender(r1, r2) {\n if (r1 == null) return r2 === null ? void 0 : r2;\n if (r2 == null) return r1 === null ? void 0 : r1;\n if (typeof r1 !== \"function\") throw new TypeError(`invalid render transform: ${r1}`);\n if (typeof r2 !== \"function\") throw new TypeError(`invalid render transform: ${r2}`);\n return function(i, s2, v2, d, c4, next) {\n return r1.call(this, i, s2, v2, d, c4, (i2, s3, v3, d2, c5) => {\n return r2.call(this, i2, s3, v3, d2, c5, next);\n });\n };\n}\nfunction maybeChannels(channels) {\n return Object.fromEntries(\n Object.entries(maybeNamed(channels)).map(([name2, channel]) => {\n channel = typeof channel === \"string\" ? { value: channel, label: name2 } : maybeValue(channel);\n if (channel.filter === void 0 && channel.scale == null) channel = { ...channel, filter: null };\n return [name2, channel];\n })\n );\n}\nfunction maybeTip(tip2) {\n return tip2 === true ? \"xy\" : tip2 === false || tip2 == null ? null : typeof tip2 === \"string\" ? keyword(tip2, \"tip\", [\"x\", \"y\", \"xy\"]) : tip2;\n}\nfunction withTip(options, pointer2) {\n return options?.tip === true ? { ...options, tip: pointer2 } : isObject(options?.tip) && options.tip.pointer === void 0 ? { ...options, tip: { ...options.tip, pointer: pointer2 } } : options;\n}\n\n// ../../node_modules/@observablehq/plot/src/dimensions.js\nfunction createDimensions(scales2, marks2, options = {}) {\n let marginTopDefault = 0.5 - offset, marginRightDefault = 0.5 + offset, marginBottomDefault = 0.5 + offset, marginLeftDefault = 0.5 - offset;\n for (const { marginTop: marginTop3, marginRight: marginRight3, marginBottom: marginBottom3, marginLeft: marginLeft3 } of marks2) {\n if (marginTop3 > marginTopDefault) marginTopDefault = marginTop3;\n if (marginRight3 > marginRightDefault) marginRightDefault = marginRight3;\n if (marginBottom3 > marginBottomDefault) marginBottomDefault = marginBottom3;\n if (marginLeft3 > marginLeftDefault) marginLeftDefault = marginLeft3;\n }\n let {\n margin: margin2,\n marginTop: marginTop2 = margin2 !== void 0 ? margin2 : marginTopDefault,\n marginRight: marginRight2 = margin2 !== void 0 ? margin2 : marginRightDefault,\n marginBottom: marginBottom2 = margin2 !== void 0 ? margin2 : marginBottomDefault,\n marginLeft: marginLeft2 = margin2 !== void 0 ? margin2 : marginLeftDefault\n } = options;\n marginTop2 = +marginTop2;\n marginRight2 = +marginRight2;\n marginBottom2 = +marginBottom2;\n marginLeft2 = +marginLeft2;\n let {\n width: width2 = 640,\n height: height2 = autoHeight(scales2, options, {\n width: width2,\n marginTopDefault,\n marginRightDefault,\n marginBottomDefault,\n marginLeftDefault\n }) + Math.max(0, marginTop2 - marginTopDefault + marginBottom2 - marginBottomDefault)\n } = options;\n width2 = +width2;\n height2 = +height2;\n const dimensions = {\n width: width2,\n height: height2,\n marginTop: marginTop2,\n marginRight: marginRight2,\n marginBottom: marginBottom2,\n marginLeft: marginLeft2\n };\n if (scales2.fx || scales2.fy) {\n let {\n margin: facetMargin2,\n marginTop: facetMarginTop2 = facetMargin2 !== void 0 ? facetMargin2 : marginTop2,\n marginRight: facetMarginRight2 = facetMargin2 !== void 0 ? facetMargin2 : marginRight2,\n marginBottom: facetMarginBottom2 = facetMargin2 !== void 0 ? facetMargin2 : marginBottom2,\n marginLeft: facetMarginLeft2 = facetMargin2 !== void 0 ? facetMargin2 : marginLeft2\n } = options.facet ?? {};\n facetMarginTop2 = +facetMarginTop2;\n facetMarginRight2 = +facetMarginRight2;\n facetMarginBottom2 = +facetMarginBottom2;\n facetMarginLeft2 = +facetMarginLeft2;\n dimensions.facet = {\n marginTop: facetMarginTop2,\n marginRight: facetMarginRight2,\n marginBottom: facetMarginBottom2,\n marginLeft: facetMarginLeft2\n };\n }\n return dimensions;\n}\nfunction autoHeight({ x: x3, y: y3, fy, fx }, { projection: projection3, aspectRatio: aspectRatio2 }, { width: width2, marginTopDefault, marginRightDefault, marginBottomDefault, marginLeftDefault }) {\n const nfy = fy ? fy.scale.domain().length || 1 : 1;\n const ar = projectionAspectRatio(projection3);\n if (ar) {\n const nfx = fx ? fx.scale.domain().length : 1;\n const far = (1.1 * nfy - 0.1) / (1.1 * nfx - 0.1) * ar;\n const lar = Math.max(0.1, Math.min(10, far));\n return Math.round((width2 - marginLeftDefault - marginRightDefault) * lar + marginTopDefault + marginBottomDefault);\n }\n const ny = y3 ? isOrdinalScale(y3) ? y3.scale.domain().length || 1 : Math.max(7, 17 / nfy) : 1;\n if (aspectRatio2 != null) {\n aspectRatio2 = +aspectRatio2;\n if (!(isFinite(aspectRatio2) && aspectRatio2 > 0)) throw new Error(`invalid aspectRatio: ${aspectRatio2}`);\n const ratio = aspectRatioLength(\"y\", y3) / (aspectRatioLength(\"x\", x3) * aspectRatio2);\n const fxb = fx ? fx.scale.bandwidth() : 1;\n const fyb = fy ? fy.scale.bandwidth() : 1;\n const w = fxb * (width2 - marginLeftDefault - marginRightDefault) - x3.insetLeft - x3.insetRight;\n return (ratio * w + y3.insetTop + y3.insetBottom) / fyb + marginTopDefault + marginBottomDefault;\n }\n return !!(y3 || fy) * Math.max(1, Math.min(60, ny * nfy)) * 20 + !!fx * 30 + 60;\n}\nfunction aspectRatioLength(k2, scale3) {\n if (!scale3) throw new Error(`aspectRatio requires ${k2} scale`);\n const { type: type2, domain } = scale3;\n let transform3;\n switch (type2) {\n case \"linear\":\n case \"utc\":\n case \"time\":\n transform3 = Number;\n break;\n case \"pow\": {\n const exponent = scale3.scale.exponent();\n transform3 = (x3) => Math.pow(x3, exponent);\n break;\n }\n case \"log\":\n transform3 = Math.log;\n break;\n case \"point\":\n case \"band\":\n return domain.length;\n default:\n throw new Error(`unsupported ${k2} scale for aspectRatio: ${type2}`);\n }\n const [min5, max4] = extent(domain);\n return Math.abs(transform3(max4) - transform3(min5));\n}\n\n// ../../node_modules/@observablehq/plot/src/interactions/pointer.js\nvar states = /* @__PURE__ */ new WeakMap();\nfunction pointerK(kx2, ky2, { x: x3, y: y3, px, py, maxRadius = 40, channels, render, ...options } = {}) {\n maxRadius = +maxRadius;\n if (px != null) x3 ??= null, channels = { ...channels, px: { value: px, scale: \"x\" } };\n if (py != null) y3 ??= null, channels = { ...channels, py: { value: py, scale: \"y\" } };\n return {\n x: x3,\n y: y3,\n channels,\n ...options,\n // Unlike other composed transforms, the render transform must be the\n // outermost render function because it will re-render dynamically in\n // response to pointer events.\n render: composeRender(function(index2, scales2, values2, dimensions, context, next) {\n context = { ...context, pointerSticky: false };\n const svg = context.ownerSVGElement;\n const { data } = context.getMarkState(this);\n let state = states.get(svg);\n if (!state) states.set(svg, state = { sticky: false, roots: [], renders: [] });\n let renderIndex = state.renders.push(render2) - 1;\n const { x: x4, y: y4, fx, fy } = scales2;\n let tx = fx ? fx(index2.fx) - dimensions.marginLeft : 0;\n let ty = fy ? fy(index2.fy) - dimensions.marginTop : 0;\n if (x4?.bandwidth) tx += x4.bandwidth() / 2;\n if (y4?.bandwidth) ty += y4.bandwidth() / 2;\n const faceted = index2.fi != null;\n let facetState;\n if (faceted) {\n let facetStates = state.facetStates;\n if (!facetStates) state.facetStates = facetStates = /* @__PURE__ */ new Map();\n facetState = facetStates.get(this);\n if (!facetState) facetStates.set(this, facetState = /* @__PURE__ */ new Map());\n }\n const [cx, cy] = applyFrameAnchor(this, dimensions);\n const { px: PX, py: PY } = values2;\n const px2 = PX ? (i2) => PX[i2] : anchorX(values2, cx);\n const py2 = PY ? (i2) => PY[i2] : anchorY(values2, cy);\n let i;\n let g;\n let s2;\n let f;\n function update2(ii, ri) {\n if (faceted) {\n if (f) f = cancelAnimationFrame(f);\n if (ii == null) facetState.delete(index2.fi);\n else {\n facetState.set(index2.fi, ri);\n f = requestAnimationFrame(() => {\n f = null;\n for (const [fi, r] of facetState) {\n if (r < ri || r === ri && fi < index2.fi) {\n ii = null;\n break;\n }\n }\n render2(ii);\n });\n return;\n }\n }\n render2(ii);\n }\n function render2(ii) {\n if (i === ii && s2 === state.sticky) return;\n i = ii;\n s2 = context.pointerSticky = state.sticky;\n const I = i == null ? [] : [i];\n if (faceted) I.fx = index2.fx, I.fy = index2.fy, I.fi = index2.fi;\n const r = next(I, scales2, values2, dimensions, context);\n if (g) {\n if (faceted) {\n const p = g.parentNode;\n const ft = g.getAttribute(\"transform\");\n const mt = r.getAttribute(\"transform\");\n ft ? r.setAttribute(\"transform\", ft) : r.removeAttribute(\"transform\");\n mt ? p.setAttribute(\"transform\", mt) : p.removeAttribute(\"transform\");\n r.removeAttribute(\"aria-label\");\n r.removeAttribute(\"aria-description\");\n r.removeAttribute(\"aria-hidden\");\n }\n g.replaceWith(r);\n }\n state.roots[renderIndex] = g = r;\n if (!(i == null && facetState?.size > 1)) {\n const value = i == null ? null : isArray2(data) ? data[i] : data.get(i);\n context.dispatchValue(value);\n }\n return r;\n }\n function pointermove(event) {\n if (state.sticky || event.pointerType === \"mouse\" && event.buttons === 1) return;\n let [xp, yp] = pointer_default(event);\n xp -= tx, yp -= ty;\n const kpx = xp < dimensions.marginLeft || xp > dimensions.width - dimensions.marginRight ? 1 : kx2;\n const kpy = yp < dimensions.marginTop || yp > dimensions.height - dimensions.marginBottom ? 1 : ky2;\n let ii = null;\n let ri = maxRadius * maxRadius;\n for (const j of index2) {\n const dx = kpx * (px2(j) - xp);\n const dy = kpy * (py2(j) - yp);\n const rj = dx * dx + dy * dy;\n if (rj <= ri) ii = j, ri = rj;\n }\n if (ii != null && (kx2 !== 1 || ky2 !== 1)) {\n const dx = px2(ii) - xp;\n const dy = py2(ii) - yp;\n ri = dx * dx + dy * dy;\n }\n update2(ii, ri);\n }\n function pointerdown(event) {\n if (event.pointerType !== \"mouse\") return;\n if (i == null) return;\n if (state.sticky && state.roots.some((r) => r?.contains(event.target))) return;\n if (state.sticky) state.sticky = false, state.renders.forEach((r) => r(null));\n else state.sticky = true, render2(i);\n event.stopImmediatePropagation();\n }\n function pointerleave(event) {\n if (event.pointerType !== \"mouse\") return;\n if (!state.sticky) update2(null);\n }\n svg.addEventListener(\"pointerenter\", pointermove);\n svg.addEventListener(\"pointermove\", pointermove);\n svg.addEventListener(\"pointerdown\", pointerdown);\n svg.addEventListener(\"pointerleave\", pointerleave);\n return render2(null);\n }, render)\n };\n}\nfunction pointer(options) {\n return pointerK(1, 1, options);\n}\nfunction pointerX(options) {\n return pointerK(1, 0.01, options);\n}\nfunction pointerY(options) {\n return pointerK(0.01, 1, options);\n}\nfunction anchorX({ x1: X13, x2: X23, x: X3 = X13 }, cx) {\n return X13 && X23 ? (i) => (X13[i] + X23[i]) / 2 : X3 ? (i) => X3[i] : () => cx;\n}\nfunction anchorY({ y1: Y13, y2: Y23, y: Y3 = Y13 }, cy) {\n return Y13 && Y23 ? (i) => (Y13[i] + Y23[i]) / 2 : Y3 ? (i) => Y3[i] : () => cy;\n}\n\n// ../../node_modules/@observablehq/plot/src/axes.js\nfunction inferFontVariant(scale3) {\n return isOrdinalScale(scale3) && scale3.interval === void 0 ? void 0 : \"tabular-nums\";\n}\n\n// ../../node_modules/@observablehq/plot/src/legends/ramp.js\nfunction legendRamp(color3, options) {\n let {\n label: label2 = color3.label,\n tickSize = 6,\n width: width2 = 240,\n height: height2 = 44 + tickSize,\n marginTop: marginTop2 = 18,\n marginRight: marginRight2 = 0,\n marginBottom: marginBottom2 = 16 + tickSize,\n marginLeft: marginLeft2 = 0,\n style: style2,\n ticks: ticks2 = (width2 - marginLeft2 - marginRight2) / 64,\n tickFormat: tickFormat2,\n fontVariant = inferFontVariant(color3),\n round: round2 = true,\n opacity: opacity2,\n className\n } = options;\n const context = createContext(options);\n className = maybeClassName(className);\n opacity2 = maybeNumberChannel(opacity2)[1];\n if (tickFormat2 === null) tickFormat2 = () => null;\n const svg = create4(\"svg\", context).attr(\"class\", `${className}-ramp`).attr(\"font-family\", \"system-ui, sans-serif\").attr(\"font-size\", 10).attr(\"width\", width2).attr(\"height\", height2).attr(\"viewBox\", `0 0 ${width2} ${height2}`).call(\n (svg2) => (\n // Warning: if you edit this, change defaultClassName.\n svg2.append(\"style\").text(\n `:where(.${className}-ramp) {\n display: block;\n height: auto;\n height: intrinsic;\n max-width: 100%;\n overflow: visible;\n}\n:where(.${className}-ramp text) {\n white-space: pre;\n}`\n )\n )\n ).call(applyInlineStyles, style2);\n let tickAdjust = (g) => g.selectAll(\".tick line\").attr(\"y1\", marginTop2 + marginBottom2 - height2);\n let x3;\n const applyRange = round2 ? (x4, range4) => x4.rangeRound(range4) : (x4, range4) => x4.range(range4);\n const { type: type2, domain, range: range3, interpolate, scale: scale3, pivot } = color3;\n if (interpolate) {\n const interpolator = range3 === void 0 ? interpolate : piecewise(interpolate.length === 1 ? interpolatePiecewise(interpolate) : interpolate, range3);\n x3 = applyRange(\n scale3.copy(),\n quantize_default(\n number_default(marginLeft2, width2 - marginRight2),\n Math.min(domain.length + (pivot !== void 0), range3 === void 0 ? Infinity : range3.length)\n )\n );\n const n = 256;\n const canvas = context.document.createElement(\"canvas\");\n canvas.width = n;\n canvas.height = 1;\n const context2 = canvas.getContext(\"2d\");\n for (let i = 0, j = n - 1; i < n; ++i) {\n context2.fillStyle = interpolator(i / j);\n context2.fillRect(i, 0, 1, 1);\n }\n svg.append(\"image\").attr(\"opacity\", opacity2).attr(\"x\", marginLeft2).attr(\"y\", marginTop2).attr(\"width\", width2 - marginLeft2 - marginRight2).attr(\"height\", height2 - marginTop2 - marginBottom2).attr(\"preserveAspectRatio\", \"none\").attr(\"xlink:href\", canvas.toDataURL());\n } else if (type2 === \"threshold\") {\n const thresholds = domain;\n const thresholdFormat = tickFormat2 === void 0 ? (d) => d : typeof tickFormat2 === \"string\" ? format(tickFormat2) : tickFormat2;\n x3 = applyRange(linear2().domain([-1, range3.length - 1]), [marginLeft2, width2 - marginRight2]);\n svg.append(\"g\").attr(\"fill-opacity\", opacity2).selectAll().data(range3).enter().append(\"rect\").attr(\"x\", (d, i) => x3(i - 1)).attr(\"y\", marginTop2).attr(\"width\", (d, i) => x3(i) - x3(i - 1)).attr(\"height\", height2 - marginTop2 - marginBottom2).attr(\"fill\", (d) => d);\n ticks2 = map3(thresholds, (_, i) => i);\n tickFormat2 = (i) => thresholdFormat(thresholds[i], i);\n } else {\n x3 = applyRange(band().domain(domain), [marginLeft2, width2 - marginRight2]);\n svg.append(\"g\").attr(\"fill-opacity\", opacity2).selectAll().data(domain).enter().append(\"rect\").attr(\"x\", x3).attr(\"y\", marginTop2).attr(\"width\", Math.max(0, x3.bandwidth() - 1)).attr(\"height\", height2 - marginTop2 - marginBottom2).attr(\"fill\", scale3);\n tickAdjust = () => {\n };\n }\n svg.append(\"g\").attr(\"transform\", `translate(0,${height2 - marginBottom2})`).call(\n axisBottom(x3).ticks(Array.isArray(ticks2) ? null : ticks2, typeof tickFormat2 === \"string\" ? tickFormat2 : void 0).tickFormat(typeof tickFormat2 === \"function\" ? tickFormat2 : void 0).tickSize(tickSize).tickValues(Array.isArray(ticks2) ? ticks2 : null)\n ).attr(\"font-size\", null).attr(\"font-family\", null).attr(\"font-variant\", impliedString(fontVariant, \"normal\")).call(tickAdjust).call((g) => g.select(\".domain\").remove());\n if (label2 !== void 0) {\n svg.append(\"text\").attr(\"x\", marginLeft2).attr(\"y\", marginTop2 - 6).attr(\"fill\", \"currentColor\").attr(\"font-weight\", \"bold\").text(label2);\n }\n return svg.node();\n}\n\n// ../../node_modules/@observablehq/plot/src/math.js\nvar radians3 = Math.PI / 180;\n\n// ../../node_modules/@observablehq/plot/src/marker.js\nfunction markers(mark2, { marker, markerStart = marker, markerMid = marker, markerEnd = marker } = {}) {\n mark2.markerStart = maybeMarker(markerStart);\n mark2.markerMid = maybeMarker(markerMid);\n mark2.markerEnd = maybeMarker(markerEnd);\n}\nfunction maybeMarker(marker) {\n if (marker == null || marker === false) return null;\n if (marker === true) return markerCircleFill;\n if (typeof marker === \"function\") return marker;\n switch (`${marker}`.toLowerCase()) {\n case \"none\":\n return null;\n case \"arrow\":\n return markerArrow(\"auto\");\n case \"arrow-reverse\":\n return markerArrow(\"auto-start-reverse\");\n case \"dot\":\n return markerDot;\n case \"circle\":\n case \"circle-fill\":\n return markerCircleFill;\n case \"circle-stroke\":\n return markerCircleStroke;\n case \"tick\":\n return markerTick(\"auto\");\n case \"tick-x\":\n return markerTick(90);\n case \"tick-y\":\n return markerTick(0);\n }\n throw new Error(`invalid marker: ${marker}`);\n}\nfunction markerArrow(orient) {\n return (color3, context) => create4(\"svg:marker\", context).attr(\"viewBox\", \"-5 -5 10 10\").attr(\"markerWidth\", 6.67).attr(\"markerHeight\", 6.67).attr(\"orient\", orient).attr(\"fill\", \"none\").attr(\"stroke\", color3).attr(\"stroke-width\", 1.5).attr(\"stroke-linecap\", \"round\").attr(\"stroke-linejoin\", \"round\").call((marker) => marker.append(\"path\").attr(\"d\", \"M-1.5,-3l3,3l-3,3\")).node();\n}\nfunction markerDot(color3, context) {\n return create4(\"svg:marker\", context).attr(\"viewBox\", \"-5 -5 10 10\").attr(\"markerWidth\", 6.67).attr(\"markerHeight\", 6.67).attr(\"fill\", color3).attr(\"stroke\", \"none\").call((marker) => marker.append(\"circle\").attr(\"r\", 2.5)).node();\n}\nfunction markerCircleFill(color3, context) {\n return create4(\"svg:marker\", context).attr(\"viewBox\", \"-5 -5 10 10\").attr(\"markerWidth\", 6.67).attr(\"markerHeight\", 6.67).attr(\"fill\", color3).attr(\"stroke\", \"var(--plot-background)\").attr(\"stroke-width\", 1.5).call((marker) => marker.append(\"circle\").attr(\"r\", 3)).node();\n}\nfunction markerCircleStroke(color3, context) {\n return create4(\"svg:marker\", context).attr(\"viewBox\", \"-5 -5 10 10\").attr(\"markerWidth\", 6.67).attr(\"markerHeight\", 6.67).attr(\"fill\", \"var(--plot-background)\").attr(\"stroke\", color3).attr(\"stroke-width\", 1.5).call((marker) => marker.append(\"circle\").attr(\"r\", 3)).node();\n}\nfunction markerTick(orient) {\n return (color3, context) => create4(\"svg:marker\", context).attr(\"viewBox\", \"-3 -3 6 6\").attr(\"markerWidth\", 6).attr(\"markerHeight\", 6).attr(\"orient\", orient).attr(\"stroke\", color3).call((marker) => marker.append(\"path\").attr(\"d\", \"M0,-3v6\")).node();\n}\nvar nextMarkerId = 0;\nfunction applyMarkers(path2, mark2, { stroke: S }, context) {\n return applyMarkersColor(path2, mark2, S && ((i) => S[i]), null, context);\n}\nfunction applyGroupedMarkers(path2, mark2, { stroke: S, z: Z }, context) {\n return applyMarkersColor(path2, mark2, S && (([i]) => S[i]), Z, context);\n}\nvar START = 1;\nvar END = 2;\nfunction getGroupedOrientation(path2, Z) {\n const O = new Uint8Array(Z.length);\n const D3 = path2.data().filter((I) => I.length > 1);\n const n = D3.length;\n for (let i = 0, z = unset; i < n; ++i) {\n const I = D3[i];\n if (I.length > 1) {\n const i2 = I[0];\n if (z !== (z = keyof2(Z[i2]))) O[i2] |= START;\n }\n }\n for (let i = n - 1, z = unset; i >= 0; --i) {\n const I = D3[i];\n if (I.length > 1) {\n const i2 = I[0];\n if (z !== (z = keyof2(Z[i2]))) O[i2] |= END;\n }\n }\n return ([i]) => O[i];\n}\nfunction applyMarkersColor(path2, { markerStart, markerMid, markerEnd, stroke }, strokeof = () => stroke, Z, context) {\n if (!markerStart && !markerMid && !markerEnd) return;\n const iriByMarkerColor = /* @__PURE__ */ new Map();\n const orient = Z && getGroupedOrientation(path2, Z);\n function applyMarker(name2, marker, filter3) {\n return function(i) {\n if (filter3 && !filter3(i)) return;\n const color3 = strokeof(i);\n let iriByColor = iriByMarkerColor.get(marker);\n if (!iriByColor) iriByMarkerColor.set(marker, iriByColor = /* @__PURE__ */ new Map());\n let iri = iriByColor.get(color3);\n if (!iri) {\n const node = this.parentNode.insertBefore(marker(color3, context), this);\n const id2 = `plot-marker-${++nextMarkerId}`;\n node.setAttribute(\"id\", id2);\n iriByColor.set(color3, iri = `url(#${id2})`);\n }\n this.setAttribute(name2, iri);\n };\n }\n if (markerStart) path2.each(applyMarker(\"marker-start\", markerStart, orient && ((i) => orient(i) & START)));\n if (markerMid && orient) path2.each(applyMarker(\"marker-start\", markerMid, (i) => !(orient(i) & START)));\n if (markerMid) path2.each(applyMarker(\"marker-mid\", markerMid));\n if (markerEnd) path2.each(applyMarker(\"marker-end\", markerEnd, orient && ((i) => orient(i) & END)));\n}\n\n// ../../node_modules/@observablehq/plot/src/transforms/inset.js\nfunction maybeInsetX({ inset: inset2, insetLeft, insetRight, ...options } = {}) {\n [insetLeft, insetRight] = maybeInset(inset2, insetLeft, insetRight);\n return { inset: inset2, insetLeft, insetRight, ...options };\n}\nfunction maybeInsetY({ inset: inset2, insetTop, insetBottom, ...options } = {}) {\n [insetTop, insetBottom] = maybeInset(inset2, insetTop, insetBottom);\n return { inset: inset2, insetTop, insetBottom, ...options };\n}\nfunction maybeInset(inset2, inset1, inset22) {\n return inset2 === void 0 && inset1 === void 0 && inset22 === void 0 ? offset ? [1, 0] : [0.5, 0.5] : [inset1, inset22];\n}\n\n// ../../node_modules/@observablehq/plot/src/transforms/interval.js\nfunction maybeIntervalValue(value, { interval: interval3 }) {\n value = { ...maybeValue(value) };\n value.interval = maybeInterval(value.interval === void 0 ? interval3 : value.interval);\n return value;\n}\nfunction maybeIntervalK(k2, maybeInsetK, options, trivial) {\n const { [k2]: v2, [`${k2}1`]: v1, [`${k2}2`]: v22 } = options;\n const { value, interval: interval3 } = maybeIntervalValue(v2, options);\n if (value == null || interval3 == null && !trivial) return options;\n const label2 = labelof(v2);\n if (interval3 == null) {\n let V;\n const kv = { transform: (data) => V || (V = valueof(data, value)), label: label2 };\n return {\n ...options,\n [k2]: void 0,\n [`${k2}1`]: v1 === void 0 ? kv : v1,\n [`${k2}2`]: v22 === void 0 && !(v1 === v22 && trivial) ? kv : v22\n };\n }\n let D1, V1;\n function transform3(data) {\n if (V1 !== void 0 && data === D1) return V1;\n return V1 = map3(valueof(D1 = data, value), (v3) => interval3.floor(v3));\n }\n return maybeInsetK({\n ...options,\n [k2]: void 0,\n [`${k2}1`]: v1 === void 0 ? { transform: transform3, label: label2 } : v1,\n [`${k2}2`]: v22 === void 0 ? { transform: (data) => transform3(data).map((v3) => interval3.offset(v3)), label: label2 } : v22\n });\n}\nfunction maybeIntervalMidK(k2, maybeInsetK, options) {\n const { [k2]: v2 } = options;\n const { value, interval: interval3 } = maybeIntervalValue(v2, options);\n if (value == null || interval3 == null) return options;\n return maybeInsetK({\n ...options,\n [k2]: {\n label: labelof(v2),\n transform: (data) => {\n const V1 = map3(valueof(data, value), (v3) => interval3.floor(v3));\n const V2 = V1.map((v3) => interval3.offset(v3));\n return V1.map(\n isTemporal(V1) ? (v1, v22) => v1 == null || isNaN(v1 = +v1) || (v22 = V2[v22], v22 == null) || isNaN(v22 = +v22) ? void 0 : new Date((v1 + v22) / 2) : (v1, v22) => v1 == null || (v22 = V2[v22], v22 == null) ? NaN : (+v1 + +v22) / 2\n );\n }\n }\n });\n}\nfunction maybeTrivialIntervalX(options = {}) {\n return maybeIntervalK(\"x\", maybeInsetX, options, true);\n}\nfunction maybeTrivialIntervalY(options = {}) {\n return maybeIntervalK(\"y\", maybeInsetY, options, true);\n}\nfunction maybeIntervalX(options = {}) {\n return maybeIntervalK(\"x\", maybeInsetX, options);\n}\nfunction maybeIntervalY(options = {}) {\n return maybeIntervalK(\"y\", maybeInsetY, options);\n}\nfunction maybeIntervalMidX(options = {}) {\n return maybeIntervalMidK(\"x\", maybeInsetX, options);\n}\nfunction maybeIntervalMidY(options = {}) {\n return maybeIntervalMidK(\"y\", maybeInsetY, options);\n}\n\n// ../../node_modules/@observablehq/plot/src/marks/rule.js\nvar defaults = {\n ariaLabel: \"rule\",\n fill: null,\n stroke: \"currentColor\"\n};\nvar RuleX = class extends Mark {\n constructor(data, options = {}) {\n const { x: x3, y1: y12, y2: y22, inset: inset2 = 0, insetTop = inset2, insetBottom = inset2 } = options;\n super(\n data,\n {\n x: { value: x3, scale: \"x\", optional: true },\n y1: { value: y12, scale: \"y\", optional: true },\n y2: { value: y22, scale: \"y\", optional: true }\n },\n withTip(options, \"x\"),\n defaults\n );\n this.insetTop = number5(insetTop);\n this.insetBottom = number5(insetBottom);\n markers(this, options);\n }\n render(index2, scales2, channels, dimensions, context) {\n const { x: x3, y: y3 } = scales2;\n const { x: X3, y1: Y13, y2: Y23 } = channels;\n const { width: width2, height: height2, marginTop: marginTop2, marginRight: marginRight2, marginLeft: marginLeft2, marginBottom: marginBottom2 } = dimensions;\n const { insetTop, insetBottom } = this;\n return create4(\"svg:g\", context).call(applyIndirectStyles, this, dimensions, context).call(applyTransform, this, { x: X3 && x3 }, offset, 0).call(\n (g) => g.selectAll().data(index2).enter().append(\"line\").call(applyDirectStyles, this).attr(\"x1\", X3 ? (i) => X3[i] : (marginLeft2 + width2 - marginRight2) / 2).attr(\"x2\", X3 ? (i) => X3[i] : (marginLeft2 + width2 - marginRight2) / 2).attr(\"y1\", Y13 && !isCollapsed(y3) ? (i) => Y13[i] + insetTop : marginTop2 + insetTop).attr(\n \"y2\",\n Y23 && !isCollapsed(y3) ? y3.bandwidth ? (i) => Y23[i] + y3.bandwidth() - insetBottom : (i) => Y23[i] - insetBottom : height2 - marginBottom2 - insetBottom\n ).call(applyChannelStyles, this, channels).call(applyMarkers, this, channels, context)\n ).node();\n }\n};\nvar RuleY = class extends Mark {\n constructor(data, options = {}) {\n const { x1: x12, x2: x22, y: y3, inset: inset2 = 0, insetRight = inset2, insetLeft = inset2 } = options;\n super(\n data,\n {\n y: { value: y3, scale: \"y\", optional: true },\n x1: { value: x12, scale: \"x\", optional: true },\n x2: { value: x22, scale: \"x\", optional: true }\n },\n withTip(options, \"y\"),\n defaults\n );\n this.insetRight = number5(insetRight);\n this.insetLeft = number5(insetLeft);\n markers(this, options);\n }\n render(index2, scales2, channels, dimensions, context) {\n const { x: x3, y: y3 } = scales2;\n const { y: Y3, x1: X13, x2: X23 } = channels;\n const { width: width2, height: height2, marginTop: marginTop2, marginRight: marginRight2, marginLeft: marginLeft2, marginBottom: marginBottom2 } = dimensions;\n const { insetLeft, insetRight } = this;\n return create4(\"svg:g\", context).call(applyIndirectStyles, this, dimensions, context).call(applyTransform, this, { y: Y3 && y3 }, 0, offset).call(\n (g) => g.selectAll().data(index2).enter().append(\"line\").call(applyDirectStyles, this).attr(\"x1\", X13 && !isCollapsed(x3) ? (i) => X13[i] + insetLeft : marginLeft2 + insetLeft).attr(\n \"x2\",\n X23 && !isCollapsed(x3) ? x3.bandwidth ? (i) => X23[i] + x3.bandwidth() - insetRight : (i) => X23[i] - insetRight : width2 - marginRight2 - insetRight\n ).attr(\"y1\", Y3 ? (i) => Y3[i] : (marginTop2 + height2 - marginBottom2) / 2).attr(\"y2\", Y3 ? (i) => Y3[i] : (marginTop2 + height2 - marginBottom2) / 2).call(applyChannelStyles, this, channels).call(applyMarkers, this, channels, context)\n ).node();\n }\n};\nfunction ruleX(data, options) {\n let { x: x3 = identity7, y: y3, y1: y12, y2: y22, ...rest } = maybeIntervalY(options);\n [y12, y22] = maybeOptionalZero(y3, y12, y22);\n return new RuleX(data, { ...rest, x: x3, y1: y12, y2: y22 });\n}\nfunction ruleY(data, options) {\n let { y: y3 = identity7, x: x3, x1: x12, x2: x22, ...rest } = maybeIntervalX(options);\n [x12, x22] = maybeOptionalZero(x3, x12, x22);\n return new RuleY(data, { ...rest, y: y3, x1: x12, x2: x22 });\n}\nfunction maybeOptionalZero(x3, x12, x22) {\n if (x3 == null) {\n if (x12 === void 0) {\n if (x22 !== void 0) return [0, x22];\n } else {\n if (x22 === void 0) return [0, x12];\n }\n } else if (x12 === void 0) {\n return x22 === void 0 ? [0, x3] : [x3, x22];\n } else if (x22 === void 0) {\n return [x3, x12];\n }\n return [x12, x22];\n}\n\n// ../../node_modules/@observablehq/plot/src/template.js\nfunction template(strings, ...parts) {\n let n = parts.length;\n for (let j = 0, copy4 = true; j < n; ++j) {\n if (typeof parts[j] !== \"function\") {\n if (copy4) {\n strings = strings.slice();\n copy4 = false;\n }\n strings.splice(j, 2, strings[j] + parts[j] + strings[j + 1]);\n parts.splice(j, 1);\n --j, --n;\n }\n }\n return (i) => {\n let s2 = strings[0];\n for (let j = 0; j < n; ++j) {\n s2 += parts[j](i) + strings[j + 1];\n }\n return s2;\n };\n}\n\n// ../../node_modules/@observablehq/plot/src/marks/text.js\nvar defaults2 = {\n ariaLabel: \"text\",\n strokeLinejoin: \"round\",\n strokeWidth: 3,\n paintOrder: \"stroke\"\n};\nvar softHyphen = \"\\xAD\";\nvar Text = class extends Mark {\n constructor(data, options = {}) {\n const {\n x: x3,\n y: y3,\n text: text3 = isIterable(data) && isTextual(data) ? identity7 : indexOf,\n frameAnchor,\n textAnchor = /right$/i.test(frameAnchor) ? \"end\" : /left$/i.test(frameAnchor) ? \"start\" : \"middle\",\n lineAnchor = /^top/i.test(frameAnchor) ? \"top\" : /^bottom/i.test(frameAnchor) ? \"bottom\" : \"middle\",\n lineHeight = 1,\n lineWidth = Infinity,\n textOverflow,\n monospace,\n fontFamily = monospace ? \"ui-monospace, monospace\" : void 0,\n fontSize,\n fontStyle,\n fontVariant,\n fontWeight,\n rotate\n } = options;\n const [vrotate, crotate] = maybeNumberChannel(rotate, 0);\n const [vfontSize, cfontSize] = maybeFontSizeChannel(fontSize);\n super(\n data,\n {\n x: { value: x3, scale: \"x\", optional: true },\n y: { value: y3, scale: \"y\", optional: true },\n fontSize: { value: vfontSize, optional: true },\n rotate: { value: numberChannel(vrotate), optional: true },\n text: { value: text3, filter: nonempty, optional: true }\n },\n options,\n defaults2\n );\n this.rotate = crotate;\n this.textAnchor = impliedString(textAnchor, \"middle\");\n this.lineAnchor = keyword(lineAnchor, \"lineAnchor\", [\"top\", \"middle\", \"bottom\"]);\n this.lineHeight = +lineHeight;\n this.lineWidth = +lineWidth;\n this.textOverflow = maybeTextOverflow(textOverflow);\n this.monospace = !!monospace;\n this.fontFamily = string(fontFamily);\n this.fontSize = cfontSize;\n this.fontStyle = string(fontStyle);\n this.fontVariant = string(fontVariant);\n this.fontWeight = string(fontWeight);\n this.frameAnchor = maybeFrameAnchor(frameAnchor);\n if (!(this.lineWidth >= 0)) throw new Error(`invalid lineWidth: ${lineWidth}`);\n this.splitLines = splitter2(this);\n this.clipLine = clipper(this);\n }\n render(index2, scales2, channels, dimensions, context) {\n const { x: x3, y: y3 } = scales2;\n const { x: X3, y: Y3, rotate: R, text: T, title: TL, fontSize: FS } = channels;\n const { rotate } = this;\n const [cx, cy] = applyFrameAnchor(this, dimensions);\n return create4(\"svg:g\", context).call(applyIndirectStyles, this, dimensions, context).call(applyIndirectTextStyles, this, T, dimensions).call(applyTransform, this, { x: X3 && x3, y: Y3 && y3 }).call(\n (g) => g.selectAll().data(index2).enter().append(\"text\").call(applyDirectStyles, this).call(applyMultilineText, this, T, TL).attr(\n \"transform\",\n template`translate(${X3 ? (i) => X3[i] : cx},${Y3 ? (i) => Y3[i] : cy})${R ? (i) => ` rotate(${R[i]})` : rotate ? ` rotate(${rotate})` : ``}`\n ).call(applyAttr, \"font-size\", FS && ((i) => FS[i])).call(applyChannelStyles, this, channels)\n ).node();\n }\n};\nfunction maybeTextOverflow(textOverflow) {\n return textOverflow == null ? null : keyword(textOverflow, \"textOverflow\", [\n \"clip\",\n // shorthand for clip-end\n \"ellipsis\",\n // … ellipsis-end\n \"clip-start\",\n \"clip-end\",\n \"ellipsis-start\",\n \"ellipsis-middle\",\n \"ellipsis-end\"\n ]).replace(/^(clip|ellipsis)$/, \"$1-end\");\n}\nfunction applyMultilineText(selection2, mark2, T, TL) {\n if (!T) return;\n const { lineAnchor, lineHeight, textOverflow, splitLines, clipLine } = mark2;\n selection2.each(function(i) {\n const lines = splitLines(formatDefault(T[i]) ?? \"\").map(clipLine);\n const n = lines.length;\n const y3 = lineAnchor === \"top\" ? 0.71 : lineAnchor === \"bottom\" ? 1 - n : (164 - n * 100) / 200;\n if (n > 1) {\n let m = 0;\n for (let i2 = 0; i2 < n; ++i2) {\n ++m;\n if (!lines[i2]) continue;\n const tspan = this.ownerDocument.createElementNS(namespaces_default.svg, \"tspan\");\n tspan.setAttribute(\"x\", 0);\n if (i2 === m - 1) tspan.setAttribute(\"y\", `${(y3 + i2) * lineHeight}em`);\n else tspan.setAttribute(\"dy\", `${m * lineHeight}em`);\n tspan.textContent = lines[i2];\n this.appendChild(tspan);\n m = 0;\n }\n } else {\n if (y3) this.setAttribute(\"y\", `${y3 * lineHeight}em`);\n this.textContent = lines[0];\n }\n if (textOverflow && !TL && lines[0] !== T[i]) {\n const title = this.ownerDocument.createElementNS(namespaces_default.svg, \"title\");\n title.textContent = T[i];\n this.appendChild(title);\n }\n });\n}\nfunction text(data, { x: x3, y: y3, ...options } = {}) {\n if (options.frameAnchor === void 0) [x3, y3] = maybeTuple(x3, y3);\n return new Text(data, { ...options, x: x3, y: y3 });\n}\nfunction textX(data, { x: x3 = identity7, ...options } = {}) {\n return new Text(data, maybeIntervalMidY({ ...options, x: x3 }));\n}\nfunction textY(data, { y: y3 = identity7, ...options } = {}) {\n return new Text(data, maybeIntervalMidX({ ...options, y: y3 }));\n}\nfunction applyIndirectTextStyles(selection2, mark2, T) {\n applyAttr(selection2, \"text-anchor\", mark2.textAnchor);\n applyAttr(selection2, \"font-family\", mark2.fontFamily);\n applyAttr(selection2, \"font-size\", mark2.fontSize);\n applyAttr(selection2, \"font-style\", mark2.fontStyle);\n applyAttr(selection2, \"font-variant\", mark2.fontVariant === void 0 ? inferFontVariant2(T) : mark2.fontVariant);\n applyAttr(selection2, \"font-weight\", mark2.fontWeight);\n}\nfunction inferFontVariant2(T) {\n return T && (isNumeric(T) || isTemporal(T)) ? \"tabular-nums\" : void 0;\n}\nvar fontSizes = /* @__PURE__ */ new Set([\n // global keywords\n \"inherit\",\n \"initial\",\n \"revert\",\n \"unset\",\n // absolute keywords\n \"xx-small\",\n \"x-small\",\n \"small\",\n \"medium\",\n \"large\",\n \"x-large\",\n \"xx-large\",\n \"xxx-large\",\n // relative keywords\n \"larger\",\n \"smaller\"\n]);\nfunction maybeFontSizeChannel(fontSize) {\n if (fontSize == null || typeof fontSize === \"number\") return [void 0, fontSize];\n if (typeof fontSize !== \"string\") return [fontSize, void 0];\n fontSize = fontSize.trim().toLowerCase();\n return fontSizes.has(fontSize) || /^[+-]?\\d*\\.?\\d+(e[+-]?\\d+)?(\\w*|%)$/.test(fontSize) ? [void 0, fontSize] : [fontSize, void 0];\n}\nfunction lineWrap(input3, maxWidth, widthof2) {\n const lines = [];\n let lineStart, lineEnd = 0;\n for (const [wordStart, wordEnd, required2] of lineBreaks(input3)) {\n if (lineStart === void 0) lineStart = wordStart;\n if (lineEnd > lineStart && widthof2(input3, lineStart, wordEnd) > maxWidth) {\n lines.push(input3.slice(lineStart, lineEnd) + (input3[lineEnd - 1] === softHyphen ? \"-\" : \"\"));\n lineStart = wordStart;\n }\n if (required2) {\n lines.push(input3.slice(lineStart, wordEnd));\n lineStart = void 0;\n continue;\n }\n lineEnd = wordEnd;\n }\n return lines;\n}\nfunction* lineBreaks(input3) {\n let i = 0, j = 0;\n const n = input3.length;\n while (j < n) {\n let k2 = 1;\n switch (input3[j]) {\n case softHyphen:\n case \"-\":\n ++j;\n yield [i, j, false];\n i = j;\n break;\n case \" \":\n yield [i, j, false];\n while (input3[++j] === \" \") ;\n i = j;\n break;\n case \"\\r\":\n if (input3[j + 1] === \"\\n\") ++k2;\n // falls through\n case \"\\n\":\n yield [i, j, true];\n j += k2;\n i = j;\n break;\n default:\n ++j;\n break;\n }\n }\n yield [i, j, true];\n}\nvar defaultWidthMap = {\n a: 56,\n b: 63,\n c: 57,\n d: 63,\n e: 58,\n f: 37,\n g: 62,\n h: 60,\n i: 26,\n j: 26,\n k: 55,\n l: 26,\n m: 88,\n n: 60,\n o: 60,\n p: 62,\n q: 62,\n r: 39,\n s: 54,\n t: 38,\n u: 60,\n v: 55,\n w: 79,\n x: 54,\n y: 55,\n z: 55,\n A: 69,\n B: 67,\n C: 73,\n D: 74,\n E: 61,\n F: 58,\n G: 76,\n H: 75,\n I: 28,\n J: 55,\n K: 67,\n L: 58,\n M: 89,\n N: 75,\n O: 78,\n P: 65,\n Q: 78,\n R: 67,\n S: 65,\n T: 65,\n U: 75,\n V: 69,\n W: 98,\n X: 69,\n Y: 67,\n Z: 67,\n 0: 64,\n 1: 48,\n 2: 62,\n 3: 64,\n 4: 66,\n 5: 63,\n 6: 65,\n 7: 58,\n 8: 65,\n 9: 65,\n \" \": 29,\n \"!\": 32,\n '\"': 49,\n \"'\": 31,\n \"(\": 39,\n \")\": 39,\n \",\": 31,\n \"-\": 48,\n \".\": 31,\n \"/\": 32,\n \":\": 31,\n \";\": 31,\n \"?\": 52,\n \"\\u2018\": 31,\n \"\\u2019\": 31,\n \"\\u201C\": 47,\n \"\\u201D\": 47,\n \"\\u2026\": 82\n};\nfunction defaultWidth(text3, start2 = 0, end = text3.length) {\n let sum4 = 0;\n for (let i = start2; i < end; i = readCharacter(text3, i)) {\n sum4 += defaultWidthMap[text3[i]] ?? (isPictographic(text3, i) ? 120 : defaultWidthMap.e);\n }\n return sum4;\n}\nfunction monospaceWidth(text3, start2 = 0, end = text3.length) {\n let sum4 = 0;\n for (let i = start2; i < end; i = readCharacter(text3, i)) {\n sum4 += isPictographic(text3, i) ? 126 : 63;\n }\n return sum4;\n}\nfunction splitter2({ monospace, lineWidth, textOverflow }) {\n if (textOverflow != null || lineWidth == Infinity) return (text3) => text3.split(/\\r\\n?|\\n/g);\n const widthof2 = monospace ? monospaceWidth : defaultWidth;\n const maxWidth = lineWidth * 100;\n return (text3) => lineWrap(text3, maxWidth, widthof2);\n}\nfunction clipper({ monospace, lineWidth, textOverflow }) {\n if (textOverflow == null || lineWidth == Infinity) return (text3) => text3;\n const widthof2 = monospace ? monospaceWidth : defaultWidth;\n const maxWidth = lineWidth * 100;\n switch (textOverflow) {\n case \"clip-start\":\n return (text3) => clipStart(text3, maxWidth, widthof2, \"\");\n case \"clip-end\":\n return (text3) => clipEnd(text3, maxWidth, widthof2, \"\");\n case \"ellipsis-start\":\n return (text3) => clipStart(text3, maxWidth, widthof2, ellipsis);\n case \"ellipsis-middle\":\n return (text3) => clipMiddle(text3, maxWidth, widthof2, ellipsis);\n case \"ellipsis-end\":\n return (text3) => clipEnd(text3, maxWidth, widthof2, ellipsis);\n }\n}\nvar ellipsis = \"\\u2026\";\nfunction cut(text3, width2, widthof2, inset2) {\n const I = [];\n let w = 0;\n for (let i = 0, j = 0, n = text3.length; i < n; i = j) {\n j = readCharacter(text3, i);\n const l = widthof2(text3, i, j);\n if (w + l > width2) {\n w += inset2;\n while (w > width2 && i > 0) j = i, i = I.pop(), w -= widthof2(text3, i, j);\n return [i, width2 - w];\n }\n w += l;\n I.push(i);\n }\n return [-1, 0];\n}\nfunction clipEnd(text3, width2, widthof2, ellipsis2) {\n text3 = text3.trim();\n const e = widthof2(ellipsis2);\n const [i] = cut(text3, width2, widthof2, e);\n return i < 0 ? text3 : text3.slice(0, i).trimEnd() + ellipsis2;\n}\nfunction clipMiddle(text3, width2, widthof2, ellipsis2) {\n text3 = text3.trim();\n const w = widthof2(text3);\n if (w <= width2) return text3;\n const e = widthof2(ellipsis2) / 2;\n const [i, ei] = cut(text3, width2 / 2, widthof2, e);\n const [j] = cut(text3, w - width2 / 2 - ei + e, widthof2, -e);\n return j < 0 ? ellipsis2 : text3.slice(0, i).trimEnd() + ellipsis2 + text3.slice(readCharacter(text3, j)).trimStart();\n}\nfunction clipStart(text3, width2, widthof2, ellipsis2) {\n text3 = text3.trim();\n const w = widthof2(text3);\n if (w <= width2) return text3;\n const e = widthof2(ellipsis2);\n const [j] = cut(text3, w - width2 + e, widthof2, -e);\n return j < 0 ? ellipsis2 : ellipsis2 + text3.slice(readCharacter(text3, j)).trimStart();\n}\nvar reCombiner = /[\\p{Combining_Mark}\\p{Emoji_Modifier}]+/uy;\nvar rePictographic = /\\p{Extended_Pictographic}/uy;\nfunction readCharacter(text3, i) {\n i += isSurrogatePair(text3, i) ? 2 : 1;\n if (isCombiner(text3, i)) i = reCombiner.lastIndex;\n if (isZeroWidthJoiner(text3, i)) return readCharacter(text3, i + 1);\n return i;\n}\nfunction isAscii(text3, i) {\n return text3.charCodeAt(i) < 128;\n}\nfunction isSurrogatePair(text3, i) {\n const hi = text3.charCodeAt(i);\n if (hi >= 55296 && hi < 56320) {\n const lo = text3.charCodeAt(i + 1);\n return lo >= 56320 && lo < 57344;\n }\n return false;\n}\nfunction isZeroWidthJoiner(text3, i) {\n return text3.charCodeAt(i) === 8205;\n}\nfunction isCombiner(text3, i) {\n return isAscii(text3, i) ? false : (reCombiner.lastIndex = i, reCombiner.test(text3));\n}\nfunction isPictographic(text3, i) {\n return isAscii(text3, i) ? false : (rePictographic.lastIndex = i, rePictographic.test(text3));\n}\n\n// ../../node_modules/@observablehq/plot/src/marks/vector.js\nvar defaults3 = {\n ariaLabel: \"vector\",\n fill: \"none\",\n stroke: \"currentColor\",\n strokeWidth: 1.5,\n strokeLinejoin: \"round\",\n strokeLinecap: \"round\"\n};\nvar defaultRadius = 3.5;\nvar wingRatio = defaultRadius * 5;\nvar shapeArrow = {\n draw(context, l, r) {\n const wing = l * r / wingRatio;\n context.moveTo(0, 0);\n context.lineTo(0, -l);\n context.moveTo(-wing, wing - l);\n context.lineTo(0, -l);\n context.lineTo(wing, wing - l);\n }\n};\nvar shapeSpike = {\n draw(context, l, r) {\n context.moveTo(-r, 0);\n context.lineTo(0, -l);\n context.lineTo(r, 0);\n }\n};\nvar shapes = /* @__PURE__ */ new Map([\n [\"arrow\", shapeArrow],\n [\"spike\", shapeSpike]\n]);\nfunction isShapeObject(value) {\n return value && typeof value.draw === \"function\";\n}\nfunction maybeShape(shape) {\n if (isShapeObject(shape)) return shape;\n const value = shapes.get(`${shape}`.toLowerCase());\n if (value) return value;\n throw new Error(`invalid shape: ${shape}`);\n}\nvar Vector = class extends Mark {\n constructor(data, options = {}) {\n const { x: x3, y: y3, r = defaultRadius, length: length4, rotate, shape = shapeArrow, anchor = \"middle\", frameAnchor } = options;\n const [vl, cl] = maybeNumberChannel(length4, 12);\n const [vr, cr] = maybeNumberChannel(rotate, 0);\n super(\n data,\n {\n x: { value: x3, scale: \"x\", optional: true },\n y: { value: y3, scale: \"y\", optional: true },\n length: { value: vl, scale: \"length\", optional: true },\n rotate: { value: vr, optional: true }\n },\n options,\n defaults3\n );\n this.r = +r;\n this.length = cl;\n this.rotate = cr;\n this.shape = maybeShape(shape);\n this.anchor = keyword(anchor, \"anchor\", [\"start\", \"middle\", \"end\"]);\n this.frameAnchor = maybeFrameAnchor(frameAnchor);\n }\n render(index2, scales2, channels, dimensions, context) {\n const { x: x3, y: y3 } = scales2;\n const { x: X3, y: Y3, length: L, rotate: A5 } = channels;\n const { length: length4, rotate, anchor, shape, r } = this;\n const [cx, cy] = applyFrameAnchor(this, dimensions);\n return create4(\"svg:g\", context).call(applyIndirectStyles, this, dimensions, context).call(applyTransform, this, { x: X3 && x3, y: Y3 && y3 }).call(\n (g) => g.selectAll().data(index2).enter().append(\"path\").call(applyDirectStyles, this).attr(\n \"transform\",\n template`translate(${X3 ? (i) => X3[i] : cx},${Y3 ? (i) => Y3[i] : cy})${A5 ? (i) => ` rotate(${A5[i]})` : rotate ? ` rotate(${rotate})` : ``}${anchor === \"start\" ? `` : anchor === \"end\" ? L ? (i) => ` translate(0,${L[i]})` : ` translate(0,${length4})` : L ? (i) => ` translate(0,${L[i] / 2})` : ` translate(0,${length4 / 2})`}`\n ).attr(\n \"d\",\n L ? (i) => {\n const p = pathRound();\n shape.draw(p, L[i], r);\n return p;\n } : (() => {\n const p = pathRound();\n shape.draw(p, length4, r);\n return p;\n })()\n ).call(applyChannelStyles, this, channels)\n ).node();\n }\n};\nfunction vector(data, options = {}) {\n let { x: x3, y: y3, ...rest } = options;\n if (options.frameAnchor === void 0) [x3, y3] = maybeTuple(x3, y3);\n return new Vector(data, { ...rest, x: x3, y: y3 });\n}\nfunction vectorX(data, options = {}) {\n const { x: x3 = identity7, ...rest } = options;\n return new Vector(data, { ...rest, x: x3 });\n}\nfunction vectorY(data, options = {}) {\n const { y: y3 = identity7, ...rest } = options;\n return new Vector(data, { ...rest, y: y3 });\n}\nfunction spike(data, options = {}) {\n const {\n shape = shapeSpike,\n stroke = defaults3.stroke,\n strokeWidth = 1,\n fill = stroke,\n fillOpacity = 0.3,\n anchor = \"start\",\n ...rest\n } = options;\n return vector(data, { ...rest, shape, stroke, strokeWidth, fill, fillOpacity, anchor });\n}\n\n// ../../node_modules/@observablehq/plot/src/marks/axis.js\nfunction maybeData(data, options) {\n if (arguments.length < 2 && !isIterable(data)) options = data, data = null;\n if (options === void 0) options = {};\n return [data, options];\n}\nfunction maybeAnchor2({ anchor } = {}, anchors) {\n return anchor === void 0 ? anchors[0] : keyword(anchor, \"anchor\", anchors);\n}\nfunction anchorY2(options) {\n return maybeAnchor2(options, [\"left\", \"right\"]);\n}\nfunction anchorFy(options) {\n return maybeAnchor2(options, [\"right\", \"left\"]);\n}\nfunction anchorX2(options) {\n return maybeAnchor2(options, [\"bottom\", \"top\"]);\n}\nfunction anchorFx(options) {\n return maybeAnchor2(options, [\"top\", \"bottom\"]);\n}\nfunction axisY() {\n const [data, options] = maybeData(...arguments);\n return axisKy(\"y\", anchorY2(options), data, options);\n}\nfunction axisFy() {\n const [data, options] = maybeData(...arguments);\n return axisKy(\"fy\", anchorFy(options), data, options);\n}\nfunction axisX() {\n const [data, options] = maybeData(...arguments);\n return axisKx(\"x\", anchorX2(options), data, options);\n}\nfunction axisFx() {\n const [data, options] = maybeData(...arguments);\n return axisKx(\"fx\", anchorFx(options), data, options);\n}\nfunction axisKy(k2, anchor, data, {\n color: color3 = \"currentColor\",\n opacity: opacity2 = 1,\n stroke = color3,\n strokeOpacity = opacity2,\n strokeWidth = 1,\n fill = color3,\n fillOpacity = opacity2,\n textAnchor,\n textStroke,\n textStrokeOpacity,\n textStrokeWidth,\n tickSize = k2 === \"y\" ? 6 : 0,\n tickPadding,\n tickRotate,\n x: x3,\n margin: margin2,\n marginTop: marginTop2 = margin2 === void 0 ? 20 : margin2,\n marginRight: marginRight2 = margin2 === void 0 ? anchor === \"right\" ? 40 : 0 : margin2,\n marginBottom: marginBottom2 = margin2 === void 0 ? 20 : margin2,\n marginLeft: marginLeft2 = margin2 === void 0 ? anchor === \"left\" ? 40 : 0 : margin2,\n label: label2,\n labelAnchor,\n labelArrow,\n labelOffset,\n ...options\n}) {\n tickSize = number5(tickSize);\n tickPadding = number5(tickPadding);\n tickRotate = number5(tickRotate);\n if (labelAnchor !== void 0) labelAnchor = keyword(labelAnchor, \"labelAnchor\", [\"center\", \"top\", \"bottom\"]);\n labelArrow = maybeLabelArrow(labelArrow);\n return marks(\n tickSize && !isNoneish(stroke) ? axisTickKy(k2, anchor, data, {\n stroke,\n strokeOpacity,\n strokeWidth,\n tickSize,\n tickPadding,\n tickRotate,\n x: x3,\n ...options\n }) : null,\n !isNoneish(fill) ? axisTextKy(k2, anchor, data, {\n fill,\n fillOpacity,\n stroke: textStroke,\n strokeOpacity: textStrokeOpacity,\n strokeWidth: textStrokeWidth,\n textAnchor,\n tickSize,\n tickPadding,\n tickRotate,\n x: x3,\n marginTop: marginTop2,\n marginRight: marginRight2,\n marginBottom: marginBottom2,\n marginLeft: marginLeft2,\n ...options\n }) : null,\n !isNoneish(fill) && label2 !== null ? text(\n [],\n labelOptions({ fill, fillOpacity, ...options }, function(data2, facets, channels, scales2, dimensions) {\n const scale3 = scales2[k2];\n const { marginTop: marginTop3, marginRight: marginRight3, marginBottom: marginBottom3, marginLeft: marginLeft3 } = k2 === \"y\" && dimensions.inset || dimensions;\n const cla = labelAnchor ?? (scale3.bandwidth ? \"center\" : \"top\");\n const clo = labelOffset ?? (anchor === \"right\" ? marginRight3 : marginLeft3) - 3;\n if (cla === \"center\") {\n this.textAnchor = void 0;\n this.lineAnchor = anchor === \"right\" ? \"bottom\" : \"top\";\n this.frameAnchor = anchor;\n this.rotate = -90;\n } else {\n this.textAnchor = anchor === \"right\" ? \"end\" : \"start\";\n this.lineAnchor = cla;\n this.frameAnchor = `${cla}-${anchor}`;\n this.rotate = 0;\n }\n this.dy = cla === \"top\" ? 3 - marginTop3 : cla === \"bottom\" ? marginBottom3 - 3 : 0;\n this.dx = anchor === \"right\" ? clo : -clo;\n this.ariaLabel = `${k2}-axis label`;\n return {\n facets: [[0]],\n channels: { text: { value: [formatAxisLabel(k2, scale3, { anchor, label: label2, labelAnchor: cla, labelArrow })] } }\n };\n })\n ) : null\n );\n}\nfunction axisKx(k2, anchor, data, {\n color: color3 = \"currentColor\",\n opacity: opacity2 = 1,\n stroke = color3,\n strokeOpacity = opacity2,\n strokeWidth = 1,\n fill = color3,\n fillOpacity = opacity2,\n textAnchor,\n textStroke,\n textStrokeOpacity,\n textStrokeWidth,\n tickSize = k2 === \"x\" ? 6 : 0,\n tickPadding,\n tickRotate,\n y: y3,\n margin: margin2,\n marginTop: marginTop2 = margin2 === void 0 ? anchor === \"top\" ? 30 : 0 : margin2,\n marginRight: marginRight2 = margin2 === void 0 ? 20 : margin2,\n marginBottom: marginBottom2 = margin2 === void 0 ? anchor === \"bottom\" ? 30 : 0 : margin2,\n marginLeft: marginLeft2 = margin2 === void 0 ? 20 : margin2,\n label: label2,\n labelAnchor,\n labelArrow,\n labelOffset,\n ...options\n}) {\n tickSize = number5(tickSize);\n tickPadding = number5(tickPadding);\n tickRotate = number5(tickRotate);\n if (labelAnchor !== void 0) labelAnchor = keyword(labelAnchor, \"labelAnchor\", [\"center\", \"left\", \"right\"]);\n labelArrow = maybeLabelArrow(labelArrow);\n return marks(\n tickSize && !isNoneish(stroke) ? axisTickKx(k2, anchor, data, {\n stroke,\n strokeOpacity,\n strokeWidth,\n tickSize,\n tickPadding,\n tickRotate,\n y: y3,\n ...options\n }) : null,\n !isNoneish(fill) ? axisTextKx(k2, anchor, data, {\n fill,\n fillOpacity,\n stroke: textStroke,\n strokeOpacity: textStrokeOpacity,\n strokeWidth: textStrokeWidth,\n textAnchor,\n tickSize,\n tickPadding,\n tickRotate,\n y: y3,\n marginTop: marginTop2,\n marginRight: marginRight2,\n marginBottom: marginBottom2,\n marginLeft: marginLeft2,\n ...options\n }) : null,\n !isNoneish(fill) && label2 !== null ? text(\n [],\n labelOptions({ fill, fillOpacity, ...options }, function(data2, facets, channels, scales2, dimensions) {\n const scale3 = scales2[k2];\n const { marginTop: marginTop3, marginRight: marginRight3, marginBottom: marginBottom3, marginLeft: marginLeft3 } = k2 === \"x\" && dimensions.inset || dimensions;\n const cla = labelAnchor ?? (scale3.bandwidth ? \"center\" : \"right\");\n const clo = labelOffset ?? (anchor === \"top\" ? marginTop3 : marginBottom3) - 3;\n if (cla === \"center\") {\n this.frameAnchor = anchor;\n this.textAnchor = void 0;\n } else {\n this.frameAnchor = `${anchor}-${cla}`;\n this.textAnchor = cla === \"right\" ? \"end\" : \"start\";\n }\n this.lineAnchor = anchor;\n this.dy = anchor === \"top\" ? -clo : clo;\n this.dx = cla === \"right\" ? marginRight3 - 3 : cla === \"left\" ? 3 - marginLeft3 : 0;\n this.ariaLabel = `${k2}-axis label`;\n return {\n facets: [[0]],\n channels: { text: { value: [formatAxisLabel(k2, scale3, { anchor, label: label2, labelAnchor: cla, labelArrow })] } }\n };\n })\n ) : null\n );\n}\nfunction axisTickKy(k2, anchor, data, {\n strokeWidth = 1,\n strokeLinecap = null,\n strokeLinejoin = null,\n facetAnchor = anchor + (k2 === \"y\" ? \"-empty\" : \"\"),\n frameAnchor = anchor,\n tickSize,\n inset: inset2 = 0,\n insetLeft = inset2,\n insetRight = inset2,\n dx = 0,\n y: y3 = k2 === \"y\" ? void 0 : null,\n ...options\n}) {\n return axisMark(\n vectorY,\n k2,\n data,\n {\n ariaLabel: `${k2}-axis tick`,\n ariaHidden: true\n },\n {\n strokeWidth,\n strokeLinecap,\n strokeLinejoin,\n facetAnchor,\n frameAnchor,\n y: y3,\n ...options,\n dx: anchor === \"left\" ? +dx - offset + +insetLeft : +dx + offset - insetRight,\n anchor: \"start\",\n length: tickSize,\n shape: anchor === \"left\" ? shapeTickLeft : shapeTickRight\n }\n );\n}\nfunction axisTickKx(k2, anchor, data, {\n strokeWidth = 1,\n strokeLinecap = null,\n strokeLinejoin = null,\n facetAnchor = anchor + (k2 === \"x\" ? \"-empty\" : \"\"),\n frameAnchor = anchor,\n tickSize,\n inset: inset2 = 0,\n insetTop = inset2,\n insetBottom = inset2,\n dy = 0,\n x: x3 = k2 === \"x\" ? void 0 : null,\n ...options\n}) {\n return axisMark(\n vectorX,\n k2,\n data,\n {\n ariaLabel: `${k2}-axis tick`,\n ariaHidden: true\n },\n {\n strokeWidth,\n strokeLinejoin,\n strokeLinecap,\n facetAnchor,\n frameAnchor,\n x: x3,\n ...options,\n dy: anchor === \"bottom\" ? +dy - offset - insetBottom : +dy + offset + +insetTop,\n anchor: \"start\",\n length: tickSize,\n shape: anchor === \"bottom\" ? shapeTickBottom : shapeTickTop\n }\n );\n}\nfunction axisTextKy(k2, anchor, data, {\n facetAnchor = anchor + (k2 === \"y\" ? \"-empty\" : \"\"),\n frameAnchor = anchor,\n tickSize,\n tickRotate = 0,\n tickPadding = Math.max(3, 9 - tickSize) + (Math.abs(tickRotate) > 60 ? 4 * Math.cos(tickRotate * radians3) : 0),\n text: text3,\n textAnchor = Math.abs(tickRotate) > 60 ? \"middle\" : anchor === \"left\" ? \"end\" : \"start\",\n lineAnchor = tickRotate > 60 ? \"top\" : tickRotate < -60 ? \"bottom\" : \"middle\",\n fontVariant,\n inset: inset2 = 0,\n insetLeft = inset2,\n insetRight = inset2,\n dx = 0,\n y: y3 = k2 === \"y\" ? void 0 : null,\n ...options\n}) {\n return axisMark(\n textY,\n k2,\n data,\n { ariaLabel: `${k2}-axis tick label` },\n {\n facetAnchor,\n frameAnchor,\n text: text3,\n textAnchor,\n lineAnchor,\n fontVariant,\n rotate: tickRotate,\n y: y3,\n ...options,\n dx: anchor === \"left\" ? +dx - tickSize - tickPadding + +insetLeft : +dx + +tickSize + +tickPadding - insetRight\n },\n function(scale3, data2, ticks2, tickFormat2, channels) {\n if (fontVariant === void 0) this.fontVariant = inferFontVariant3(scale3);\n if (text3 === void 0) channels.text = inferTextChannel(scale3, data2, ticks2, tickFormat2, anchor);\n }\n );\n}\nfunction axisTextKx(k2, anchor, data, {\n facetAnchor = anchor + (k2 === \"x\" ? \"-empty\" : \"\"),\n frameAnchor = anchor,\n tickSize,\n tickRotate = 0,\n tickPadding = Math.max(3, 9 - tickSize) + (Math.abs(tickRotate) >= 10 ? 4 * Math.cos(tickRotate * radians3) : 0),\n text: text3,\n textAnchor = Math.abs(tickRotate) >= 10 ? tickRotate < 0 ^ anchor === \"bottom\" ? \"start\" : \"end\" : \"middle\",\n lineAnchor = Math.abs(tickRotate) >= 10 ? \"middle\" : anchor === \"bottom\" ? \"top\" : \"bottom\",\n fontVariant,\n inset: inset2 = 0,\n insetTop = inset2,\n insetBottom = inset2,\n dy = 0,\n x: x3 = k2 === \"x\" ? void 0 : null,\n ...options\n}) {\n return axisMark(\n textX,\n k2,\n data,\n { ariaLabel: `${k2}-axis tick label` },\n {\n facetAnchor,\n frameAnchor,\n text: text3 === void 0 ? null : text3,\n textAnchor,\n lineAnchor,\n fontVariant,\n rotate: tickRotate,\n x: x3,\n ...options,\n dy: anchor === \"bottom\" ? +dy + +tickSize + +tickPadding - insetBottom : +dy - tickSize - tickPadding + +insetTop\n },\n function(scale3, data2, ticks2, tickFormat2, channels) {\n if (fontVariant === void 0) this.fontVariant = inferFontVariant3(scale3);\n if (text3 === void 0) channels.text = inferTextChannel(scale3, data2, ticks2, tickFormat2, anchor);\n }\n );\n}\nfunction gridY() {\n const [data, options] = maybeData(...arguments);\n return gridKy(\"y\", anchorY2(options), data, options);\n}\nfunction gridFy() {\n const [data, options] = maybeData(...arguments);\n return gridKy(\"fy\", anchorFy(options), data, options);\n}\nfunction gridX() {\n const [data, options] = maybeData(...arguments);\n return gridKx(\"x\", anchorX2(options), data, options);\n}\nfunction gridFx() {\n const [data, options] = maybeData(...arguments);\n return gridKx(\"fx\", anchorFx(options), data, options);\n}\nfunction gridKy(k2, anchor, data, {\n y: y3 = k2 === \"y\" ? void 0 : null,\n x: x3 = null,\n x1: x12 = anchor === \"left\" ? x3 : null,\n x2: x22 = anchor === \"right\" ? x3 : null,\n ...options\n}) {\n return axisMark(ruleY, k2, data, { ariaLabel: `${k2}-grid`, ariaHidden: true }, { y: y3, x1: x12, x2: x22, ...gridDefaults(options) });\n}\nfunction gridKx(k2, anchor, data, {\n x: x3 = k2 === \"x\" ? void 0 : null,\n y: y3 = null,\n y1: y12 = anchor === \"top\" ? y3 : null,\n y2: y22 = anchor === \"bottom\" ? y3 : null,\n ...options\n}) {\n return axisMark(ruleX, k2, data, { ariaLabel: `${k2}-grid`, ariaHidden: true }, { x: x3, y1: y12, y2: y22, ...gridDefaults(options) });\n}\nfunction gridDefaults({\n color: color3 = \"currentColor\",\n opacity: opacity2 = 0.1,\n stroke = color3,\n strokeOpacity = opacity2,\n strokeWidth = 1,\n ...options\n}) {\n return { stroke, strokeOpacity, strokeWidth, ...options };\n}\nfunction labelOptions({\n fill,\n fillOpacity,\n fontFamily,\n fontSize,\n fontStyle,\n fontVariant,\n fontWeight,\n monospace,\n pointerEvents,\n shapeRendering,\n clip = false\n}, initializer2) {\n [, fill] = maybeColorChannel(fill);\n [, fillOpacity] = maybeNumberChannel(fillOpacity);\n return {\n facet: \"super\",\n x: null,\n y: null,\n fill,\n fillOpacity,\n fontFamily,\n fontSize,\n fontStyle,\n fontVariant,\n fontWeight,\n monospace,\n pointerEvents,\n shapeRendering,\n clip,\n initializer: initializer2\n };\n}\nfunction axisMark(mark2, k2, data, properties, options, initialize) {\n let channels;\n function axisInitializer(data2, facets, _channels, scales2, dimensions, context) {\n const initializeFacets = data2 == null && (k2 === \"fx\" || k2 === \"fy\");\n const { [k2]: scale3 } = scales2;\n if (!scale3) throw new Error(`missing scale: ${k2}`);\n const domain = scale3.domain();\n let { interval: interval3, ticks: ticks2, tickFormat: tickFormat2, tickSpacing = k2 === \"x\" ? 80 : 35 } = options;\n if (typeof ticks2 === \"string\" && hasTemporalDomain(scale3)) interval3 = ticks2, ticks2 = void 0;\n if (ticks2 === void 0) ticks2 = maybeRangeInterval(interval3, scale3.type) ?? inferTickCount(scale3, tickSpacing);\n if (data2 == null) {\n if (isIterable(ticks2)) {\n data2 = arrayify2(ticks2);\n } else if (isInterval(ticks2)) {\n data2 = inclusiveRange(ticks2, ...extent(domain));\n } else if (scale3.interval) {\n let interval4 = scale3.interval;\n if (scale3.ticks) {\n const [min5, max4] = extent(domain);\n const n = (max4 - min5) / interval4[intervalDuration];\n interval4 = generalizeTimeInterval(interval4, n / ticks2) ?? interval4;\n data2 = inclusiveRange(interval4, min5, max4);\n } else {\n data2 = domain;\n const n = data2.length;\n interval4 = generalizeTimeInterval(interval4, n / ticks2) ?? interval4;\n if (interval4 !== scale3.interval) data2 = inclusiveRange(interval4, ...extent(data2));\n }\n if (interval4 === scale3.interval) {\n const n = Math.round(data2.length / ticks2);\n if (n > 1) data2 = data2.filter((d, i) => i % n === 0);\n }\n } else if (scale3.ticks) {\n data2 = scale3.ticks(ticks2);\n } else {\n data2 = domain;\n }\n if (!scale3.ticks && data2.length && data2 !== domain) {\n const domainSet = new InternSet(domain);\n data2 = data2.filter((d) => domainSet.has(d));\n if (!data2.length) warn(`Warning: the ${k2}-axis ticks appear to not align with the scale domain, resulting in no ticks. Try different ticks?`);\n }\n if (k2 === \"y\" || k2 === \"x\") {\n facets = [range2(data2)];\n } else {\n channels[k2] = { scale: k2, value: identity7 };\n }\n }\n initialize?.call(this, scale3, data2, ticks2, tickFormat2, channels);\n const initializedChannels = Object.fromEntries(\n Object.entries(channels).map(([name2, channel]) => {\n return [name2, { ...channel, value: valueof(data2, channel.value) }];\n })\n );\n if (initializeFacets) facets = context.filterFacets(data2, initializedChannels);\n return { data: data2, facets, channels: initializedChannels };\n }\n const basicInitializer = initializer(options).initializer;\n const m = mark2(data, initializer({ ...options, initializer: axisInitializer }, basicInitializer));\n if (data == null) {\n channels = m.channels;\n m.channels = {};\n } else {\n channels = {};\n }\n if (properties !== void 0) Object.assign(m, properties);\n if (m.clip === void 0) m.clip = false;\n return m;\n}\nfunction inferTickCount(scale3, tickSpacing) {\n const [min5, max4] = extent(scale3.range());\n return (max4 - min5) / tickSpacing;\n}\nfunction inferTextChannel(scale3, data, ticks2, tickFormat2, anchor) {\n return { value: inferTickFormat(scale3, data, ticks2, tickFormat2, anchor) };\n}\nfunction inferTickFormat(scale3, data, ticks2, tickFormat2, anchor) {\n return typeof tickFormat2 === \"function\" && !(scale3.type === \"log\" && scale3.tickFormat) ? tickFormat2 : tickFormat2 === void 0 && data && isTemporal(data) ? inferTimeFormat(scale3.type, data, anchor) ?? formatDefault : scale3.tickFormat ? scale3.tickFormat(typeof ticks2 === \"number\" ? ticks2 : null, tickFormat2) : tickFormat2 === void 0 ? formatDefault : typeof tickFormat2 === \"string\" ? (isTemporal(scale3.domain()) ? utcFormat : format)(tickFormat2) : constant(tickFormat2);\n}\nfunction inclusiveRange(interval3, min5, max4) {\n return interval3.range(min5, interval3.offset(interval3.floor(max4)));\n}\nvar shapeTickBottom = {\n draw(context, l) {\n context.moveTo(0, 0);\n context.lineTo(0, l);\n }\n};\nvar shapeTickTop = {\n draw(context, l) {\n context.moveTo(0, 0);\n context.lineTo(0, -l);\n }\n};\nvar shapeTickLeft = {\n draw(context, l) {\n context.moveTo(0, 0);\n context.lineTo(-l, 0);\n }\n};\nvar shapeTickRight = {\n draw(context, l) {\n context.moveTo(0, 0);\n context.lineTo(l, 0);\n }\n};\nfunction inferFontVariant3(scale3) {\n return scale3.bandwidth && !scale3.interval ? void 0 : \"tabular-nums\";\n}\nfunction formatAxisLabel(k2, scale3, { anchor, label: label2 = scale3.label, labelAnchor, labelArrow } = {}) {\n if (label2 == null || label2.inferred && hasTemporalDomain(scale3) && /^(date|time|year)$/i.test(label2)) return;\n label2 = String(label2);\n if (labelArrow === \"auto\") labelArrow = (!scale3.bandwidth || scale3.interval) && !/[↑↓→←]/.test(label2);\n if (!labelArrow) return label2;\n if (labelArrow === true) {\n const order = inferScaleOrder(scale3);\n if (order)\n labelArrow = /x$/.test(k2) || labelAnchor === \"center\" ? /x$/.test(k2) === order < 0 ? \"left\" : \"right\" : order < 0 ? \"up\" : \"down\";\n }\n switch (labelArrow) {\n case \"left\":\n return `\\u2190 ${label2}`;\n case \"right\":\n return `${label2} \\u2192`;\n case \"up\":\n return anchor === \"right\" ? `${label2} \\u2191` : `\\u2191 ${label2}`;\n case \"down\":\n return anchor === \"right\" ? `${label2} \\u2193` : `\\u2193 ${label2}`;\n }\n return label2;\n}\nfunction maybeLabelArrow(labelArrow = \"auto\") {\n return isNoneish(labelArrow) ? false : typeof labelArrow === \"boolean\" ? labelArrow : keyword(labelArrow, \"labelArrow\", [\"auto\", \"up\", \"right\", \"down\", \"left\"]);\n}\nfunction hasTemporalDomain(scale3) {\n return isTemporal(scale3.domain());\n}\n\n// ../../node_modules/@observablehq/plot/src/legends/swatches.js\nfunction maybeScale(scale3, key) {\n if (key == null) return key;\n const s2 = scale3(key);\n if (!s2) throw new Error(`scale not found: ${key}`);\n return s2;\n}\nfunction legendSwatches(color3, { opacity: opacity2, ...options } = {}) {\n if (!isOrdinalScale(color3) && !isThresholdScale(color3))\n throw new Error(`swatches legend requires ordinal or threshold color scale (not ${color3.type})`);\n return legendItems(\n color3,\n options,\n (selection2, scale3, width2, height2) => selection2.append(\"svg\").attr(\"width\", width2).attr(\"height\", height2).attr(\"fill\", scale3.scale).attr(\"fill-opacity\", maybeNumberChannel(opacity2)[1]).append(\"rect\").attr(\"width\", \"100%\").attr(\"height\", \"100%\")\n );\n}\nfunction legendSymbols(symbol2, {\n fill = symbol2.hint?.fill !== void 0 ? symbol2.hint.fill : \"none\",\n fillOpacity = 1,\n stroke = symbol2.hint?.stroke !== void 0 ? symbol2.hint.stroke : isNoneish(fill) ? \"currentColor\" : \"none\",\n strokeOpacity = 1,\n strokeWidth = 1.5,\n r = 4.5,\n ...options\n} = {}, scale3) {\n const [vf, cf] = maybeColorChannel(fill);\n const [vs, cs] = maybeColorChannel(stroke);\n const sf = maybeScale(scale3, vf);\n const ss = maybeScale(scale3, vs);\n const size = r * r * Math.PI;\n fillOpacity = maybeNumberChannel(fillOpacity)[1];\n strokeOpacity = maybeNumberChannel(strokeOpacity)[1];\n strokeWidth = maybeNumberChannel(strokeWidth)[1];\n return legendItems(\n symbol2,\n options,\n (selection2, scale4, width2, height2) => selection2.append(\"svg\").attr(\"viewBox\", \"-8 -8 16 16\").attr(\"width\", width2).attr(\"height\", height2).attr(\"fill\", vf === \"color\" ? (d) => sf.scale(d) : cf).attr(\"fill-opacity\", fillOpacity).attr(\"stroke\", vs === \"color\" ? (d) => ss.scale(d) : cs).attr(\"stroke-opacity\", strokeOpacity).attr(\"stroke-width\", strokeWidth).append(\"path\").attr(\"d\", (d) => {\n const p = pathRound();\n symbol2.scale(d).draw(p, size);\n return p;\n })\n );\n}\nfunction legendItems(scale3, options = {}, swatch) {\n let {\n columns,\n tickFormat: tickFormat2,\n fontVariant = inferFontVariant(scale3),\n // TODO label,\n swatchSize = 15,\n swatchWidth = swatchSize,\n swatchHeight = swatchSize,\n marginLeft: marginLeft2 = 0,\n className,\n style: style2,\n width: width2\n } = options;\n const context = createContext(options);\n className = maybeClassName(className);\n tickFormat2 = inferTickFormat(scale3.scale, scale3.domain, void 0, tickFormat2);\n const swatches = create4(\"div\", context).attr(\n \"class\",\n `${className}-swatches ${className}-swatches-${columns != null ? \"columns\" : \"wrap\"}`\n );\n let extraStyle;\n if (columns != null) {\n extraStyle = `:where(.${className}-swatches-columns .${className}-swatch) {\n display: flex;\n align-items: center;\n break-inside: avoid;\n padding-bottom: 1px;\n}\n:where(.${className}-swatches-columns .${className}-swatch::before) {\n flex-shrink: 0;\n}\n:where(.${className}-swatches-columns .${className}-swatch-label) {\n white-space: nowrap;\n overflow: hidden;\n text-overflow: ellipsis;\n}`;\n swatches.style(\"columns\", columns).selectAll().data(scale3.domain).enter().append(\"div\").attr(\"class\", `${className}-swatch`).call(swatch, scale3, swatchWidth, swatchHeight).call(\n (item) => item.append(\"div\").attr(\"class\", `${className}-swatch-label`).attr(\"title\", tickFormat2).text(tickFormat2)\n );\n } else {\n extraStyle = `:where(.${className}-swatches-wrap) {\n display: flex;\n align-items: center;\n min-height: 33px;\n flex-wrap: wrap;\n}\n:where(.${className}-swatches-wrap .${className}-swatch) {\n display: inline-flex;\n align-items: center;\n margin-right: 1em;\n}`;\n swatches.selectAll().data(scale3.domain).enter().append(\"span\").attr(\"class\", `${className}-swatch`).call(swatch, scale3, swatchWidth, swatchHeight).append(function() {\n return this.ownerDocument.createTextNode(tickFormat2.apply(this, arguments));\n });\n }\n return swatches.call(\n (div) => div.insert(\"style\", \"*\").text(\n `:where(.${className}-swatches) {\n font-family: system-ui, sans-serif;\n font-size: 10px;\n margin-bottom: 0.5em;\n}\n:where(.${className}-swatch > svg) {\n margin-right: 0.5em;\n overflow: visible;\n}\n${extraStyle}`\n )\n ).style(\"margin-left\", marginLeft2 ? `${+marginLeft2}px` : null).style(\"width\", width2 === void 0 ? null : `${+width2}px`).style(\"font-variant\", impliedString(fontVariant, \"normal\")).call(applyInlineStyles, style2).node();\n}\n\n// ../../node_modules/@observablehq/plot/src/legends.js\nvar legendRegistry = /* @__PURE__ */ new Map([\n [\"symbol\", legendSymbols],\n [\"color\", legendColor],\n [\"opacity\", legendOpacity]\n]);\nfunction legend(options = {}) {\n for (const [key, value] of legendRegistry) {\n const scale3 = options[key];\n if (isScaleOptions(scale3)) {\n const context = createContext(options);\n let hint;\n if (key === \"symbol\") {\n const { fill, stroke = fill === void 0 && isScaleOptions(options.color) ? \"color\" : void 0 } = options;\n hint = { fill, stroke };\n }\n return value(\n normalizeScale(key, scale3, hint),\n legendOptions(context, scale3, options),\n (key2) => isScaleOptions(options[key2]) ? normalizeScale(key2, options[key2]) : null\n );\n }\n }\n throw new Error(\"unknown legend type; no scale found\");\n}\nfunction exposeLegends(scales2, context, defaults22 = {}) {\n return (key, options) => {\n if (!legendRegistry.has(key)) throw new Error(`unknown legend type: ${key}`);\n if (!(key in scales2)) return;\n return legendRegistry.get(key)(scales2[key], legendOptions(context, defaults22[key], options), (key2) => scales2[key2]);\n };\n}\nfunction legendOptions({ className, ...context }, { label: label2, ticks: ticks2, tickFormat: tickFormat2 } = {}, options) {\n return inherit2(options, { className, ...context }, { label: label2, ticks: ticks2, tickFormat: tickFormat2 });\n}\nfunction legendColor(color3, { legend: legend3 = true, ...options }) {\n if (legend3 === true) legend3 = color3.type === \"ordinal\" ? \"swatches\" : \"ramp\";\n if (color3.domain === void 0) return;\n switch (`${legend3}`.toLowerCase()) {\n case \"swatches\":\n return legendSwatches(color3, options);\n case \"ramp\":\n return legendRamp(color3, options);\n default:\n throw new Error(`unknown legend type: ${legend3}`);\n }\n}\nfunction legendOpacity({ type: type2, interpolate, ...scale3 }, { legend: legend3 = true, color: color3 = rgb(0, 0, 0), ...options }) {\n if (!interpolate) throw new Error(`${type2} opacity scales are not supported`);\n if (legend3 === true) legend3 = \"ramp\";\n if (`${legend3}`.toLowerCase() !== \"ramp\") throw new Error(`${legend3} opacity legends are not supported`);\n return legendColor({ type: type2, ...scale3, interpolate: interpolateOpacity(color3) }, { legend: legend3, ...options });\n}\nfunction interpolateOpacity(color3) {\n const { r, g, b } = rgb(color3) || rgb(0, 0, 0);\n return (t) => `rgba(${r},${g},${b},${t})`;\n}\nfunction createLegends(scales2, context, options) {\n const legends = [];\n for (const [key, value] of legendRegistry) {\n const o = options[key];\n if (o?.legend && key in scales2) {\n const legend3 = value(scales2[key], legendOptions(context, scales2[key], o), (key2) => scales2[key2]);\n if (legend3 != null) legends.push(legend3);\n }\n }\n return legends;\n}\n\n// ../../node_modules/@observablehq/plot/src/transforms/identity.js\nfunction maybeIdentityX(options = {}) {\n return hasX(options) ? options : { ...options, x: identity7 };\n}\nfunction maybeIdentityY(options = {}) {\n return hasY(options) ? options : { ...options, y: identity7 };\n}\n\n// ../../node_modules/@observablehq/plot/src/transforms/exclusiveFacets.js\nfunction exclusiveFacets(data, facets) {\n if (facets.length === 1) return { data, facets };\n const n = lengthof(data);\n const O = new Uint8Array(n);\n let overlaps = 0;\n for (const facet of facets) {\n for (const i of facet) {\n if (O[i]) ++overlaps;\n O[i] = 1;\n }\n }\n if (overlaps === 0) return { data, facets };\n data = slice3(data);\n const R = data[reindex] = new Uint32Array(n + overlaps);\n facets = facets.map((facet) => slice3(facet, Uint32Array));\n let j = n;\n O.fill(0);\n for (const facet of facets) {\n for (let k2 = 0, m = facet.length; k2 < m; ++k2) {\n const i = facet[k2];\n if (O[i]) facet[k2] = j, data[j] = data[i], R[j] = i, ++j;\n else R[i] = i;\n O[i] = 1;\n }\n }\n return { data, facets };\n}\n\n// ../../node_modules/@observablehq/plot/src/transforms/stack.js\nfunction stackX(stackOptions = {}, options = {}) {\n if (arguments.length === 1) [stackOptions, options] = mergeOptions(stackOptions);\n const { y1: y12, y: y3 = y12, x: x3, ...rest } = options;\n const [transform3, Y3, x12, x22] = stack(y3, x3, \"y\", \"x\", stackOptions, rest);\n return { ...transform3, y1: y12, y: Y3, x1: x12, x2: x22, x: mid(x12, x22) };\n}\nfunction stackX1(stackOptions = {}, options = {}) {\n if (arguments.length === 1) [stackOptions, options] = mergeOptions(stackOptions);\n const { y1: y12, y: y3 = y12, x: x3 } = options;\n const [transform3, Y3, X3] = stack(y3, x3, \"y\", \"x\", stackOptions, options);\n return { ...transform3, y1: y12, y: Y3, x: X3 };\n}\nfunction stackX2(stackOptions = {}, options = {}) {\n if (arguments.length === 1) [stackOptions, options] = mergeOptions(stackOptions);\n const { y1: y12, y: y3 = y12, x: x3 } = options;\n const [transform3, Y3, , X3] = stack(y3, x3, \"y\", \"x\", stackOptions, options);\n return { ...transform3, y1: y12, y: Y3, x: X3 };\n}\nfunction stackY(stackOptions = {}, options = {}) {\n if (arguments.length === 1) [stackOptions, options] = mergeOptions(stackOptions);\n const { x1: x12, x: x3 = x12, y: y3, ...rest } = options;\n const [transform3, X3, y12, y22] = stack(x3, y3, \"x\", \"y\", stackOptions, rest);\n return { ...transform3, x1: x12, x: X3, y1: y12, y2: y22, y: mid(y12, y22) };\n}\nfunction stackY1(stackOptions = {}, options = {}) {\n if (arguments.length === 1) [stackOptions, options] = mergeOptions(stackOptions);\n const { x1: x12, x: x3 = x12, y: y3 } = options;\n const [transform3, X3, Y3] = stack(x3, y3, \"x\", \"y\", stackOptions, options);\n return { ...transform3, x1: x12, x: X3, y: Y3 };\n}\nfunction stackY2(stackOptions = {}, options = {}) {\n if (arguments.length === 1) [stackOptions, options] = mergeOptions(stackOptions);\n const { x1: x12, x: x3 = x12, y: y3 } = options;\n const [transform3, X3, , Y3] = stack(x3, y3, \"x\", \"y\", stackOptions, options);\n return { ...transform3, x1: x12, x: X3, y: Y3 };\n}\nfunction maybeStackX({ x: x3, x1: x12, x2: x22, ...options } = {}) {\n options = withTip(options, \"y\");\n if (x12 === void 0 && x22 === void 0) return stackX({ x: x3, ...options });\n [x12, x22] = maybeZero(x3, x12, x22);\n return { ...options, x1: x12, x2: x22 };\n}\nfunction maybeStackY({ y: y3, y1: y12, y2: y22, ...options } = {}) {\n options = withTip(options, \"x\");\n if (y12 === void 0 && y22 === void 0) return stackY({ y: y3, ...options });\n [y12, y22] = maybeZero(y3, y12, y22);\n return { ...options, y1: y12, y2: y22 };\n}\nfunction mergeOptions(options) {\n const { offset: offset2, order, reverse: reverse3, ...rest } = options;\n return [{ offset: offset2, order, reverse: reverse3 }, rest];\n}\nvar lengthy = { length: true };\nfunction stack(x3, y3 = one2, kx2, ky2, { offset: offset2, order, reverse: reverse3 }, options) {\n if (y3 === null) throw new Error(`stack requires ${ky2}`);\n const z = maybeZ(options);\n const [X3, setX] = maybeColumn(x3);\n const [Y13, setY1] = column2(y3);\n const [Y23, setY2] = column2(y3);\n Y13.hint = Y23.hint = lengthy;\n offset2 = maybeOffset(offset2);\n order = maybeOrder2(order, offset2, ky2);\n return [\n basic(options, (data, facets, plotOptions) => {\n ({ data, facets } = exclusiveFacets(data, facets));\n const X4 = x3 == null ? void 0 : setX(maybeApplyInterval(valueof(data, x3), plotOptions?.[kx2]));\n const Y3 = valueof(data, y3, Float64Array);\n const Z = valueof(data, z);\n const compare = order && order(data, X4, Y3, Z);\n const n = lengthof(data);\n const Y14 = setY1(new Float64Array(n));\n const Y24 = setY2(new Float64Array(n));\n const facetstacks = [];\n for (const facet of facets) {\n const stacks = X4 ? Array.from(group(facet, (i) => X4[i]).values()) : [facet];\n if (compare) for (const stack2 of stacks) stack2.sort(compare);\n for (const stack2 of stacks) {\n let yn = 0;\n let yp = 0;\n if (reverse3) stack2.reverse();\n for (const i of stack2) {\n const y4 = Y3[i];\n if (y4 < 0) yn = Y24[i] = (Y14[i] = yn) + y4;\n else if (y4 > 0) yp = Y24[i] = (Y14[i] = yp) + y4;\n else Y24[i] = Y14[i] = yp;\n }\n }\n facetstacks.push(stacks);\n }\n if (offset2) offset2(facetstacks, Y14, Y24, Z);\n return { data, facets };\n }),\n X3,\n Y13,\n Y23\n ];\n}\nfunction maybeOffset(offset2) {\n if (offset2 == null) return;\n if (typeof offset2 === \"function\") return offset2;\n switch (`${offset2}`.toLowerCase()) {\n case \"expand\":\n case \"normalize\":\n return offsetExpand;\n case \"center\":\n case \"silhouette\":\n return offsetCenter;\n case \"wiggle\":\n return offsetWiggle;\n }\n throw new Error(`unknown offset: ${offset2}`);\n}\nfunction extent2(stack2, Y23) {\n let min5 = 0, max4 = 0;\n for (const i of stack2) {\n const y3 = Y23[i];\n if (y3 < min5) min5 = y3;\n if (y3 > max4) max4 = y3;\n }\n return [min5, max4];\n}\nfunction offsetExpand(facetstacks, Y13, Y23) {\n for (const stacks of facetstacks) {\n for (const stack2 of stacks) {\n const [yn, yp] = extent2(stack2, Y23);\n for (const i of stack2) {\n const m = 1 / (yp - yn || 1);\n Y13[i] = m * (Y13[i] - yn);\n Y23[i] = m * (Y23[i] - yn);\n }\n }\n }\n}\nfunction offsetCenter(facetstacks, Y13, Y23) {\n for (const stacks of facetstacks) {\n for (const stack2 of stacks) {\n const [yn, yp] = extent2(stack2, Y23);\n for (const i of stack2) {\n const m = (yp + yn) / 2;\n Y13[i] -= m;\n Y23[i] -= m;\n }\n }\n offsetZero(stacks, Y13, Y23);\n }\n offsetCenterFacets(facetstacks, Y13, Y23);\n}\nfunction offsetWiggle(facetstacks, Y13, Y23, Z) {\n for (const stacks of facetstacks) {\n const prev = new InternMap();\n let y3 = 0;\n for (const stack2 of stacks) {\n let j = -1;\n const Fi = stack2.map((i) => Math.abs(Y23[i] - Y13[i]));\n const Df = stack2.map((i) => {\n j = Z ? Z[i] : ++j;\n const value = Y23[i] - Y13[i];\n const diff = prev.has(j) ? value - prev.get(j) : 0;\n prev.set(j, value);\n return diff;\n });\n const Cf1 = [0, ...cumsum(Df)];\n for (const i of stack2) {\n Y13[i] += y3;\n Y23[i] += y3;\n }\n const s1 = sum2(Fi);\n if (s1) y3 -= sum2(Fi, (d, i) => (Df[i] / 2 + Cf1[i]) * d) / s1;\n }\n offsetZero(stacks, Y13, Y23);\n }\n offsetCenterFacets(facetstacks, Y13, Y23);\n}\nfunction offsetZero(stacks, Y13, Y23) {\n const m = min2(stacks, (stack2) => min2(stack2, (i) => Y13[i]));\n for (const stack2 of stacks) {\n for (const i of stack2) {\n Y13[i] -= m;\n Y23[i] -= m;\n }\n }\n}\nfunction offsetCenterFacets(facetstacks, Y13, Y23) {\n const n = facetstacks.length;\n if (n === 1) return;\n const facets = facetstacks.map((stacks) => stacks.flat());\n const m = facets.map((I) => (min2(I, (i) => Y13[i]) + max2(I, (i) => Y23[i])) / 2);\n const m0 = min2(m);\n for (let j = 0; j < n; j++) {\n const p = m0 - m[j];\n for (const i of facets[j]) {\n Y13[i] += p;\n Y23[i] += p;\n }\n }\n}\nfunction maybeOrder2(order, offset2, ky2) {\n if (order === void 0 && offset2 === offsetWiggle) return orderInsideOut(ascendingDefined2);\n if (order == null) return;\n if (typeof order === \"string\") {\n const negate2 = order.startsWith(\"-\");\n const compare = negate2 ? descendingDefined : ascendingDefined2;\n switch ((negate2 ? order.slice(1) : order).toLowerCase()) {\n case \"value\":\n case ky2:\n return orderY(compare);\n case \"z\":\n return orderZ(compare);\n case \"sum\":\n return orderSum(compare);\n case \"appearance\":\n return orderAppearance(compare);\n case \"inside-out\":\n return orderInsideOut(compare);\n }\n return orderAccessor(field2(order));\n }\n if (typeof order === \"function\") return (order.length === 1 ? orderAccessor : orderComparator)(order);\n if (isArray2(order)) return orderGiven(order);\n throw new Error(`invalid order: ${order}`);\n}\nfunction orderY(compare) {\n return (data, X3, Y3) => (i, j) => compare(Y3[i], Y3[j]);\n}\nfunction orderZ(compare) {\n return (data, X3, Y3, Z) => (i, j) => compare(Z[i], Z[j]);\n}\nfunction orderSum(compare) {\n return orderZDomain(\n compare,\n (data, X3, Y3, Z) => groupSort(\n range2(data),\n (I) => sum2(I, (i) => Y3[i]),\n (i) => Z[i]\n )\n );\n}\nfunction orderAppearance(compare) {\n return orderZDomain(\n compare,\n (data, X3, Y3, Z) => groupSort(\n range2(data),\n (I) => X3[greatest(I, (i) => Y3[i])],\n (i) => Z[i]\n )\n );\n}\nfunction orderInsideOut(compare) {\n return orderZDomain(compare, (data, X3, Y3, Z) => {\n const I = range2(data);\n const K2 = groupSort(\n I,\n (I2) => X3[greatest(I2, (i) => Y3[i])],\n (i) => Z[i]\n );\n const sums = rollup(\n I,\n (I2) => sum2(I2, (i) => Y3[i]),\n (i) => Z[i]\n );\n const Kp = [], Kn = [];\n let s2 = 0;\n for (const k2 of K2) {\n if (s2 < 0) {\n s2 += sums.get(k2);\n Kp.push(k2);\n } else {\n s2 -= sums.get(k2);\n Kn.push(k2);\n }\n }\n return Kn.reverse().concat(Kp);\n });\n}\nfunction orderAccessor(f) {\n return (data) => {\n const O = valueof(data, f);\n return (i, j) => ascendingDefined2(O[i], O[j]);\n };\n}\nfunction orderComparator(f) {\n return (data) => {\n return isArray2(data) ? (i, j) => f(data[i], data[j]) : (i, j) => f(data.get(i), data.get(j));\n };\n}\nfunction orderGiven(domain) {\n return orderZDomain(ascendingDefined2, () => domain);\n}\nfunction orderZDomain(compare, domain) {\n return (data, X3, Y3, Z) => {\n if (!Z) throw new Error(\"missing channel: z\");\n const map5 = new InternMap(domain(data, X3, Y3, Z).map((d, i) => [d, i]));\n return (i, j) => compare(map5.get(Z[i]), map5.get(Z[j]));\n };\n}\n\n// ../../node_modules/@observablehq/plot/src/marks/rect.js\nvar defaults4 = {\n ariaLabel: \"rect\"\n};\nvar Rect = class extends Mark {\n constructor(data, options = {}) {\n const { x1: x12, y1: y12, x2: x22, y2: y22 } = options;\n super(\n data,\n {\n x1: { value: x12, scale: \"x\", type: x12 != null && x22 == null ? \"band\" : void 0, optional: true },\n y1: { value: y12, scale: \"y\", type: y12 != null && y22 == null ? \"band\" : void 0, optional: true },\n x2: { value: x22, scale: \"x\", optional: true },\n y2: { value: y22, scale: \"y\", optional: true }\n },\n options,\n defaults4\n );\n rectInsets(this, options);\n rectRadii(this, options);\n }\n render(index2, scales2, channels, dimensions, context) {\n const { x: x3, y: y3 } = scales2;\n let { x1: X13, y1: Y13, x2: X23, y2: Y23 } = channels;\n const { marginTop: marginTop2, marginRight: marginRight2, marginBottom: marginBottom2, marginLeft: marginLeft2, width: width2, height: height2 } = dimensions;\n const { projection: projection3 } = context;\n const { insetTop, insetRight, insetBottom, insetLeft } = this;\n const { rx, ry, rx1y1, rx1y2, rx2y1, rx2y2 } = this;\n if ((X13 || X23) && !projection3 && isCollapsed(x3)) X13 = X23 = null;\n if ((Y13 || Y23) && !projection3 && isCollapsed(y3)) Y13 = Y23 = null;\n const bx = x3?.bandwidth ? x3.bandwidth() : 0;\n const by = y3?.bandwidth ? y3.bandwidth() : 0;\n return create4(\"svg:g\", context).call(applyIndirectStyles, this, dimensions, context).call(applyTransform, this, {}, 0, 0).call(\n (g) => g.selectAll().data(index2).enter().call(\n rx1y1 || rx1y2 || rx2y1 || rx2y2 ? (g2) => g2.append(\"path\").call(applyDirectStyles, this).call(\n applyRoundedRect,\n X13 && X23 ? (i) => X13[i] + (X23[i] < X13[i] ? -insetRight : insetLeft) : X13 ? (i) => X13[i] + insetLeft : marginLeft2 + insetLeft,\n Y13 && Y23 ? (i) => Y13[i] + (Y23[i] < Y13[i] ? -insetBottom : insetTop) : Y13 ? (i) => Y13[i] + insetTop : marginTop2 + insetTop,\n X13 && X23 ? (i) => X23[i] - (X23[i] < X13[i] ? -insetLeft : insetRight) : X13 ? (i) => X13[i] + bx - insetRight : width2 - marginRight2 - insetRight,\n Y13 && Y23 ? (i) => Y23[i] - (Y23[i] < Y13[i] ? -insetTop : insetBottom) : Y13 ? (i) => Y13[i] + by - insetBottom : height2 - marginBottom2 - insetBottom,\n this\n ).call(applyChannelStyles, this, channels) : (g2) => g2.append(\"rect\").call(applyDirectStyles, this).attr(\n \"x\",\n X13 ? X23 ? (i) => Math.min(X13[i], X23[i]) + insetLeft : (i) => X13[i] + insetLeft : marginLeft2 + insetLeft\n ).attr(\n \"y\",\n Y13 ? Y23 ? (i) => Math.min(Y13[i], Y23[i]) + insetTop : (i) => Y13[i] + insetTop : marginTop2 + insetTop\n ).attr(\n \"width\",\n X13 ? X23 ? (i) => Math.max(0, Math.abs(X23[i] - X13[i]) + bx - insetLeft - insetRight) : bx - insetLeft - insetRight : width2 - marginRight2 - marginLeft2 - insetRight - insetLeft\n ).attr(\n \"height\",\n Y13 ? Y23 ? (i) => Math.max(0, Math.abs(Y13[i] - Y23[i]) + by - insetTop - insetBottom) : by - insetTop - insetBottom : height2 - marginTop2 - marginBottom2 - insetTop - insetBottom\n ).call(applyAttr, \"rx\", rx).call(applyAttr, \"ry\", ry).call(applyChannelStyles, this, channels)\n )\n ).node();\n }\n};\nfunction rectInsets(mark2, { inset: inset2 = 0, insetTop = inset2, insetRight = inset2, insetBottom = inset2, insetLeft = inset2 } = {}) {\n mark2.insetTop = number5(insetTop);\n mark2.insetRight = number5(insetRight);\n mark2.insetBottom = number5(insetBottom);\n mark2.insetLeft = number5(insetLeft);\n}\nfunction rectRadii(mark2, {\n r,\n rx,\n // for elliptic corners\n ry,\n // for elliptic corners\n rx1 = r,\n ry1 = r,\n rx2 = r,\n ry2 = r,\n rx1y1 = rx1 !== void 0 ? +rx1 : ry1 !== void 0 ? +ry1 : 0,\n rx1y2 = rx1 !== void 0 ? +rx1 : ry2 !== void 0 ? +ry2 : 0,\n rx2y1 = rx2 !== void 0 ? +rx2 : ry1 !== void 0 ? +ry1 : 0,\n rx2y2 = rx2 !== void 0 ? +rx2 : ry2 !== void 0 ? +ry2 : 0\n} = {}) {\n if (rx1y1 || rx1y2 || rx2y1 || rx2y2) {\n mark2.rx1y1 = rx1y1;\n mark2.rx1y2 = rx1y2;\n mark2.rx2y1 = rx2y1;\n mark2.rx2y2 = rx2y2;\n } else {\n mark2.rx = impliedString(rx, \"auto\");\n mark2.ry = impliedString(ry, \"auto\");\n }\n}\nfunction applyRoundedRect(selection2, X13, Y13, X23, Y23, mark2) {\n const { rx1y1: r11, rx1y2: r12, rx2y1: r21, rx2y2: r22 } = mark2;\n if (typeof X13 !== \"function\") X13 = constant(X13);\n if (typeof Y13 !== \"function\") Y13 = constant(Y13);\n if (typeof X23 !== \"function\") X23 = constant(X23);\n if (typeof Y23 !== \"function\") Y23 = constant(Y23);\n const rx = Math.max(Math.abs(r11 + r21), Math.abs(r12 + r22));\n const ry = Math.max(Math.abs(r11 + r12), Math.abs(r21 + r22));\n selection2.attr(\"d\", (i) => {\n const x12 = X13(i);\n const y12 = Y13(i);\n const x22 = X23(i);\n const y22 = Y23(i);\n const ix = x12 > x22;\n const iy = y12 > y22;\n const l = ix ? x22 : x12;\n const r = ix ? x12 : x22;\n const t = iy ? y22 : y12;\n const b = iy ? y12 : y22;\n const k2 = Math.min(1, (r - l) / rx, (b - t) / ry);\n const tl = k2 * (ix ? iy ? r22 : r21 : iy ? r12 : r11);\n const tr = k2 * (ix ? iy ? r12 : r11 : iy ? r22 : r21);\n const br = k2 * (ix ? iy ? r11 : r12 : iy ? r21 : r22);\n const bl = k2 * (ix ? iy ? r21 : r22 : iy ? r11 : r12);\n return `M${l},${t + biasY(tl, bl)}A${tl},${tl} 0 0 ${tl < 0 ? 0 : 1} ${l + biasX(tl, bl)},${t}H${r - biasX(tr, br)}A${tr},${tr} 0 0 ${tr < 0 ? 0 : 1} ${r},${t + biasY(tr, br)}V${b - biasY(br, tr)}A${br},${br} 0 0 ${br < 0 ? 0 : 1} ${r - biasX(br, tr)},${b}H${l + biasX(bl, tl)}A${bl},${bl} 0 0 ${bl < 0 ? 0 : 1} ${l},${b - biasY(bl, tl)}Z`;\n });\n}\nfunction biasX(r1, r2) {\n return r2 < 0 ? r1 : Math.abs(r1);\n}\nfunction biasY(r1, r2) {\n return r2 < 0 ? Math.abs(r1) : r1;\n}\nfunction rect(data, options) {\n return new Rect(data, maybeTrivialIntervalX(maybeTrivialIntervalY(options)));\n}\nfunction rectX(data, options = {}) {\n if (!hasXY(options)) options = { ...options, y: indexOf, x2: identity7, interval: 1 };\n return new Rect(data, maybeStackX(maybeTrivialIntervalY(maybeIdentityX(options))));\n}\nfunction rectY(data, options = {}) {\n if (!hasXY(options)) options = { ...options, x: indexOf, y2: identity7, interval: 1 };\n return new Rect(data, maybeStackY(maybeTrivialIntervalX(maybeIdentityY(options))));\n}\n\n// ../../node_modules/@observablehq/plot/src/marks/frame.js\nvar defaults5 = {\n ariaLabel: \"frame\",\n fill: \"none\",\n stroke: \"currentColor\",\n clip: false\n};\nvar lineDefaults = {\n ariaLabel: \"frame\",\n fill: null,\n stroke: \"currentColor\",\n strokeLinecap: \"square\",\n clip: false\n};\nvar Frame = class extends Mark {\n constructor(options = {}) {\n const { anchor = null } = options;\n super(singleton, void 0, options, anchor == null ? defaults5 : lineDefaults);\n this.anchor = maybeKeyword(anchor, \"anchor\", [\"top\", \"right\", \"bottom\", \"left\"]);\n rectInsets(this, options);\n if (!anchor) rectRadii(this, options);\n }\n render(index2, scales2, channels, dimensions, context) {\n const { marginTop: marginTop2, marginRight: marginRight2, marginBottom: marginBottom2, marginLeft: marginLeft2, width: width2, height: height2 } = dimensions;\n const { anchor, insetTop, insetRight, insetBottom, insetLeft } = this;\n const { rx, ry, rx1y1, rx1y2, rx2y1, rx2y2 } = this;\n const x12 = marginLeft2 + insetLeft;\n const x22 = width2 - marginRight2 - insetRight;\n const y12 = marginTop2 + insetTop;\n const y22 = height2 - marginBottom2 - insetBottom;\n return create4(anchor ? \"svg:line\" : rx1y1 || rx1y2 || rx2y1 || rx2y2 ? \"svg:path\" : \"svg:rect\", context).datum(0).call(applyIndirectStyles, this, dimensions, context).call(applyDirectStyles, this).call(applyChannelStyles, this, channels).call(applyTransform, this, {}).call(\n anchor === \"left\" ? (line3) => line3.attr(\"x1\", x12).attr(\"x2\", x12).attr(\"y1\", y12).attr(\"y2\", y22) : anchor === \"right\" ? (line3) => line3.attr(\"x1\", x22).attr(\"x2\", x22).attr(\"y1\", y12).attr(\"y2\", y22) : anchor === \"top\" ? (line3) => line3.attr(\"x1\", x12).attr(\"x2\", x22).attr(\"y1\", y12).attr(\"y2\", y12) : anchor === \"bottom\" ? (line3) => line3.attr(\"x1\", x12).attr(\"x2\", x22).attr(\"y1\", y22).attr(\"y2\", y22) : rx1y1 || rx1y2 || rx2y1 || rx2y2 ? (path2) => path2.call(applyRoundedRect, x12, y12, x22, y22, this) : (rect3) => rect3.attr(\"x\", x12).attr(\"y\", y12).attr(\"width\", x22 - x12).attr(\"height\", y22 - y12).attr(\"rx\", rx).attr(\"ry\", ry)\n ).node();\n }\n};\nfunction frame2(options) {\n return new Frame(options);\n}\n\n// ../../node_modules/@observablehq/plot/src/marks/tip.js\nvar defaults6 = {\n ariaLabel: \"tip\",\n fill: \"var(--plot-background)\",\n stroke: \"currentColor\"\n};\nvar ignoreChannels = /* @__PURE__ */ new Set([\"geometry\", \"href\", \"src\", \"ariaLabel\", \"scales\"]);\nvar Tip = class extends Mark {\n constructor(data, options = {}) {\n if (options.tip) options = { ...options, tip: false };\n if (options.title === void 0 && isIterable(data) && isTextual(data)) options = { ...options, title: identity7 };\n const {\n x: x3,\n y: y3,\n x1: x12,\n x2: x22,\n y1: y12,\n y2: y22,\n anchor,\n preferredAnchor = \"bottom\",\n monospace,\n fontFamily = monospace ? \"ui-monospace, monospace\" : void 0,\n fontSize,\n fontStyle,\n fontVariant,\n fontWeight,\n lineHeight = 1,\n lineWidth = 20,\n frameAnchor,\n format: format3,\n textAnchor = \"start\",\n textOverflow,\n textPadding = 8,\n title,\n pointerSize = 12,\n pathFilter = \"drop-shadow(0 3px 4px rgba(0,0,0,0.2))\"\n } = options;\n super(\n data,\n {\n x: { value: x12 != null && x22 != null ? null : x3, scale: \"x\", optional: true },\n // ignore midpoint\n y: { value: y12 != null && y22 != null ? null : y3, scale: \"y\", optional: true },\n // ignore midpoint\n x1: { value: x12, scale: \"x\", optional: x22 == null },\n y1: { value: y12, scale: \"y\", optional: y22 == null },\n x2: { value: x22, scale: \"x\", optional: x12 == null },\n y2: { value: y22, scale: \"y\", optional: y12 == null },\n title: { value: title, optional: true }\n // filter: defined\n },\n options,\n defaults6\n );\n this.anchor = maybeAnchor(anchor, \"anchor\");\n this.preferredAnchor = maybeAnchor(preferredAnchor, \"preferredAnchor\");\n this.frameAnchor = maybeFrameAnchor(frameAnchor);\n this.textAnchor = impliedString(textAnchor, \"middle\");\n this.textPadding = +textPadding;\n this.pointerSize = +pointerSize;\n this.pathFilter = string(pathFilter);\n this.lineHeight = +lineHeight;\n this.lineWidth = +lineWidth;\n this.textOverflow = maybeTextOverflow(textOverflow);\n this.monospace = !!monospace;\n this.fontFamily = string(fontFamily);\n this.fontSize = number5(fontSize);\n this.fontStyle = string(fontStyle);\n this.fontVariant = string(fontVariant);\n this.fontWeight = string(fontWeight);\n for (const key in defaults6) if (key in this.channels) this[key] = defaults6[key];\n this.splitLines = splitter2(this);\n this.clipLine = clipper(this);\n this.format = typeof format3 === \"string\" || typeof format3 === \"function\" ? { title: format3 } : { ...format3 };\n }\n render(index2, scales2, values2, dimensions, context) {\n const mark2 = this;\n const { x: x3, y: y3, fx, fy } = scales2;\n const { ownerSVGElement: svg, document: document2 } = context;\n const { anchor, monospace, lineHeight, lineWidth } = this;\n const { textPadding: r, pointerSize: m, pathFilter } = this;\n const { marginTop: marginTop2, marginLeft: marginLeft2 } = dimensions;\n const { x1: X13, y1: Y13, x2: X23, y2: Y23, x: X3 = X13 ?? X23, y: Y3 = Y13 ?? Y23 } = values2;\n const ox2 = fx ? fx(index2.fx) - marginLeft2 : 0;\n const oy2 = fy ? fy(index2.fy) - marginTop2 : 0;\n const [cx, cy] = applyFrameAnchor(this, dimensions);\n const px = anchorX(values2, cx);\n const py = anchorY(values2, cy);\n const widthof2 = monospace ? monospaceWidth : defaultWidth;\n const ee = widthof2(ellipsis);\n let sources, format3;\n if (\"title\" in values2) {\n sources = getSourceChannels.call(this, { title: values2.channels.title }, scales2);\n format3 = formatTitle;\n } else {\n sources = getSourceChannels.call(this, values2.channels, scales2);\n format3 = formatChannels;\n }\n const g = create4(\"svg:g\", context).call(applyIndirectStyles, this, dimensions, context).call(applyIndirectTextStyles, this).call(applyTransform, this, { x: X3 && x3, y: Y3 && y3 }).call(\n (g2) => g2.selectAll().data(index2).enter().append(\"g\").attr(\"transform\", (i) => `translate(${Math.round(px(i))},${Math.round(py(i))})`).call(applyDirectStyles, this).call((g3) => g3.append(\"path\").attr(\"filter\", pathFilter)).call(\n (g3) => g3.append(\"text\").each(function(i) {\n const that = select_default2(this);\n this.setAttribute(\"fill\", \"currentColor\");\n this.setAttribute(\"fill-opacity\", 1);\n this.setAttribute(\"stroke\", \"none\");\n const lines = format3.call(mark2, i, index2, sources, scales2, values2);\n if (typeof lines === \"string\") {\n for (const line3 of mark2.splitLines(lines)) {\n renderLine(that, { value: mark2.clipLine(line3) });\n }\n } else {\n const labels = /* @__PURE__ */ new Set();\n for (const line3 of lines) {\n const { label: label2 = \"\" } = line3;\n if (label2 && labels.has(label2)) continue;\n else labels.add(label2);\n renderLine(that, line3);\n }\n }\n })\n )\n );\n function renderLine(selection2, { label: label2, value, color: color3, opacity: opacity2 }) {\n label2 ??= \"\", value ??= \"\";\n const swatch = color3 != null || opacity2 != null;\n let title;\n let w = lineWidth * 100;\n const [j] = cut(label2, w, widthof2, ee);\n if (j >= 0) {\n label2 = label2.slice(0, j).trimEnd() + ellipsis;\n title = value.trim();\n value = \"\";\n } else {\n if (label2 || !value && !swatch) value = \" \" + value;\n const [k2] = cut(value, w - widthof2(label2), widthof2, ee);\n if (k2 >= 0) {\n title = value.trim();\n value = value.slice(0, k2).trimEnd() + ellipsis;\n }\n }\n const line3 = selection2.append(\"tspan\").attr(\"x\", 0).attr(\"dy\", `${lineHeight}em`).text(\"\\u200B\");\n if (label2) line3.append(\"tspan\").attr(\"font-weight\", \"bold\").text(label2);\n if (value) line3.append(() => document2.createTextNode(value));\n if (swatch) line3.append(\"tspan\").text(\" \\u25A0\").attr(\"fill\", color3).attr(\"fill-opacity\", opacity2).style(\"user-select\", \"none\");\n if (title) line3.append(\"title\").text(title);\n }\n function postrender() {\n const { width: width2, height: height2 } = dimensions.facet ?? dimensions;\n g.selectChildren().each(function(i) {\n let { x: tx, width: w, height: h } = this.getBBox();\n w = Math.round(w), h = Math.round(h);\n let a2 = anchor;\n if (a2 === void 0) {\n const x4 = px(i) + ox2;\n const y4 = py(i) + oy2;\n const fitLeft = x4 + w + m + r * 2 < width2;\n const fitRight = x4 - w - m - r * 2 > 0;\n const fitTop = y4 + h + m + r * 2 < height2;\n const fitBottom = y4 - h - m - r * 2 > 0;\n a2 = fitLeft && fitRight ? fitTop && fitBottom ? mark2.preferredAnchor : fitBottom ? \"bottom\" : \"top\" : fitTop && fitBottom ? fitLeft ? \"left\" : \"right\" : (fitLeft || fitRight) && (fitTop || fitBottom) ? `${fitBottom ? \"bottom\" : \"top\"}-${fitLeft ? \"left\" : \"right\"}` : mark2.preferredAnchor;\n }\n const path2 = this.firstChild;\n const text3 = this.lastChild;\n path2.setAttribute(\"d\", getPath(a2, m, r, w, h));\n if (tx) for (const t of text3.childNodes) t.setAttribute(\"x\", -tx);\n text3.setAttribute(\"y\", `${+getLineOffset(a2, text3.childNodes.length, lineHeight).toFixed(6)}em`);\n text3.setAttribute(\"transform\", `translate(${getTextTranslate(a2, m, r, w, h)})`);\n });\n g.attr(\"visibility\", null);\n }\n if (index2.length) {\n g.attr(\"visibility\", \"hidden\");\n if (svg.isConnected) Promise.resolve().then(postrender);\n else if (typeof requestAnimationFrame !== \"undefined\") requestAnimationFrame(postrender);\n }\n return g.node();\n }\n};\nfunction tip(data, { x: x3, y: y3, ...options } = {}) {\n if (options.frameAnchor === void 0) [x3, y3] = maybeTuple(x3, y3);\n return new Tip(data, { ...options, x: x3, y: y3 });\n}\nfunction getLineOffset(anchor, length4, lineHeight) {\n return /^top(?:-|$)/.test(anchor) ? 0.94 - lineHeight : /^bottom(?:-|$)/ ? -0.29 - length4 * lineHeight : length4 / 2 * lineHeight;\n}\nfunction getTextTranslate(anchor, m, r, width2, height2) {\n switch (anchor) {\n case \"middle\":\n return [-width2 / 2, height2 / 2];\n case \"top-left\":\n return [r, m + r];\n case \"top\":\n return [-width2 / 2, m / 2 + r];\n case \"top-right\":\n return [-width2 - r, m + r];\n case \"right\":\n return [-m / 2 - width2 - r, height2 / 2];\n case \"bottom-left\":\n return [r, -m - r];\n case \"bottom\":\n return [-width2 / 2, -m / 2 - r];\n case \"bottom-right\":\n return [-width2 - r, -m - r];\n case \"left\":\n return [r + m / 2, height2 / 2];\n }\n}\nfunction getPath(anchor, m, r, width2, height2) {\n const w = width2 + r * 2;\n const h = height2 + r * 2;\n switch (anchor) {\n case \"middle\":\n return `M${-w / 2},${-h / 2}h${w}v${h}h${-w}z`;\n case \"top-left\":\n return `M0,0l${m},${m}h${w - m}v${h}h${-w}z`;\n case \"top\":\n return `M0,0l${m / 2},${m / 2}h${(w - m) / 2}v${h}h${-w}v${-h}h${(w - m) / 2}z`;\n case \"top-right\":\n return `M0,0l${-m},${m}h${m - w}v${h}h${w}z`;\n case \"right\":\n return `M0,0l${-m / 2},${-m / 2}v${m / 2 - h / 2}h${-w}v${h}h${w}v${m / 2 - h / 2}z`;\n case \"bottom-left\":\n return `M0,0l${m},${-m}h${w - m}v${-h}h${-w}z`;\n case \"bottom\":\n return `M0,0l${m / 2},${-m / 2}h${(w - m) / 2}v${-h}h${-w}v${h}h${(w - m) / 2}z`;\n case \"bottom-right\":\n return `M0,0l${-m},${-m}h${m - w}v${-h}h${w}z`;\n case \"left\":\n return `M0,0l${m / 2},${-m / 2}v${m / 2 - h / 2}h${w}v${h}h${-w}v${m / 2 - h / 2}z`;\n }\n}\nfunction getSourceChannels(channels, scales2) {\n const sources = {};\n let format3 = this.format;\n format3 = maybeExpandPairedFormat(format3, channels, \"x\");\n format3 = maybeExpandPairedFormat(format3, channels, \"y\");\n this.format = format3;\n for (const key in format3) {\n const value = format3[key];\n if (value === null || value === false) {\n continue;\n } else if (key === \"fx\" || key === \"fy\") {\n sources[key] = true;\n } else {\n const source = getSource(channels, key);\n if (source) sources[key] = source;\n }\n }\n for (const key in channels) {\n if (key in sources || key in format3 || ignoreChannels.has(key)) continue;\n if ((key === \"x\" || key === \"y\") && channels.geometry) continue;\n const source = getSource(channels, key);\n if (source) {\n if (source.scale == null && source.defaultScale === \"color\") continue;\n sources[key] = source;\n }\n }\n if (this.facet) {\n if (scales2.fx && !(\"fx\" in format3)) sources.fx = true;\n if (scales2.fy && !(\"fy\" in format3)) sources.fy = true;\n }\n for (const key in sources) {\n const format4 = this.format[key];\n if (typeof format4 === \"string\") {\n const value = sources[key]?.value ?? scales2[key]?.domain() ?? [];\n this.format[key] = (isTemporal(value) ? utcFormat : format)(format4);\n } else if (format4 === void 0 || format4 === true) {\n const scale3 = scales2[key];\n this.format[key] = scale3?.bandwidth ? inferTickFormat(scale3, scale3.domain()) : formatDefault;\n }\n }\n return sources;\n}\nfunction maybeExpandPairedFormat(format3, channels, key) {\n if (!(key in format3)) return format3;\n const key1 = `${key}1`;\n const key2 = `${key}2`;\n if ((key1 in format3 || !(key1 in channels)) && (key2 in format3 || !(key2 in channels))) return format3;\n const entries = Object.entries(format3);\n const value = format3[key];\n entries.splice(entries.findIndex(([name2]) => name2 === key) + 1, 0, [key1, value], [key2, value]);\n return Object.fromEntries(entries);\n}\nfunction formatTitle(i, index2, { title }) {\n return this.format.title(title.value[i], i);\n}\nfunction* formatChannels(i, index2, channels, scales2, values2) {\n for (const key in channels) {\n if (key === \"fx\" || key === \"fy\") {\n yield {\n label: formatLabel(scales2, channels, key),\n value: this.format[key](index2[key], i)\n };\n continue;\n }\n if (key === \"x1\" && \"x2\" in channels) continue;\n if (key === \"y1\" && \"y2\" in channels) continue;\n const channel = channels[key];\n if (key === \"x2\" && \"x1\" in channels) {\n yield {\n label: formatPairLabel(scales2, channels, \"x\"),\n value: formatPair(this.format.x2, channels.x1, channel, i)\n };\n } else if (key === \"y2\" && \"y1\" in channels) {\n yield {\n label: formatPairLabel(scales2, channels, \"y\"),\n value: formatPair(this.format.y2, channels.y1, channel, i)\n };\n } else {\n const value = channel.value[i];\n const scale3 = channel.scale;\n if (!defined(value) && scale3 == null) continue;\n yield {\n label: formatLabel(scales2, channels, key),\n value: this.format[key](value, i),\n color: scale3 === \"color\" ? values2[key][i] : null,\n opacity: scale3 === \"opacity\" ? values2[key][i] : null\n };\n }\n }\n}\nfunction formatPair(formatValue, c1, c22, i) {\n return c22.hint?.length ? `${formatValue(c22.value[i] - c1.value[i], i)}` : `${formatValue(c1.value[i], i)}\\u2013${formatValue(c22.value[i], i)}`;\n}\nfunction formatPairLabel(scales2, channels, key) {\n const l1 = formatLabel(scales2, channels, `${key}1`, key);\n const l2 = formatLabel(scales2, channels, `${key}2`, key);\n return l1 === l2 ? l1 : `${l1}\\u2013${l2}`;\n}\nfunction formatLabel(scales2, channels, key, defaultLabel = key) {\n const channel = channels[key];\n const scale3 = scales2[channel?.scale ?? key];\n return String(scale3?.label ?? channel?.label ?? defaultLabel);\n}\n\n// ../../node_modules/@observablehq/plot/src/plot.js\nfunction plot(options = {}) {\n const { facet, style: style2, title, subtitle, caption, ariaLabel, ariaDescription } = options;\n const className = maybeClassName(options.className);\n const marks2 = options.marks === void 0 ? [] : flatMarks(options.marks);\n marks2.push(...inferTips(marks2));\n const topFacetState = maybeTopFacet(facet, options);\n const facetStateByMark = /* @__PURE__ */ new Map();\n for (const mark2 of marks2) {\n const facetState = maybeMarkFacet(mark2, topFacetState, options);\n if (facetState) facetStateByMark.set(mark2, facetState);\n }\n const channelsByScale = /* @__PURE__ */ new Map();\n if (topFacetState) addScaleChannels(channelsByScale, [topFacetState], options);\n addScaleChannels(channelsByScale, facetStateByMark, options);\n const axes = flatMarks(inferAxes(marks2, channelsByScale, options));\n for (const mark2 of axes) {\n const facetState = maybeMarkFacet(mark2, topFacetState, options);\n if (facetState) facetStateByMark.set(mark2, facetState);\n }\n marks2.unshift(...axes);\n let facets = createFacets(channelsByScale, options);\n if (facets !== void 0) {\n const topFacetsIndex = topFacetState ? facetFilter(facets, topFacetState) : void 0;\n for (const mark2 of marks2) {\n if (mark2.facet === null || mark2.facet === \"super\") continue;\n const facetState = facetStateByMark.get(mark2);\n if (facetState === void 0) continue;\n facetState.facetsIndex = mark2.fx != null || mark2.fy != null ? facetFilter(facets, facetState) : topFacetsIndex;\n }\n const nonEmpty = /* @__PURE__ */ new Set();\n for (const { facetsIndex } of facetStateByMark.values()) {\n facetsIndex?.forEach((index2, i) => {\n if (index2?.length > 0) {\n nonEmpty.add(i);\n }\n });\n }\n facets.forEach(\n 0 < nonEmpty.size && nonEmpty.size < facets.length ? (f, i) => f.empty = !nonEmpty.has(i) : (f) => f.empty = false\n );\n for (const mark2 of marks2) {\n if (mark2.facet === \"exclude\") {\n const facetState = facetStateByMark.get(mark2);\n if (facetState !== void 0) facetState.facetsIndex = facetExclude(facetState.facetsIndex);\n }\n }\n }\n for (const key of registry.keys()) {\n if (isScaleOptions(options[key]) && key !== \"fx\" && key !== \"fy\") {\n channelsByScale.set(key, []);\n }\n }\n const stateByMark = /* @__PURE__ */ new Map();\n for (const mark2 of marks2) {\n if (stateByMark.has(mark2)) throw new Error(\"duplicate mark; each mark must be unique\");\n const { facetsIndex, channels: facetChannels } = facetStateByMark.get(mark2) ?? {};\n const { data, facets: facets2, channels } = mark2.initialize(facetsIndex, facetChannels, options);\n applyScaleTransforms(channels, options);\n stateByMark.set(mark2, { data, facets: facets2, channels });\n }\n const scaleDescriptors = createScales(addScaleChannels(channelsByScale, stateByMark, options), options);\n const dimensions = createDimensions(scaleDescriptors, marks2, options);\n autoScaleRange(scaleDescriptors, dimensions);\n const scales2 = createScaleFunctions(scaleDescriptors);\n const { fx, fy } = scales2;\n const subdimensions = fx || fy ? innerDimensions(scaleDescriptors, dimensions) : dimensions;\n const superdimensions = fx || fy ? actualDimensions(scales2, dimensions) : dimensions;\n const context = createContext(options);\n const document2 = context.document;\n const svg = creator_default(\"svg\").call(document2.documentElement);\n let figure = svg;\n context.ownerSVGElement = svg;\n context.className = className;\n context.projection = createProjection(options, subdimensions);\n context.filterFacets = (data, channels) => {\n return facetFilter(facets, { channels, groups: facetGroups(data, channels) });\n };\n context.getMarkState = (mark2) => {\n const state = stateByMark.get(mark2);\n const facetState = facetStateByMark.get(mark2);\n return { ...state, channels: { ...state.channels, ...facetState?.channels } };\n };\n context.dispatchValue = (value) => {\n if (figure.value === value) return;\n figure.value = value;\n figure.dispatchEvent(new Event(\"input\", { bubbles: true }));\n };\n const newByScale = /* @__PURE__ */ new Set();\n for (const [mark2, state] of stateByMark) {\n if (mark2.initializer != null) {\n const dimensions2 = mark2.facet === \"super\" ? superdimensions : subdimensions;\n const update2 = mark2.initializer(state.data, state.facets, state.channels, scales2, dimensions2, context);\n if (update2.data !== void 0) {\n state.data = update2.data;\n }\n if (update2.facets !== void 0) {\n state.facets = update2.facets;\n }\n if (update2.channels !== void 0) {\n const { fx: fx2, fy: fy2, ...channels } = update2.channels;\n inferChannelScales(channels);\n Object.assign(state.channels, channels);\n for (const channel of Object.values(channels)) {\n const { scale: scale3 } = channel;\n if (scale3 != null && !isPosition(registry.get(scale3))) {\n applyScaleTransform(channel, options);\n newByScale.add(scale3);\n }\n }\n if (fx2 != null || fy2 != null) facetStateByMark.set(mark2, true);\n }\n }\n }\n if (newByScale.size) {\n const newChannelsByScale = /* @__PURE__ */ new Map();\n addScaleChannels(newChannelsByScale, stateByMark, options, (key) => newByScale.has(key));\n addScaleChannels(channelsByScale, stateByMark, options, (key) => newByScale.has(key));\n const newScaleDescriptors = inheritScaleLabels(createScales(newChannelsByScale, options), scaleDescriptors);\n const { scales: newExposedScales, ...newScales } = createScaleFunctions(newScaleDescriptors);\n Object.assign(scaleDescriptors, newScaleDescriptors);\n Object.assign(scales2, newScales);\n Object.assign(scales2.scales, newExposedScales);\n }\n let facetDomains, facetTranslate;\n if (facets !== void 0) {\n facetDomains = { x: fx?.domain(), y: fy?.domain() };\n facets = recreateFacets(facets, facetDomains);\n facetTranslate = facetTranslator(fx, fy, dimensions);\n }\n for (const [mark2, state] of stateByMark) {\n state.values = mark2.scale(state.channels, scales2, context);\n }\n const { width: width2, height: height2 } = dimensions;\n select_default2(svg).attr(\"class\", className).attr(\"fill\", \"currentColor\").attr(\"font-family\", \"system-ui, sans-serif\").attr(\"font-size\", 10).attr(\"text-anchor\", \"middle\").attr(\"width\", width2).attr(\"height\", height2).attr(\"viewBox\", `0 0 ${width2} ${height2}`).attr(\"aria-label\", ariaLabel).attr(\"aria-description\", ariaDescription).call(\n (svg2) => (\n // Warning: if you edit this, change defaultClassName.\n svg2.append(\"style\").text(\n `:where(.${className}) {\n --plot-background: white;\n display: block;\n height: auto;\n height: intrinsic;\n max-width: 100%;\n}\n:where(.${className} text),\n:where(.${className} tspan) {\n white-space: pre;\n}`\n )\n )\n ).call(applyInlineStyles, style2);\n for (const mark2 of marks2) {\n const { channels, values: values2, facets: indexes2 } = stateByMark.get(mark2);\n if (facets === void 0 || mark2.facet === \"super\") {\n let index2 = null;\n if (indexes2) {\n index2 = indexes2[0];\n index2 = mark2.filter(index2, channels, values2);\n if (index2.length === 0) {\n continue;\n }\n }\n const node = mark2.render(index2, scales2, values2, superdimensions, context);\n if (node == null) continue;\n svg.appendChild(node);\n } else {\n let g;\n for (const f of facets) {\n if (!(mark2.facetAnchor?.(facets, facetDomains, f) ?? !f.empty)) continue;\n let index2 = null;\n if (indexes2) {\n const faceted = facetStateByMark.has(mark2);\n index2 = indexes2[faceted ? f.i : 0];\n index2 = mark2.filter(index2, channels, values2);\n if (index2.length === 0) continue;\n if (!faceted && index2 === indexes2[0]) index2 = subarray(index2);\n index2.fx = f.x, index2.fy = f.y, index2.fi = f.i;\n }\n const node = mark2.render(index2, scales2, values2, subdimensions, context);\n if (node == null) continue;\n (g ??= select_default2(svg).append(\"g\")).append(() => node).datum(f);\n for (const name2 of [\"aria-label\", \"aria-description\", \"aria-hidden\", \"transform\"]) {\n if (node.hasAttribute(name2)) {\n g.attr(name2, node.getAttribute(name2));\n node.removeAttribute(name2);\n }\n }\n }\n g?.selectChildren().attr(\"transform\", facetTranslate);\n }\n }\n const legends = createLegends(scaleDescriptors, context, options);\n const { figure: figured = title != null || subtitle != null || caption != null || legends.length > 0 } = options;\n if (figured) {\n figure = document2.createElement(\"figure\");\n figure.className = `${className}-figure`;\n figure.style.maxWidth = \"initial\";\n if (title != null) figure.append(createTitleElement(document2, title, \"h2\"));\n if (subtitle != null) figure.append(createTitleElement(document2, subtitle, \"h3\"));\n figure.append(...legends, svg);\n if (caption != null) figure.append(createFigcaption(document2, caption));\n if (\"value\" in svg) figure.value = svg.value, delete svg.value;\n }\n figure.scale = exposeScales(scales2.scales);\n figure.legend = exposeLegends(scaleDescriptors, context, options);\n const w = consumeWarnings();\n if (w > 0) {\n select_default2(svg).append(\"text\").attr(\"x\", width2).attr(\"y\", 20).attr(\"dy\", \"-1em\").attr(\"text-anchor\", \"end\").attr(\"font-family\", \"initial\").text(\"\\u26A0\\uFE0F\").append(\"title\").text(`${w.toLocaleString(\"en-US\")} warning${w === 1 ? \"\" : \"s\"}. Please check the console.`);\n }\n return figure;\n}\nfunction createTitleElement(document2, contents, tag) {\n if (contents.ownerDocument) return contents;\n const e = document2.createElement(tag);\n e.append(contents);\n return e;\n}\nfunction createFigcaption(document2, caption) {\n const e = document2.createElement(\"figcaption\");\n e.append(caption);\n return e;\n}\nfunction flatMarks(marks2) {\n return marks2.flat(Infinity).filter((mark2) => mark2 != null).map(markify);\n}\nfunction markify(mark2) {\n return typeof mark2.render === \"function\" ? mark2 : new Render(mark2);\n}\nvar Render = class extends Mark {\n constructor(render) {\n if (typeof render !== \"function\") throw new TypeError(\"invalid mark; missing render function\");\n super();\n this.render = render;\n }\n render() {\n }\n};\nfunction applyScaleTransforms(channels, options) {\n for (const name2 in channels) applyScaleTransform(channels[name2], options);\n return channels;\n}\nfunction applyScaleTransform(channel, options) {\n const { scale: scale3, transform: t = true } = channel;\n if (scale3 == null || !t) return;\n const {\n type: type2,\n percent,\n interval: interval3,\n transform: transform3 = percent ? (x3) => x3 == null ? NaN : x3 * 100 : maybeIntervalTransform(interval3, type2)\n } = options[scale3] ?? {};\n if (transform3 == null) return;\n channel.value = map3(channel.value, transform3);\n channel.transform = false;\n}\nfunction inferChannelScales(channels) {\n for (const name2 in channels) {\n inferChannelScale(name2, channels[name2]);\n }\n}\nfunction addScaleChannels(channelsByScale, stateByMark, options, filter3 = yes) {\n for (const { channels } of stateByMark.values()) {\n for (const name2 in channels) {\n const channel = channels[name2];\n const { scale: scale3 } = channel;\n if (scale3 != null && filter3(scale3)) {\n if (scale3 === \"projection\") {\n if (!hasProjection(options)) {\n const gx = options.x?.domain === void 0;\n const gy = options.y?.domain === void 0;\n if (gx || gy) {\n const [x3, y3] = getGeometryChannels(channel);\n if (gx) addScaleChannel(channelsByScale, \"x\", x3);\n if (gy) addScaleChannel(channelsByScale, \"y\", y3);\n }\n }\n } else {\n addScaleChannel(channelsByScale, scale3, channel);\n }\n }\n }\n }\n return channelsByScale;\n}\nfunction addScaleChannel(channelsByScale, scale3, channel) {\n const scaleChannels = channelsByScale.get(scale3);\n if (scaleChannels !== void 0) scaleChannels.push(channel);\n else channelsByScale.set(scale3, [channel]);\n}\nfunction maybeTopFacet(facet, options) {\n if (facet == null) return;\n const { x: x3, y: y3 } = facet;\n if (x3 == null && y3 == null) return;\n const data = dataify(facet.data);\n if (data == null) throw new Error(\"missing facet data\");\n const channels = {};\n if (x3 != null) channels.fx = createChannel(data, { value: x3, scale: \"fx\" });\n if (y3 != null) channels.fy = createChannel(data, { value: y3, scale: \"fy\" });\n applyScaleTransforms(channels, options);\n const groups2 = facetGroups(data, channels);\n return { channels, groups: groups2, data: facet.data };\n}\nfunction maybeMarkFacet(mark2, topFacetState, options) {\n if (mark2.facet === null || mark2.facet === \"super\") return;\n const { fx, fy } = mark2;\n if (fx != null || fy != null) {\n const data2 = dataify(mark2.data ?? fx ?? fy);\n if (data2 === void 0) throw new Error(`missing facet data in ${mark2.ariaLabel}`);\n if (data2 === null) return;\n const channels2 = {};\n if (fx != null) channels2.fx = createChannel(data2, { value: fx, scale: \"fx\" });\n if (fy != null) channels2.fy = createChannel(data2, { value: fy, scale: \"fy\" });\n applyScaleTransforms(channels2, options);\n return { channels: channels2, groups: facetGroups(data2, channels2) };\n }\n if (topFacetState === void 0) return;\n const { channels, groups: groups2, data } = topFacetState;\n if (mark2.facet !== \"auto\" || mark2.data === data) return { channels, groups: groups2 };\n if (data.length > 0 && (groups2.size > 1 || groups2.size === 1 && channels.fx && channels.fy && [...groups2][0][1].size > 1) && lengthof(dataify(mark2.data)) === lengthof(data)) {\n warn(\n `Warning: the ${mark2.ariaLabel} mark appears to use faceted data, but isn\\u2019t faceted. The mark data has the same length as the facet data and the mark facet option is \"auto\", but the mark data and facet data are distinct. If this mark should be faceted, set the mark facet option to true; otherwise, suppress this warning by setting the mark facet option to false.`\n );\n }\n}\nfunction derive(mark2, options = {}) {\n return initializer({ ...options, x: null, y: null }, (data, facets, channels, scales2, dimensions, context) => {\n return context.getMarkState(mark2);\n });\n}\nfunction inferTips(marks2) {\n const tips = [];\n for (const mark2 of marks2) {\n let tipOptions = mark2.tip;\n if (tipOptions) {\n if (tipOptions === true) tipOptions = {};\n else if (typeof tipOptions === \"string\") tipOptions = { pointer: tipOptions };\n let { pointer: p, preferredAnchor: a2 } = tipOptions;\n p = /^x$/i.test(p) ? pointerX : /^y$/i.test(p) ? pointerY : pointer;\n tipOptions = p(derive(mark2, tipOptions));\n tipOptions.title = null;\n if (a2 === void 0) tipOptions.preferredAnchor = p === pointerY ? \"left\" : \"bottom\";\n const t = tip(mark2.data, tipOptions);\n t.facet = mark2.facet;\n t.facetAnchor = mark2.facetAnchor;\n tips.push(t);\n }\n }\n return tips;\n}\nfunction inferAxes(marks2, channelsByScale, options) {\n let {\n projection: projection3,\n x: x3 = {},\n y: y3 = {},\n fx = {},\n fy = {},\n axis: axis3,\n grid: grid2,\n facet = {},\n facet: { axis: facetAxis = axis3, grid: facetGrid2 } = facet,\n x: { axis: xAxis2 = axis3, grid: xGrid2 = xAxis2 === null ? null : grid2 } = x3,\n y: { axis: yAxis2 = axis3, grid: yGrid2 = yAxis2 === null ? null : grid2 } = y3,\n fx: { axis: fxAxis2 = facetAxis, grid: fxGrid2 = fxAxis2 === null ? null : facetGrid2 } = fx,\n fy: { axis: fyAxis2 = facetAxis, grid: fyGrid2 = fyAxis2 === null ? null : facetGrid2 } = fy\n } = options;\n if (projection3 || !isScaleOptions(x3) && !hasPositionChannel(\"x\", marks2)) xAxis2 = xGrid2 = null;\n if (projection3 || !isScaleOptions(y3) && !hasPositionChannel(\"y\", marks2)) yAxis2 = yGrid2 = null;\n if (!channelsByScale.has(\"fx\")) fxAxis2 = fxGrid2 = null;\n if (!channelsByScale.has(\"fy\")) fyAxis2 = fyGrid2 = null;\n if (xAxis2 === void 0) xAxis2 = !hasAxis(marks2, \"x\");\n if (yAxis2 === void 0) yAxis2 = !hasAxis(marks2, \"y\");\n if (fxAxis2 === void 0) fxAxis2 = !hasAxis(marks2, \"fx\");\n if (fyAxis2 === void 0) fyAxis2 = !hasAxis(marks2, \"fy\");\n if (xAxis2 === true) xAxis2 = \"bottom\";\n if (yAxis2 === true) yAxis2 = \"left\";\n if (fxAxis2 === true) fxAxis2 = xAxis2 === \"top\" || xAxis2 === null ? \"bottom\" : \"top\";\n if (fyAxis2 === true) fyAxis2 = yAxis2 === \"right\" || yAxis2 === null ? \"left\" : \"right\";\n const axes = [];\n maybeGrid(axes, fyGrid2, gridFy, fy);\n maybeAxis(axes, fyAxis2, axisFy, \"right\", \"left\", facet, fy);\n maybeGrid(axes, fxGrid2, gridFx, fx);\n maybeAxis(axes, fxAxis2, axisFx, \"top\", \"bottom\", facet, fx);\n maybeGrid(axes, yGrid2, gridY, y3);\n maybeAxis(axes, yAxis2, axisY, \"left\", \"right\", options, y3);\n maybeGrid(axes, xGrid2, gridX, x3);\n maybeAxis(axes, xAxis2, axisX, \"bottom\", \"top\", options, x3);\n return axes;\n}\nfunction maybeAxis(axes, axis3, axisType, primary, secondary, defaults22, options) {\n if (!axis3) return;\n const both = isBoth(axis3);\n options = axisOptions(both ? primary : axis3, defaults22, options);\n const { line: line3 } = options;\n if ((axisType === axisY || axisType === axisX) && line3 && !isNone(line3)) axes.push(frame2(lineOptions(options)));\n axes.push(axisType(options));\n if (both) axes.push(axisType({ ...options, anchor: secondary, label: null }));\n}\nfunction maybeGrid(axes, grid2, gridType, options) {\n if (!grid2 || isNone(grid2)) return;\n axes.push(gridType(gridOptions(grid2, options)));\n}\nfunction isBoth(value) {\n return /^\\s*both\\s*$/i.test(value);\n}\nfunction axisOptions(anchor, defaults22, {\n line: line3 = defaults22.line,\n ticks: ticks2,\n tickSize,\n tickSpacing,\n tickPadding,\n tickFormat: tickFormat2,\n tickRotate,\n fontVariant,\n ariaLabel,\n ariaDescription,\n label: label2 = defaults22.label,\n labelAnchor,\n labelArrow = defaults22.labelArrow,\n labelOffset\n}) {\n return {\n anchor,\n line: line3,\n ticks: ticks2,\n tickSize,\n tickSpacing,\n tickPadding,\n tickFormat: tickFormat2,\n tickRotate,\n fontVariant,\n ariaLabel,\n ariaDescription,\n label: label2,\n labelAnchor,\n labelArrow,\n labelOffset\n };\n}\nfunction lineOptions(options) {\n const { anchor, line: line3 } = options;\n return { anchor, facetAnchor: anchor + \"-empty\", stroke: line3 === true ? void 0 : line3 };\n}\nfunction gridOptions(grid2, {\n stroke = isColor(grid2) ? grid2 : void 0,\n ticks: ticks2 = isGridTicks(grid2) ? grid2 : void 0,\n tickSpacing,\n ariaLabel,\n ariaDescription\n}) {\n return {\n stroke,\n ticks: ticks2,\n tickSpacing,\n ariaLabel,\n ariaDescription\n };\n}\nfunction isGridTicks(grid2) {\n switch (typeof grid2) {\n case \"number\":\n return true;\n case \"string\":\n return !isColor(grid2);\n }\n return isIterable(grid2) || typeof grid2?.range === \"function\";\n}\nfunction hasAxis(marks2, k2) {\n const prefix2 = `${k2}-axis `;\n return marks2.some((m) => m.ariaLabel?.startsWith(prefix2));\n}\nfunction hasPositionChannel(k2, marks2) {\n for (const mark2 of marks2) {\n for (const key in mark2.channels) {\n const { scale: scale3 } = mark2.channels[key];\n if (scale3 === k2 || scale3 === \"projection\") {\n return true;\n }\n }\n }\n return false;\n}\nfunction inheritScaleLabels(newScales, scales2) {\n for (const key in newScales) {\n const newScale = newScales[key];\n const scale3 = scales2[key];\n if (newScale.label === void 0 && scale3) {\n newScale.label = scale3.label;\n }\n }\n return newScales;\n}\nfunction actualDimensions({ fx, fy }, dimensions) {\n const { marginTop: marginTop2, marginRight: marginRight2, marginBottom: marginBottom2, marginLeft: marginLeft2, width: width2, height: height2 } = outerDimensions(dimensions);\n const fxr = fx && outerRange(fx);\n const fyr = fy && outerRange(fy);\n return {\n marginTop: fy ? fyr[0] : marginTop2,\n marginRight: fx ? width2 - fxr[1] : marginRight2,\n marginBottom: fy ? height2 - fyr[1] : marginBottom2,\n marginLeft: fx ? fxr[0] : marginLeft2,\n // Some marks, namely the x- and y-axis labels, want to know what the\n // desired (rather than actual) margins are for positioning.\n inset: {\n marginTop: dimensions.marginTop,\n marginRight: dimensions.marginRight,\n marginBottom: dimensions.marginBottom,\n marginLeft: dimensions.marginLeft\n },\n width: width2,\n height: height2\n };\n}\nfunction outerRange(scale3) {\n const domain = scale3.domain();\n if (domain.length === 0) return [0, scale3.bandwidth()];\n let x12 = scale3(domain[0]);\n let x22 = scale3(domain[domain.length - 1]);\n if (x22 < x12) [x12, x22] = [x22, x12];\n return [x12, x22 + scale3.bandwidth()];\n}\n\n// ../../node_modules/@observablehq/plot/src/curve.js\nvar curves = /* @__PURE__ */ new Map([\n [\"basis\", basis_default2],\n [\"basis-closed\", basisClosed_default2],\n [\"basis-open\", basisOpen_default],\n [\"bundle\", bundle_default],\n [\"bump-x\", bumpX],\n [\"bump-y\", bumpY],\n [\"cardinal\", cardinal_default],\n [\"cardinal-closed\", cardinalClosed_default],\n [\"cardinal-open\", cardinalOpen_default],\n [\"catmull-rom\", catmullRom_default],\n [\"catmull-rom-closed\", catmullRomClosed_default],\n [\"catmull-rom-open\", catmullRomOpen_default],\n [\"linear\", linear_default],\n [\"linear-closed\", linearClosed_default],\n [\"monotone-x\", monotoneX],\n [\"monotone-y\", monotoneY],\n [\"natural\", natural_default],\n [\"step\", step_default],\n [\"step-after\", stepAfter],\n [\"step-before\", stepBefore]\n]);\nfunction maybeCurve(curve = linear_default, tension) {\n if (typeof curve === \"function\") return curve;\n const c4 = curves.get(`${curve}`.toLowerCase());\n if (!c4) throw new Error(`unknown curve: ${curve}`);\n if (tension !== void 0) {\n if (\"beta\" in c4) {\n return c4.beta(tension);\n } else if (\"tension\" in c4) {\n return c4.tension(tension);\n } else if (\"alpha\" in c4) {\n return c4.alpha(tension);\n }\n }\n return c4;\n}\nfunction maybeCurveAuto(curve = curveAuto, tension) {\n return typeof curve !== \"function\" && `${curve}`.toLowerCase() === \"auto\" ? curveAuto : maybeCurve(curve, tension);\n}\nfunction curveAuto(context) {\n return linear_default(context);\n}\n\n// ../../node_modules/@observablehq/plot/src/transforms/bin.js\nfunction binX(outputs = { y: \"count\" }, options = {}) {\n [outputs, options] = mergeOptions2(outputs, options);\n const { x: x3, y: y3 } = options;\n return binn(maybeBinValue(x3, options, identity7), null, null, y3, outputs, maybeInsetX(options));\n}\nfunction binY(outputs = { x: \"count\" }, options = {}) {\n [outputs, options] = mergeOptions2(outputs, options);\n const { x: x3, y: y3 } = options;\n return binn(null, maybeBinValue(y3, options, identity7), x3, null, outputs, maybeInsetY(options));\n}\nfunction bin(outputs = { fill: \"count\" }, options = {}) {\n [outputs, options] = mergeOptions2(outputs, options);\n const { x: x3, y: y3 } = maybeBinValueTuple(options);\n return binn(x3, y3, null, null, outputs, maybeInsetX(maybeInsetY(options)));\n}\nfunction maybeDenseInterval(bin3, k2, options = {}) {\n if (options?.interval == null) return options;\n const { reduce = reduceFirst } = options;\n const outputs = { filter: null };\n if (options[k2] != null) outputs[k2] = reduce;\n if (options[`${k2}1`] != null) outputs[`${k2}1`] = reduce;\n if (options[`${k2}2`] != null) outputs[`${k2}2`] = reduce;\n return bin3(outputs, options);\n}\nfunction maybeDenseIntervalX(options = {}) {\n return maybeDenseInterval(binX, \"y\", withTip(options, \"x\"));\n}\nfunction maybeDenseIntervalY(options = {}) {\n return maybeDenseInterval(binY, \"x\", withTip(options, \"y\"));\n}\nfunction binn(bx, by, gx, gy, {\n data: reduceData = reduceIdentity,\n // TODO avoid materializing when unused?\n filter: filter3 = reduceCount,\n // return only non-empty bins by default\n sort: sort3,\n reverse: reverse3,\n ...outputs\n // output channel definitions\n} = {}, inputs = {}) {\n bx = maybeBin(bx);\n by = maybeBin(by);\n outputs = maybeBinOutputs(outputs, inputs);\n reduceData = maybeBinReduce(reduceData, identity7);\n sort3 = sort3 == null ? void 0 : maybeBinOutput(\"sort\", sort3, inputs);\n filter3 = filter3 == null ? void 0 : maybeBinEvaluator(\"filter\", filter3, inputs);\n if (gx != null && hasOutput(outputs, \"x\", \"x1\", \"x2\")) gx = null;\n if (gy != null && hasOutput(outputs, \"y\", \"y1\", \"y2\")) gy = null;\n const [BX1, setBX1] = maybeColumn(bx);\n const [BX2, setBX2] = maybeColumn(bx);\n const [BY1, setBY1] = maybeColumn(by);\n const [BY2, setBY2] = maybeColumn(by);\n const [k2, gk] = gx != null ? [gx, \"x\"] : gy != null ? [gy, \"y\"] : [];\n const [GK, setGK] = maybeColumn(k2);\n const {\n x: x3,\n y: y3,\n z,\n fill,\n stroke,\n x1: x12,\n x2: x22,\n // consumed if x is an output\n y1: y12,\n y2: y22,\n // consumed if y is an output\n domain,\n cumulative,\n thresholds,\n interval: interval3,\n ...options\n } = inputs;\n const [GZ, setGZ] = maybeColumn(z);\n const [vfill] = maybeColorChannel(fill);\n const [vstroke] = maybeColorChannel(stroke);\n const [GF, setGF] = maybeColumn(vfill);\n const [GS, setGS] = maybeColumn(vstroke);\n return {\n ...\"z\" in inputs && { z: GZ || z },\n ...\"fill\" in inputs && { fill: GF || fill },\n ...\"stroke\" in inputs && { stroke: GS || stroke },\n ...basic(options, (data, facets, plotOptions) => {\n const K2 = maybeApplyInterval(valueof(data, k2), plotOptions?.[gk]);\n const Z = valueof(data, z);\n const F = valueof(data, vfill);\n const S = valueof(data, vstroke);\n const G = maybeSubgroup(outputs, { z: Z, fill: F, stroke: S });\n const groupFacets = [];\n const groupData = [];\n const GK2 = K2 && setGK([]);\n const GZ2 = Z && setGZ([]);\n const GF2 = F && setGF([]);\n const GS2 = S && setGS([]);\n const BX12 = bx && setBX1([]);\n const BX22 = bx && setBX2([]);\n const BY12 = by && setBY1([]);\n const BY22 = by && setBY2([]);\n const bin3 = bing(bx, by, data);\n let i = 0;\n for (const o of outputs) o.initialize(data);\n if (sort3) sort3.initialize(data);\n if (filter3) filter3.initialize(data);\n for (const facet of facets) {\n const groupFacet = [];\n for (const o of outputs) o.scope(\"facet\", facet);\n if (sort3) sort3.scope(\"facet\", facet);\n if (filter3) filter3.scope(\"facet\", facet);\n for (const [f, I] of maybeGroup(facet, G)) {\n for (const [k3, g] of maybeGroup(I, K2)) {\n for (const [b, extent4] of bin3(g)) {\n if (G) extent4.z = f;\n if (filter3 && !filter3.reduce(b, extent4)) continue;\n groupFacet.push(i++);\n groupData.push(reduceData.reduceIndex(b, data, extent4));\n if (K2) GK2.push(k3);\n if (Z) GZ2.push(G === Z ? f : Z[(b.length > 0 ? b : g)[0]]);\n if (F) GF2.push(G === F ? f : F[(b.length > 0 ? b : g)[0]]);\n if (S) GS2.push(G === S ? f : S[(b.length > 0 ? b : g)[0]]);\n if (BX12) BX12.push(extent4.x1), BX22.push(extent4.x2);\n if (BY12) BY12.push(extent4.y1), BY22.push(extent4.y2);\n for (const o of outputs) o.reduce(b, extent4);\n if (sort3) sort3.reduce(b, extent4);\n }\n }\n }\n groupFacets.push(groupFacet);\n }\n maybeSort(groupFacets, sort3, reverse3);\n return { data: groupData, facets: groupFacets };\n }),\n ...!hasOutput(outputs, \"x\") && (BX1 ? { x1: BX1, x2: BX2, x: mid(BX1, BX2) } : { x: x3, x1: x12, x2: x22 }),\n ...!hasOutput(outputs, \"y\") && (BY1 ? { y1: BY1, y2: BY2, y: mid(BY1, BY2) } : { y: y3, y1: y12, y2: y22 }),\n ...GK && { [gk]: GK },\n ...Object.fromEntries(outputs.map(({ name: name2, output }) => [name2, output]))\n };\n}\nfunction mergeOptions2({ cumulative, domain, thresholds, interval: interval3, ...outputs }, options) {\n return [outputs, { cumulative, domain, thresholds, interval: interval3, ...options }];\n}\nfunction maybeBinValue(value, { cumulative, domain, thresholds, interval: interval3 }, defaultValue) {\n value = { ...maybeValue(value) };\n if (value.domain === void 0) value.domain = domain;\n if (value.cumulative === void 0) value.cumulative = cumulative;\n if (value.thresholds === void 0) value.thresholds = thresholds;\n if (value.interval === void 0) value.interval = interval3;\n if (value.value === void 0) value.value = defaultValue;\n value.thresholds = maybeThresholds(value.thresholds, value.interval);\n return value;\n}\nfunction maybeBinValueTuple(options) {\n let { x: x3, y: y3 } = options;\n x3 = maybeBinValue(x3, options);\n y3 = maybeBinValue(y3, options);\n [x3.value, y3.value] = maybeTuple(x3.value, y3.value);\n return { x: x3, y: y3 };\n}\nfunction maybeBin(options) {\n if (options == null) return;\n const { value, cumulative, domain = extent, thresholds } = options;\n const bin3 = (data) => {\n let V = valueof(data, value);\n let T;\n if (isTemporal(V) || isTimeThresholds(thresholds)) {\n V = map3(V, coerceDate, Float64Array);\n let [min5, max4] = typeof domain === \"function\" ? domain(V) : domain;\n let t = typeof thresholds === \"function\" && !isInterval(thresholds) ? thresholds(V, min5, max4) : thresholds;\n if (typeof t === \"number\") t = utcTickInterval(min5, max4, t);\n if (isInterval(t)) {\n if (domain === extent) {\n min5 = t.floor(min5);\n max4 = t.offset(t.floor(max4));\n }\n t = t.range(min5, t.offset(max4));\n }\n T = t;\n } else {\n V = coerceNumbers(V);\n let [min5, max4] = typeof domain === \"function\" ? domain(V) : domain;\n let t = typeof thresholds === \"function\" && !isInterval(thresholds) ? thresholds(V, min5, max4) : thresholds;\n if (typeof t === \"number\") {\n if (domain === extent) {\n let step = tickIncrement(min5, max4, t);\n if (isFinite(step)) {\n if (step > 0) {\n let r0 = Math.round(min5 / step);\n let r1 = Math.round(max4 / step);\n if (!(r0 * step <= min5)) --r0;\n if (!(r1 * step > max4)) ++r1;\n let n = r1 - r0 + 1;\n t = new Float64Array(n);\n for (let i = 0; i < n; ++i) t[i] = (r0 + i) * step;\n } else if (step < 0) {\n step = -step;\n let r0 = Math.round(min5 * step);\n let r1 = Math.round(max4 * step);\n if (!(r0 / step <= min5)) --r0;\n if (!(r1 / step > max4)) ++r1;\n let n = r1 - r0 + 1;\n t = new Float64Array(n);\n for (let i = 0; i < n; ++i) t[i] = (r0 + i) / step;\n } else {\n t = [min5];\n }\n } else {\n t = [min5];\n }\n } else {\n t = ticks(min5, max4, t);\n }\n } else if (isInterval(t)) {\n if (domain === extent) {\n min5 = t.floor(min5);\n max4 = t.offset(t.floor(max4));\n }\n t = t.range(min5, t.offset(max4));\n }\n T = t;\n }\n const E2 = [];\n if (T.length === 1) E2.push([T[0], T[0]]);\n else for (let i = 1; i < T.length; ++i) E2.push([T[i - 1], T[i]]);\n E2.bin = (cumulative < 0 ? bin1cn : cumulative > 0 ? bin1cp : bin1)(E2, T, V);\n return E2;\n };\n bin3.label = labelof(value);\n return bin3;\n}\nfunction maybeThresholds(thresholds, interval3, defaultThresholds = thresholdAuto) {\n if (thresholds === void 0) {\n return interval3 === void 0 ? defaultThresholds : maybeRangeInterval(interval3);\n }\n if (typeof thresholds === \"string\") {\n switch (thresholds.toLowerCase()) {\n case \"freedman-diaconis\":\n return thresholdFreedmanDiaconis;\n case \"scott\":\n return thresholdScott;\n case \"sturges\":\n return thresholdSturges;\n case \"auto\":\n return thresholdAuto;\n }\n return utcInterval(thresholds);\n }\n return thresholds;\n}\nfunction maybeBinOutputs(outputs, inputs) {\n return maybeOutputs(outputs, inputs, maybeBinOutput);\n}\nfunction maybeBinOutput(name2, reduce, inputs) {\n return maybeOutput(name2, reduce, inputs, maybeBinEvaluator);\n}\nfunction maybeBinEvaluator(name2, reduce, inputs) {\n return maybeEvaluator(name2, reduce, inputs, maybeBinReduce);\n}\nfunction maybeBinReduce(reduce, value) {\n return maybeReduce(reduce, value, maybeBinReduceFallback);\n}\nfunction maybeBinReduceFallback(reduce) {\n switch (`${reduce}`.toLowerCase()) {\n case \"x\":\n return reduceX2;\n case \"x1\":\n return reduceX1;\n case \"x2\":\n return reduceX22;\n case \"y\":\n return reduceY2;\n case \"y1\":\n return reduceY1;\n case \"y2\":\n return reduceY22;\n case \"z\":\n return reduceZ;\n }\n throw new Error(`invalid bin reduce: ${reduce}`);\n}\nfunction thresholdAuto(values2, min5, max4) {\n return Math.min(200, thresholdScott(values2, min5, max4));\n}\nfunction isTimeThresholds(t) {\n return isTimeInterval(t) || isIterable(t) && isTemporal(t);\n}\nfunction bing(bx, by, data) {\n const EX = bx?.(data);\n const EY = by?.(data);\n return EX && EY ? function* (I) {\n const X3 = EX.bin(I);\n for (const [ix, [x12, x22]] of EX.entries()) {\n const Y3 = EY.bin(X3[ix]);\n for (const [iy, [y12, y22]] of EY.entries()) {\n yield [Y3[iy], { data, x1: x12, y1: y12, x2: x22, y2: y22 }];\n }\n }\n } : EX ? function* (I) {\n const X3 = EX.bin(I);\n for (const [i, [x12, x22]] of EX.entries()) {\n yield [X3[i], { data, x1: x12, x2: x22 }];\n }\n } : function* (I) {\n const Y3 = EY.bin(I);\n for (const [i, [y12, y22]] of EY.entries()) {\n yield [Y3[i], { data, y1: y12, y2: y22 }];\n }\n };\n}\nfunction bin1(E2, T, V) {\n T = coerceNumbers(T);\n return (I) => {\n const B3 = E2.map(() => []);\n for (const i of I) B3[bisect_default(T, V[i]) - 1]?.push(i);\n return B3;\n };\n}\nfunction bin1cp(E2, T, V) {\n const bin3 = bin1(E2, T, V);\n return (I) => {\n const B3 = bin3(I);\n for (let i = 1, n = B3.length; i < n; ++i) {\n const C3 = B3[i - 1];\n const b = B3[i];\n for (const j of C3) b.push(j);\n }\n return B3;\n };\n}\nfunction bin1cn(E2, T, V) {\n const bin3 = bin1(E2, T, V);\n return (I) => {\n const B3 = bin3(I);\n for (let i = B3.length - 2; i >= 0; --i) {\n const C3 = B3[i + 1];\n const b = B3[i];\n for (const j of C3) b.push(j);\n }\n return B3;\n };\n}\nfunction mid1(x12, x22) {\n const m = (+x12 + +x22) / 2;\n return x12 instanceof Date ? new Date(m) : m;\n}\nvar reduceX2 = {\n reduceIndex(I, X3, { x1: x12, x2: x22 }) {\n return mid1(x12, x22);\n }\n};\nvar reduceY2 = {\n reduceIndex(I, X3, { y1: y12, y2: y22 }) {\n return mid1(y12, y22);\n }\n};\nvar reduceX1 = {\n reduceIndex(I, X3, { x1: x12 }) {\n return x12;\n }\n};\nvar reduceX22 = {\n reduceIndex(I, X3, { x2: x22 }) {\n return x22;\n }\n};\nvar reduceY1 = {\n reduceIndex(I, X3, { y1: y12 }) {\n return y12;\n }\n};\nvar reduceY22 = {\n reduceIndex(I, X3, { y2: y22 }) {\n return y22;\n }\n};\n\n// ../../node_modules/@observablehq/plot/src/marks/area.js\nvar defaults7 = {\n ariaLabel: \"area\",\n strokeWidth: 1,\n strokeLinecap: \"round\",\n strokeLinejoin: \"round\",\n strokeMiterlimit: 1\n};\nvar Area = class extends Mark {\n constructor(data, options = {}) {\n const { x1: x12, y1: y12, x2: x22, y2: y22, z, curve, tension } = options;\n super(\n data,\n {\n x1: { value: x12, scale: \"x\" },\n y1: { value: y12, scale: \"y\" },\n x2: { value: x22, scale: \"x\", optional: true },\n y2: { value: y22, scale: \"y\", optional: true },\n z: { value: maybeZ(options), optional: true }\n },\n options,\n defaults7\n );\n this.z = z;\n this.curve = maybeCurve(curve, tension);\n }\n filter(index2) {\n return index2;\n }\n render(index2, scales2, channels, dimensions, context) {\n const { x1: X13, y1: Y13, x2: X23 = X13, y2: Y23 = Y13 } = channels;\n return create4(\"svg:g\", context).call(applyIndirectStyles, this, dimensions, context).call(applyTransform, this, scales2, 0, 0).call(\n (g) => g.selectAll().data(groupIndex(index2, [X13, Y13, X23, Y23], this, channels)).enter().append(\"path\").call(applyDirectStyles, this).call(applyGroupedChannelStyles, this, channels).attr(\n \"d\",\n area_default3().curve(this.curve).defined((i) => i >= 0).x0((i) => X13[i]).y0((i) => Y13[i]).x1((i) => X23[i]).y1((i) => Y23[i])\n )\n ).node();\n }\n};\nfunction area(data, options) {\n if (options === void 0) return areaY(data, { x: first2, y: second2 });\n return new Area(data, options);\n}\nfunction areaX(data, options) {\n const { y: y3 = indexOf, ...rest } = maybeDenseIntervalY(options);\n return new Area(data, maybeStackX(maybeIdentityX({ ...rest, y1: y3, y2: void 0 })));\n}\nfunction areaY(data, options) {\n const { x: x3 = indexOf, ...rest } = maybeDenseIntervalX(options);\n return new Area(data, maybeStackY(maybeIdentityY({ ...rest, x1: x3, x2: void 0 })));\n}\n\n// ../../node_modules/@observablehq/plot/src/marks/link.js\nvar defaults8 = {\n ariaLabel: \"link\",\n fill: \"none\",\n stroke: \"currentColor\",\n strokeMiterlimit: 1\n};\nvar Link = class extends Mark {\n constructor(data, options = {}) {\n const { x1: x12, y1: y12, x2: x22, y2: y22, curve, tension } = options;\n super(\n data,\n {\n x1: { value: x12, scale: \"x\" },\n y1: { value: y12, scale: \"y\" },\n x2: { value: x22, scale: \"x\", optional: true },\n y2: { value: y22, scale: \"y\", optional: true }\n },\n options,\n defaults8\n );\n this.curve = maybeCurveAuto(curve, tension);\n markers(this, options);\n }\n project(channels, values2, context) {\n if (this.curve !== curveAuto) {\n super.project(channels, values2, context);\n }\n }\n render(index2, scales2, channels, dimensions, context) {\n const { x1: X13, y1: Y13, x2: X23 = X13, y2: Y23 = Y13 } = channels;\n const { curve } = this;\n return create4(\"svg:g\", context).call(applyIndirectStyles, this, dimensions, context).call(applyTransform, this, scales2).call(\n (g) => g.selectAll().data(index2).enter().append(\"path\").call(applyDirectStyles, this).attr(\n \"d\",\n curve === curveAuto && context.projection ? sphereLink(context.projection, X13, Y13, X23, Y23) : (i) => {\n const p = pathRound();\n const c4 = curve(p);\n c4.lineStart();\n c4.point(X13[i], Y13[i]);\n c4.point(X23[i], Y23[i]);\n c4.lineEnd();\n return p;\n }\n ).call(applyChannelStyles, this, channels).call(applyMarkers, this, channels, context)\n ).node();\n }\n};\nfunction sphereLink(projection3, X13, Y13, X23, Y23) {\n const path2 = path_default(projection3);\n X13 = coerceNumbers(X13);\n Y13 = coerceNumbers(Y13);\n X23 = coerceNumbers(X23);\n Y23 = coerceNumbers(Y23);\n return (i) => path2({\n type: \"LineString\",\n coordinates: [\n [X13[i], Y13[i]],\n [X23[i], Y23[i]]\n ]\n });\n}\nfunction link2(data, { x: x3, x1: x12, x2: x22, y: y3, y1: y12, y2: y22, ...options } = {}) {\n [x12, x22] = maybeSameValue(x3, x12, x22);\n [y12, y22] = maybeSameValue(y3, y12, y22);\n return new Link(data, { ...options, x1: x12, x2: x22, y1: y12, y2: y22 });\n}\nfunction maybeSameValue(x3, x12, x22) {\n if (x3 === void 0) {\n if (x12 === void 0) {\n if (x22 !== void 0) return [x22];\n } else {\n if (x22 === void 0) return [x12];\n }\n } else if (x12 === void 0) {\n return x22 === void 0 ? [x3] : [x3, x22];\n } else if (x22 === void 0) {\n return [x3, x12];\n }\n return [x12, x22];\n}\n\n// ../../node_modules/@observablehq/plot/src/marks/arrow.js\nvar defaults9 = {\n ariaLabel: \"arrow\",\n fill: \"none\",\n stroke: \"currentColor\",\n strokeLinecap: \"round\",\n strokeMiterlimit: 1,\n strokeWidth: 1.5\n};\nvar Arrow = class extends Mark {\n constructor(data, options = {}) {\n const {\n x1: x12,\n y1: y12,\n x2: x22,\n y2: y22,\n bend = 0,\n headAngle = 60,\n headLength = 8,\n // Disable the arrow with headLength = 0; or, use Plot.link.\n inset: inset2 = 0,\n insetStart = inset2,\n insetEnd = inset2,\n sweep\n } = options;\n super(\n data,\n {\n x1: { value: x12, scale: \"x\" },\n y1: { value: y12, scale: \"y\" },\n x2: { value: x22, scale: \"x\", optional: true },\n y2: { value: y22, scale: \"y\", optional: true }\n },\n options,\n defaults9\n );\n this.bend = bend === true ? 22.5 : Math.max(-90, Math.min(90, bend));\n this.headAngle = +headAngle;\n this.headLength = +headLength;\n this.insetStart = +insetStart;\n this.insetEnd = +insetEnd;\n this.sweep = maybeSweep(sweep);\n }\n render(index2, scales2, channels, dimensions, context) {\n const { x1: X13, y1: Y13, x2: X23 = X13, y2: Y23 = Y13, SW } = channels;\n const { strokeWidth, bend, headAngle, headLength, insetStart, insetEnd } = this;\n const sw = SW ? (i) => SW[i] : constant(strokeWidth === void 0 ? 1 : strokeWidth);\n const wingAngle = headAngle * radians3 / 2;\n const wingScale = headLength / 1.5;\n return create4(\"svg:g\", context).call(applyIndirectStyles, this, dimensions, context).call(applyTransform, this, scales2).call(\n (g) => g.selectAll().data(index2).enter().append(\"path\").call(applyDirectStyles, this).attr(\"d\", (i) => {\n let x12 = X13[i], y12 = Y13[i], x22 = X23[i], y22 = Y23[i];\n const lineLength = Math.hypot(x22 - x12, y22 - y12);\n if (lineLength <= insetStart + insetEnd) return null;\n let lineAngle = Math.atan2(y22 - y12, x22 - x12);\n const headLength2 = Math.min(wingScale * sw(i), lineLength / 3);\n const bendAngle = this.sweep(x12, y12, x22, y22) * bend * radians3;\n const r = Math.hypot(lineLength / Math.tan(bendAngle), lineLength) / 2;\n if (insetStart || insetEnd) {\n if (r < 1e5) {\n const sign3 = Math.sign(bendAngle);\n const [cx, cy] = pointPointCenter([x12, y12], [x22, y22], r, sign3);\n if (insetStart) {\n [x12, y12] = circleCircleIntersect([cx, cy, r], [x12, y12, insetStart], -sign3 * Math.sign(insetStart));\n }\n if (insetEnd) {\n const [x5, y5] = circleCircleIntersect([cx, cy, r], [x22, y22, insetEnd], sign3 * Math.sign(insetEnd));\n lineAngle += Math.atan2(y5 - cy, x5 - cx) - Math.atan2(y22 - cy, x22 - cx);\n x22 = x5, y22 = y5;\n }\n } else {\n const dx = x22 - x12, dy = y22 - y12, d = Math.hypot(dx, dy);\n if (insetStart) x12 += dx / d * insetStart, y12 += dy / d * insetStart;\n if (insetEnd) x22 -= dx / d * insetEnd, y22 -= dy / d * insetEnd;\n }\n }\n const endAngle = lineAngle + bendAngle;\n const leftAngle = endAngle + wingAngle;\n const rightAngle = endAngle - wingAngle;\n const x3 = x22 - headLength2 * Math.cos(leftAngle);\n const y3 = y22 - headLength2 * Math.sin(leftAngle);\n const x4 = x22 - headLength2 * Math.cos(rightAngle);\n const y4 = y22 - headLength2 * Math.sin(rightAngle);\n const a2 = r < 1e5 ? `A${r},${r} 0,0,${bendAngle > 0 ? 1 : 0} ` : `L`;\n const h = headLength2 ? `M${x3},${y3}L${x22},${y22}L${x4},${y4}` : \"\";\n return `M${x12},${y12}${a2}${x22},${y22}${h}`;\n }).call(applyChannelStyles, this, channels)\n ).node();\n }\n};\nfunction maybeSweep(sweep = 1) {\n if (typeof sweep === \"number\") return constant(Math.sign(sweep));\n if (typeof sweep === \"function\") return (x12, y12, x22, y22) => Math.sign(sweep(x12, y12, x22, y22));\n switch (keyword(sweep, \"sweep\", [\"+x\", \"-x\", \"+y\", \"-y\"])) {\n case \"+x\":\n return (x12, y12, x22) => ascending(x12, x22);\n case \"-x\":\n return (x12, y12, x22) => descending(x12, x22);\n case \"+y\":\n return (x12, y12, x22, y22) => ascending(y12, y22);\n case \"-y\":\n return (x12, y12, x22, y22) => descending(y12, y22);\n }\n}\nfunction pointPointCenter([ax, ay], [bx, by], r, sign3) {\n const dx = bx - ax, dy = by - ay, d = Math.hypot(dx, dy);\n const k2 = sign3 * Math.sqrt(r * r - d * d / 4) / d;\n return [(ax + bx) / 2 - dy * k2, (ay + by) / 2 + dx * k2];\n}\nfunction circleCircleIntersect([ax, ay, ar], [bx, by, br], sign3) {\n const dx = bx - ax, dy = by - ay, d = Math.hypot(dx, dy);\n const x3 = (dx * dx + dy * dy - br * br + ar * ar) / (2 * d);\n const y3 = sign3 * Math.sqrt(ar * ar - x3 * x3);\n return [ax + (dx * x3 + dy * y3) / d, ay + (dy * x3 - dx * y3) / d];\n}\nfunction arrow(data, { x: x3, x1: x12, x2: x22, y: y3, y1: y12, y2: y22, ...options } = {}) {\n [x12, x22] = maybeSameValue(x3, x12, x22);\n [y12, y22] = maybeSameValue(y3, y12, y22);\n return new Arrow(data, { ...options, x1: x12, x2: x22, y1: y12, y2: y22 });\n}\n\n// ../../node_modules/@observablehq/plot/src/marks/bar.js\nvar barDefaults = {\n ariaLabel: \"bar\"\n};\nvar AbstractBar = class extends Mark {\n constructor(data, channels, options = {}, defaults22 = barDefaults) {\n super(data, channels, options, defaults22);\n rectInsets(this, options);\n rectRadii(this, options);\n }\n render(index2, scales2, channels, dimensions, context) {\n const { rx, ry, rx1y1, rx1y2, rx2y1, rx2y2 } = this;\n const x3 = this._x(scales2, channels, dimensions);\n const y3 = this._y(scales2, channels, dimensions);\n const w = this._width(scales2, channels, dimensions);\n const h = this._height(scales2, channels, dimensions);\n return create4(\"svg:g\", context).call(applyIndirectStyles, this, dimensions, context).call(this._transform, this, scales2).call(\n (g) => g.selectAll().data(index2).enter().call(\n rx1y1 || rx1y2 || rx2y1 || rx2y2 ? (g2) => g2.append(\"path\").call(applyDirectStyles, this).call(applyRoundedRect, x3, y3, add(x3, w), add(y3, h), this).call(applyChannelStyles, this, channels) : (g2) => g2.append(\"rect\").call(applyDirectStyles, this).attr(\"x\", x3).attr(\"width\", w).attr(\"y\", y3).attr(\"height\", h).call(applyAttr, \"rx\", rx).call(applyAttr, \"ry\", ry).call(applyChannelStyles, this, channels)\n )\n ).node();\n }\n _x(scales2, { x: X3 }, { marginLeft: marginLeft2 }) {\n const { insetLeft } = this;\n return X3 ? (i) => X3[i] + insetLeft : marginLeft2 + insetLeft;\n }\n _y(scales2, { y: Y3 }, { marginTop: marginTop2 }) {\n const { insetTop } = this;\n return Y3 ? (i) => Y3[i] + insetTop : marginTop2 + insetTop;\n }\n _width({ x: x3 }, { x: X3 }, { marginRight: marginRight2, marginLeft: marginLeft2, width: width2 }) {\n const { insetLeft, insetRight } = this;\n const bandwidth = X3 && x3 ? x3.bandwidth() : width2 - marginRight2 - marginLeft2;\n return Math.max(0, bandwidth - insetLeft - insetRight);\n }\n _height({ y: y3 }, { y: Y3 }, { marginTop: marginTop2, marginBottom: marginBottom2, height: height2 }) {\n const { insetTop, insetBottom } = this;\n const bandwidth = Y3 && y3 ? y3.bandwidth() : height2 - marginTop2 - marginBottom2;\n return Math.max(0, bandwidth - insetTop - insetBottom);\n }\n};\nfunction add(a2, b) {\n return typeof a2 === \"function\" && typeof b === \"function\" ? (i) => a2(i) + b(i) : typeof a2 === \"function\" ? (i) => a2(i) + b : typeof b === \"function\" ? (i) => a2 + b(i) : a2 + b;\n}\nvar BarX = class extends AbstractBar {\n constructor(data, options = {}, defaults22) {\n const { x1: x12, x2: x22, y: y3 } = options;\n super(\n data,\n {\n x1: { value: x12, scale: \"x\" },\n x2: { value: x22, scale: \"x\" },\n y: { value: y3, scale: \"y\", type: \"band\", optional: true }\n },\n options,\n defaults22\n );\n }\n _transform(selection2, mark2, { x: x3 }) {\n selection2.call(applyTransform, mark2, { x: x3 }, 0, 0);\n }\n _x({ x: x3 }, { x1: X13, x2: X23 }, { marginLeft: marginLeft2 }) {\n const { insetLeft } = this;\n return isCollapsed(x3) ? marginLeft2 + insetLeft : (i) => Math.min(X13[i], X23[i]) + insetLeft;\n }\n _width({ x: x3 }, { x1: X13, x2: X23 }, { marginRight: marginRight2, marginLeft: marginLeft2, width: width2 }) {\n const { insetLeft, insetRight } = this;\n return isCollapsed(x3) ? width2 - marginRight2 - marginLeft2 - insetLeft - insetRight : (i) => Math.max(0, Math.abs(X23[i] - X13[i]) - insetLeft - insetRight);\n }\n};\nvar BarY = class extends AbstractBar {\n constructor(data, options = {}, defaults22) {\n const { x: x3, y1: y12, y2: y22 } = options;\n super(\n data,\n {\n y1: { value: y12, scale: \"y\" },\n y2: { value: y22, scale: \"y\" },\n x: { value: x3, scale: \"x\", type: \"band\", optional: true }\n },\n options,\n defaults22\n );\n }\n _transform(selection2, mark2, { y: y3 }) {\n selection2.call(applyTransform, mark2, { y: y3 }, 0, 0);\n }\n _y({ y: y3 }, { y1: Y13, y2: Y23 }, { marginTop: marginTop2 }) {\n const { insetTop } = this;\n return isCollapsed(y3) ? marginTop2 + insetTop : (i) => Math.min(Y13[i], Y23[i]) + insetTop;\n }\n _height({ y: y3 }, { y1: Y13, y2: Y23 }, { marginTop: marginTop2, marginBottom: marginBottom2, height: height2 }) {\n const { insetTop, insetBottom } = this;\n return isCollapsed(y3) ? height2 - marginTop2 - marginBottom2 - insetTop - insetBottom : (i) => Math.max(0, Math.abs(Y23[i] - Y13[i]) - insetTop - insetBottom);\n }\n};\nfunction barX(data, options = {}) {\n if (!hasXY(options)) options = { ...options, y: indexOf, x2: identity7 };\n return new BarX(data, maybeStackX(maybeIntervalX(maybeIdentityX(options))));\n}\nfunction barY(data, options = {}) {\n if (!hasXY(options)) options = { ...options, x: indexOf, y2: identity7 };\n return new BarY(data, maybeStackY(maybeIntervalY(maybeIdentityY(options))));\n}\n\n// ../../node_modules/@observablehq/plot/src/marks/cell.js\nvar defaults10 = {\n ariaLabel: \"cell\"\n};\nvar Cell = class extends AbstractBar {\n constructor(data, { x: x3, y: y3, ...options } = {}) {\n super(\n data,\n {\n x: { value: x3, scale: \"x\", type: \"band\", optional: true },\n y: { value: y3, scale: \"y\", type: \"band\", optional: true }\n },\n options,\n defaults10\n );\n }\n _transform(selection2, mark2) {\n selection2.call(applyTransform, mark2, {}, 0, 0);\n }\n};\nfunction cell(data, { x: x3, y: y3, ...options } = {}) {\n [x3, y3] = maybeTuple(x3, y3);\n return new Cell(data, { ...options, x: x3, y: y3 });\n}\nfunction cellX(data, { x: x3 = indexOf, fill, stroke, ...options } = {}) {\n if (fill === void 0 && maybeColorChannel(stroke)[0] === void 0) fill = identity7;\n return new Cell(data, { ...options, x: x3, fill, stroke });\n}\nfunction cellY(data, { y: y3 = indexOf, fill, stroke, ...options } = {}) {\n if (fill === void 0 && maybeColorChannel(stroke)[0] === void 0) fill = identity7;\n return new Cell(data, { ...options, y: y3, fill, stroke });\n}\n\n// ../../node_modules/@observablehq/plot/src/marks/dot.js\nvar defaults11 = {\n ariaLabel: \"dot\",\n fill: \"none\",\n stroke: \"currentColor\",\n strokeWidth: 1.5\n};\nfunction withDefaultSort(options) {\n return options.sort === void 0 && options.reverse === void 0 ? sort2({ channel: \"-r\" }, options) : options;\n}\nvar Dot = class extends Mark {\n constructor(data, options = {}) {\n const { x: x3, y: y3, r, rotate, symbol: symbol2 = circle_default2, frameAnchor } = options;\n const [vrotate, crotate] = maybeNumberChannel(rotate, 0);\n const [vsymbol, csymbol] = maybeSymbolChannel(symbol2);\n const [vr, cr] = maybeNumberChannel(r, vsymbol == null ? 3 : 4.5);\n super(\n data,\n {\n x: { value: x3, scale: \"x\", optional: true },\n y: { value: y3, scale: \"y\", optional: true },\n r: { value: vr, scale: \"r\", filter: positive, optional: true },\n rotate: { value: vrotate, optional: true },\n symbol: { value: vsymbol, scale: \"auto\", optional: true }\n },\n withDefaultSort(options),\n defaults11\n );\n this.r = cr;\n this.rotate = crotate;\n this.symbol = csymbol;\n this.frameAnchor = maybeFrameAnchor(frameAnchor);\n const { channels } = this;\n const { symbol: symbolChannel } = channels;\n if (symbolChannel) {\n const { fill: fillChannel, stroke: strokeChannel } = channels;\n symbolChannel.hint = {\n fill: fillChannel ? fillChannel.value === symbolChannel.value ? \"color\" : \"currentColor\" : this.fill ?? \"currentColor\",\n stroke: strokeChannel ? strokeChannel.value === symbolChannel.value ? \"color\" : \"currentColor\" : this.stroke ?? \"none\"\n };\n }\n }\n render(index2, scales2, channels, dimensions, context) {\n const { x: x3, y: y3 } = scales2;\n const { x: X3, y: Y3, r: R, rotate: A5, symbol: S } = channels;\n const { r, rotate, symbol: symbol2 } = this;\n const [cx, cy] = applyFrameAnchor(this, dimensions);\n const circle3 = symbol2 === circle_default2;\n const size = R ? void 0 : r * r * Math.PI;\n if (negative(r)) index2 = [];\n return create4(\"svg:g\", context).call(applyIndirectStyles, this, dimensions, context).call(applyTransform, this, { x: X3 && x3, y: Y3 && y3 }).call(\n (g) => g.selectAll().data(index2).enter().append(circle3 ? \"circle\" : \"path\").call(applyDirectStyles, this).call(\n circle3 ? (selection2) => {\n selection2.attr(\"cx\", X3 ? (i) => X3[i] : cx).attr(\"cy\", Y3 ? (i) => Y3[i] : cy).attr(\"r\", R ? (i) => R[i] : r);\n } : (selection2) => {\n selection2.attr(\n \"transform\",\n template`translate(${X3 ? (i) => X3[i] : cx},${Y3 ? (i) => Y3[i] : cy})${A5 ? (i) => ` rotate(${A5[i]})` : rotate ? ` rotate(${rotate})` : ``}`\n ).attr(\n \"d\",\n R && S ? (i) => {\n const p = pathRound();\n S[i].draw(p, R[i] * R[i] * Math.PI);\n return p;\n } : R ? (i) => {\n const p = pathRound();\n symbol2.draw(p, R[i] * R[i] * Math.PI);\n return p;\n } : S ? (i) => {\n const p = pathRound();\n S[i].draw(p, size);\n return p;\n } : (() => {\n const p = pathRound();\n symbol2.draw(p, size);\n return p;\n })()\n );\n }\n ).call(applyChannelStyles, this, channels)\n ).node();\n }\n};\nfunction dot(data, { x: x3, y: y3, ...options } = {}) {\n if (options.frameAnchor === void 0) [x3, y3] = maybeTuple(x3, y3);\n return new Dot(data, { ...options, x: x3, y: y3 });\n}\nfunction dotX(data, { x: x3 = identity7, ...options } = {}) {\n return new Dot(data, maybeIntervalMidY({ ...options, x: x3 }));\n}\nfunction dotY(data, { y: y3 = identity7, ...options } = {}) {\n return new Dot(data, maybeIntervalMidX({ ...options, y: y3 }));\n}\nfunction circle(data, options) {\n return dot(data, { ...options, symbol: \"circle\" });\n}\nfunction hexagon(data, options) {\n return dot(data, { ...options, symbol: \"hexagon\" });\n}\n\n// ../../node_modules/@observablehq/plot/src/marks/line.js\nvar defaults12 = {\n ariaLabel: \"line\",\n fill: \"none\",\n stroke: \"currentColor\",\n strokeWidth: 1.5,\n strokeLinecap: \"round\",\n strokeLinejoin: \"round\",\n strokeMiterlimit: 1\n};\nvar Line = class extends Mark {\n constructor(data, options = {}) {\n const { x: x3, y: y3, z, curve, tension } = options;\n super(\n data,\n {\n x: { value: x3, scale: \"x\" },\n y: { value: y3, scale: \"y\" },\n z: { value: maybeZ(options), optional: true }\n },\n options,\n defaults12\n );\n this.z = z;\n this.curve = maybeCurveAuto(curve, tension);\n markers(this, options);\n }\n filter(index2) {\n return index2;\n }\n project(channels, values2, context) {\n if (this.curve !== curveAuto) {\n super.project(channels, values2, context);\n }\n }\n render(index2, scales2, channels, dimensions, context) {\n const { x: X3, y: Y3 } = channels;\n const { curve } = this;\n return create4(\"svg:g\", context).call(applyIndirectStyles, this, dimensions, context).call(applyTransform, this, scales2).call(\n (g) => g.selectAll().data(groupIndex(index2, [X3, Y3], this, channels)).enter().append(\"path\").call(applyDirectStyles, this).call(applyGroupedChannelStyles, this, channels).call(applyGroupedMarkers, this, channels, context).attr(\n \"d\",\n curve === curveAuto && context.projection ? sphereLine(context.projection, X3, Y3) : line_default2().curve(curve).defined((i) => i >= 0).x((i) => X3[i]).y((i) => Y3[i])\n )\n ).node();\n }\n};\nfunction sphereLine(projection3, X3, Y3) {\n const path2 = path_default(projection3);\n X3 = coerceNumbers(X3);\n Y3 = coerceNumbers(Y3);\n return (I) => {\n let line3 = [];\n const lines = [line3];\n for (const i of I) {\n if (i === -1) {\n line3 = [];\n lines.push(line3);\n } else {\n line3.push([X3[i], Y3[i]]);\n }\n }\n return path2({ type: \"MultiLineString\", coordinates: lines });\n };\n}\nfunction line(data, { x: x3, y: y3, ...options } = {}) {\n [x3, y3] = maybeTuple(x3, y3);\n return new Line(data, { ...options, x: x3, y: y3 });\n}\nfunction lineX(data, { x: x3 = identity7, y: y3 = indexOf, ...options } = {}) {\n return new Line(data, maybeDenseIntervalY({ ...options, x: x3, y: y3 }));\n}\nfunction lineY(data, { x: x3 = indexOf, y: y3 = identity7, ...options } = {}) {\n return new Line(data, maybeDenseIntervalX({ ...options, x: x3, y: y3 }));\n}\n\n// ../../node_modules/@observablehq/plot/src/marks/auto.js\nfunction autoSpec(data, options) {\n options = normalizeOptions(options);\n const { x: x3, y: y3, color: color3, size } = options;\n const X3 = materializeValue(data, x3);\n const Y3 = materializeValue(data, y3);\n const C3 = materializeValue(data, color3);\n const S = materializeValue(data, size);\n let {\n fx,\n fy,\n x: { value: xValue, reduce: xReduce, zero: xZero2, ...xOptions },\n y: { value: yValue, reduce: yReduce, zero: yZero2, ...yOptions },\n color: { value: colorValue, color: colorColor, reduce: colorReduce },\n size: { value: sizeValue, reduce: sizeReduce },\n // TODO constant radius?\n mark: mark2\n } = options;\n if (xReduce === void 0)\n xReduce = yReduce == null && xValue == null && sizeValue == null && yValue != null ? \"count\" : null;\n if (yReduce === void 0)\n yReduce = xReduce == null && yValue == null && sizeValue == null && xValue != null ? \"count\" : null;\n if (sizeReduce === void 0 && sizeValue == null && colorReduce == null && xReduce == null && yReduce == null && (xValue == null || isOrdinal(X3)) && (yValue == null || isOrdinal(Y3))) {\n sizeReduce = \"count\";\n }\n if (xZero2 === void 0) xZero2 = isZeroReducer(xReduce) ? true : void 0;\n if (yZero2 === void 0) yZero2 = isZeroReducer(yReduce) ? true : void 0;\n if (xValue == null && yValue == null) throw new Error(\"must specify x or y\");\n if (xReduce != null && yValue == null) throw new Error(\"reducing x requires y\");\n if (yReduce != null && xValue == null) throw new Error(\"reducing y requires x\");\n if (mark2 === void 0) {\n mark2 = sizeValue != null || sizeReduce != null ? \"dot\" : isZeroReducer(xReduce) || isZeroReducer(yReduce) || colorReduce != null ? \"bar\" : xValue != null && yValue != null ? isOrdinal(X3) || isOrdinal(Y3) || xReduce == null && yReduce == null && !isMonotonic(X3) && !isMonotonic(Y3) ? \"dot\" : \"line\" : xValue != null || yValue != null ? \"rule\" : null;\n }\n let Z;\n let colorMode;\n let markImpl;\n switch (mark2) {\n case \"dot\":\n markImpl = dot;\n colorMode = \"stroke\";\n break;\n case \"line\":\n markImpl = X3 && Y3 || xReduce != null || yReduce != null ? yZero2 || yReduce != null || X3 && isMonotonic(X3) ? lineY : xZero2 || xReduce != null || Y3 && isMonotonic(Y3) ? lineX : line : X3 ? lineX : lineY;\n colorMode = \"stroke\";\n if (isHighCardinality(C3)) Z = null;\n break;\n case \"area\":\n markImpl = !(yZero2 || yReduce != null) && (xZero2 || xReduce != null || Y3 && isMonotonic(Y3)) ? areaX : areaY;\n colorMode = \"fill\";\n if (isHighCardinality(C3)) Z = null;\n break;\n case \"rule\":\n markImpl = X3 ? ruleX : ruleY;\n colorMode = \"stroke\";\n break;\n case \"bar\":\n markImpl = xReduce != null ? isOrdinal(Y3) ? isSelectReducer(xReduce) && X3 && isOrdinal(X3) ? cell : barX : rectX : yReduce != null ? isOrdinal(X3) ? isSelectReducer(yReduce) && Y3 && isOrdinal(Y3) ? cell : barY : rectY : colorReduce != null || sizeReduce != null ? X3 && isOrdinal(X3) && Y3 && isOrdinal(Y3) ? cell : X3 && isOrdinal(X3) ? barY : Y3 && isOrdinal(Y3) ? barX : rect : X3 && isNumeric(X3) && !(Y3 && isNumeric(Y3)) ? barX : Y3 && isNumeric(Y3) && !(X3 && isNumeric(X3)) ? barY : cell;\n colorMode = \"fill\";\n break;\n default:\n throw new Error(`invalid mark: ${mark2}`);\n }\n let markOptions2 = {\n fx,\n fy,\n x: X3 ?? void 0,\n // treat null x as undefined for implicit stack\n y: Y3 ?? void 0,\n // treat null y as undefined for implicit stack\n [colorMode]: C3 ?? colorColor,\n z: Z,\n r: S ?? void 0,\n // treat null size as undefined for default constant radius\n tip: true\n };\n let transformImpl;\n let transformOptions = { [colorMode]: colorReduce ?? void 0, r: sizeReduce ?? void 0 };\n if (xReduce != null && yReduce != null) {\n throw new Error(`cannot reduce both x and y`);\n } else if (yReduce != null) {\n transformOptions.y = yReduce;\n transformImpl = isOrdinal(X3) ? groupX : binX;\n } else if (xReduce != null) {\n transformOptions.x = xReduce;\n transformImpl = isOrdinal(Y3) ? groupY : binY;\n } else if (colorReduce != null || sizeReduce != null) {\n if (X3 && Y3) {\n transformImpl = isOrdinal(X3) && isOrdinal(Y3) ? group2 : isOrdinal(X3) ? binY : isOrdinal(Y3) ? binX : bin;\n } else if (X3) {\n transformImpl = isOrdinal(X3) ? groupX : binX;\n } else if (Y3) {\n transformImpl = isOrdinal(Y3) ? groupY : binY;\n }\n }\n if (transformImpl === bin || transformImpl === binX) markOptions2.x = { value: X3, ...xOptions };\n if (transformImpl === bin || transformImpl === binY) markOptions2.y = { value: Y3, ...yOptions };\n if (xZero2 === void 0)\n xZero2 = X3 && !(transformImpl === bin || transformImpl === binX) && (markImpl === barX || markImpl === areaX || markImpl === rectX || markImpl === ruleY);\n if (yZero2 === void 0)\n yZero2 = Y3 && !(transformImpl === bin || transformImpl === binY) && (markImpl === barY || markImpl === areaY || markImpl === rectY || markImpl === ruleX);\n return {\n fx: fx ?? null,\n fy: fy ?? null,\n x: {\n value: xValue ?? null,\n reduce: xReduce ?? null,\n zero: !!xZero2,\n ...xOptions\n },\n y: {\n value: yValue ?? null,\n reduce: yReduce ?? null,\n zero: !!yZero2,\n ...yOptions\n },\n color: {\n value: colorValue ?? null,\n reduce: colorReduce ?? null,\n ...colorColor !== void 0 && { color: colorColor }\n },\n size: {\n value: sizeValue ?? null,\n reduce: sizeReduce ?? null\n },\n mark: mark2,\n markImpl: implNames[markImpl],\n markOptions: markOptions2,\n transformImpl: implNames[transformImpl],\n transformOptions,\n colorMode\n };\n}\nfunction auto(data, options) {\n const spec = autoSpec(data, options);\n const {\n fx,\n fy,\n x: { zero: xZero2 },\n y: { zero: yZero2 },\n markOptions: markOptions2,\n transformOptions,\n colorMode\n } = spec;\n const markImpl = impls[spec.markImpl];\n const transformImpl = impls[spec.transformImpl];\n const frames = fx != null || fy != null ? frame2({ strokeOpacity: 0.1 }) : null;\n const rules = [xZero2 ? ruleX([0]) : null, yZero2 ? ruleY([0]) : null];\n const mark2 = markImpl(data, transformImpl ? transformImpl(transformOptions, markOptions2) : markOptions2);\n return colorMode === \"stroke\" ? marks(frames, rules, mark2) : marks(frames, mark2, rules);\n}\nfunction isMonotonic(values2) {\n let previous;\n let previousOrder;\n for (const value of values2) {\n if (value == null) continue;\n if (previous === void 0) {\n previous = value;\n continue;\n }\n const order = Math.sign(ascending(previous, value));\n if (!order) continue;\n if (previousOrder !== void 0 && order !== previousOrder) return false;\n previous = value;\n previousOrder = order;\n }\n return true;\n}\nfunction normalizeOptions({ x: x3, y: y3, color: color3, size, fx, fy, mark: mark2 } = {}) {\n if (!isOptions(x3)) x3 = makeOptions(x3);\n if (!isOptions(y3)) y3 = makeOptions(y3);\n if (!isOptions(color3)) color3 = isColor(color3) ? { color: color3 } : makeOptions(color3);\n if (!isOptions(size)) size = makeOptions(size);\n if (isOptions(fx)) ({ value: fx } = makeOptions(fx));\n if (isOptions(fy)) ({ value: fy } = makeOptions(fy));\n if (mark2 != null) mark2 = `${mark2}`.toLowerCase();\n return { x: x3, y: y3, color: color3, size, fx, fy, mark: mark2 };\n}\nfunction materializeValue(data, options) {\n const V = valueof(data, options.value);\n if (V) V.label = labelof(options.value);\n return V;\n}\nfunction makeOptions(value) {\n return isReducer(value) ? { reduce: value } : { value };\n}\nfunction isZeroReducer(reduce) {\n return /^(?:distinct|count|sum|proportion)$/i.test(reduce);\n}\nfunction isSelectReducer(reduce) {\n return /^(?:first|last|mode)$/i.test(reduce);\n}\nfunction isReducer(reduce) {\n if (reduce == null) return false;\n if (typeof reduce.reduceIndex === \"function\") return true;\n if (typeof reduce.reduce === \"function\" && isObject(reduce)) return true;\n if (/^p\\d{2}$/i.test(reduce)) return true;\n switch (`${reduce}`.toLowerCase()) {\n case \"first\":\n case \"last\":\n case \"count\":\n case \"distinct\":\n case \"sum\":\n case \"proportion\":\n case \"proportion-facet\":\n // TODO remove me?\n case \"deviation\":\n case \"min\":\n case \"min-index\":\n // TODO remove me?\n case \"max\":\n case \"max-index\":\n // TODO remove me?\n case \"mean\":\n case \"median\":\n case \"variance\":\n case \"mode\":\n return true;\n }\n return false;\n}\nfunction isHighCardinality(value) {\n return value ? new InternSet(value).size > value.length >> 1 : false;\n}\nvar impls = {\n dot,\n line,\n lineX,\n lineY,\n areaX,\n areaY,\n ruleX,\n ruleY,\n barX,\n barY,\n rect,\n rectX,\n rectY,\n cell,\n bin,\n binX,\n binY,\n group: group2,\n groupX,\n groupY\n};\nvar implNames = Object.fromEntries(Object.entries(impls).map(([name2, impl]) => [impl, name2]));\n\n// ../../node_modules/@observablehq/plot/src/transforms/map.js\nfunction mapX(mapper, options = {}) {\n let { x: x3, x1: x12, x2: x22 } = options;\n if (x3 === void 0 && x12 === void 0 && x22 === void 0) options = { ...options, x: x3 = identity7 };\n const outputs = {};\n if (x3 != null) outputs.x = mapper;\n if (x12 != null) outputs.x1 = mapper;\n if (x22 != null) outputs.x2 = mapper;\n return map4(outputs, options);\n}\nfunction mapY(mapper, options = {}) {\n let { y: y3, y1: y12, y2: y22 } = options;\n if (y3 === void 0 && y12 === void 0 && y22 === void 0) options = { ...options, y: y3 = identity7 };\n const outputs = {};\n if (y3 != null) outputs.y = mapper;\n if (y12 != null) outputs.y1 = mapper;\n if (y22 != null) outputs.y2 = mapper;\n return map4(outputs, options);\n}\nfunction map4(outputs = {}, options = {}) {\n const z = maybeZ(options);\n const channels = Object.entries(outputs).map(([key, map5]) => {\n const input3 = maybeInput(key, options);\n if (input3 == null) throw new Error(`missing channel: ${key}`);\n const [output, setOutput] = column2(input3);\n return { key, input: input3, output, setOutput, map: maybeMap(map5) };\n });\n return {\n ...basic(options, (data, facets) => {\n const Z = valueof(data, z);\n const X3 = channels.map(({ input: input3 }) => valueof(data, input3));\n const MX = channels.map(({ setOutput }) => setOutput(new Array(data.length)));\n for (const facet of facets) {\n for (const I of Z ? group(facet, (i) => Z[i]).values() : [facet]) {\n channels.forEach(({ map: map5 }, i) => map5.mapIndex(I, X3[i], MX[i]));\n }\n }\n return { data, facets };\n }),\n ...Object.fromEntries(channels.map(({ key, output }) => [key, output]))\n };\n}\nfunction maybeMap(map5) {\n if (map5 == null) throw new Error(\"missing map\");\n if (typeof map5.mapIndex === \"function\") return map5;\n if (typeof map5.map === \"function\" && isObject(map5)) return mapMap(map5);\n if (typeof map5 === \"function\") return mapFunction(taker(map5));\n switch (`${map5}`.toLowerCase()) {\n case \"cumsum\":\n return mapCumsum;\n case \"rank\":\n return mapFunction((I, V) => rank2(I, (i) => V[i]));\n case \"quantile\":\n return mapFunction((I, V) => rankQuantile(I, (i) => V[i]));\n }\n throw new Error(`invalid map: ${map5}`);\n}\nfunction mapMap(map5) {\n console.warn(\"deprecated map interface; implement mapIndex instead.\");\n return { mapIndex: map5.map.bind(map5) };\n}\nfunction rankQuantile(I, f) {\n const n = count2(I, f) - 1;\n return rank2(I, f).map((r) => r / n);\n}\nfunction mapFunction(f) {\n return {\n mapIndex(I, S, T) {\n const M2 = f(I, S);\n if (M2.length !== I.length) throw new Error(\"map function returned a mismatched length\");\n for (let i = 0, n = I.length; i < n; ++i) T[I[i]] = M2[i];\n }\n };\n}\nvar mapCumsum = {\n mapIndex(I, S, T) {\n let sum4 = 0;\n for (const i of I) T[i] = sum4 += S[i];\n }\n};\n\n// ../../node_modules/@observablehq/plot/src/transforms/window.js\nfunction windowX(windowOptions = {}, options) {\n if (arguments.length === 1) options = windowOptions;\n return mapX(window2(windowOptions), options);\n}\nfunction windowY(windowOptions = {}, options) {\n if (arguments.length === 1) options = windowOptions;\n return mapY(window2(windowOptions), options);\n}\nfunction window2(options = {}) {\n if (typeof options === \"number\") options = { k: options };\n let { k: k2, reduce, shift, anchor, strict } = options;\n if (anchor === void 0 && shift !== void 0) {\n anchor = maybeShift(shift);\n warn(`Warning: the shift option is deprecated; please use anchor \"${anchor}\" instead.`);\n }\n if (!((k2 = Math.floor(k2)) > 0)) throw new Error(`invalid k: ${k2}`);\n return maybeReduce2(reduce)(k2, maybeAnchor3(anchor, k2), strict);\n}\nfunction maybeAnchor3(anchor = \"middle\", k2) {\n switch (`${anchor}`.toLowerCase()) {\n case \"middle\":\n return k2 - 1 >> 1;\n case \"start\":\n return 0;\n case \"end\":\n return k2 - 1;\n }\n throw new Error(`invalid anchor: ${anchor}`);\n}\nfunction maybeShift(shift) {\n switch (`${shift}`.toLowerCase()) {\n case \"centered\":\n return \"middle\";\n case \"leading\":\n return \"start\";\n case \"trailing\":\n return \"end\";\n }\n throw new Error(`invalid shift: ${shift}`);\n}\nfunction maybeReduce2(reduce = \"mean\") {\n if (typeof reduce === \"string\") {\n if (/^p\\d{2}$/i.test(reduce)) return reduceAccessor2(percentile(reduce));\n switch (reduce.toLowerCase()) {\n case \"deviation\":\n return reduceAccessor2(deviation);\n case \"max\":\n return reduceArray((I, V) => max2(I, (i) => V[i]));\n case \"mean\":\n return reduceMean;\n case \"median\":\n return reduceAccessor2(median2);\n case \"min\":\n return reduceArray((I, V) => min2(I, (i) => V[i]));\n case \"mode\":\n return reduceArray((I, V) => mode2(I, (i) => V[i]));\n case \"sum\":\n return reduceSum2;\n case \"variance\":\n return reduceAccessor2(variance2);\n case \"difference\":\n return reduceDifference;\n case \"ratio\":\n return reduceRatio;\n case \"first\":\n return reduceFirst2;\n case \"last\":\n return reduceLast2;\n }\n }\n if (typeof reduce !== \"function\") throw new Error(`invalid reduce: ${reduce}`);\n return reduceArray(taker(reduce));\n}\nfunction reduceAccessor2(f) {\n return (k2, s2, strict) => strict ? {\n mapIndex(I, S, T) {\n const v2 = (i) => S[i] == null ? NaN : +S[i];\n let nans = 0;\n for (let i = 0; i < k2 - 1; ++i) if (isNaN(v2(i))) ++nans;\n for (let i = 0, n = I.length - k2 + 1; i < n; ++i) {\n if (isNaN(v2(i + k2 - 1))) ++nans;\n T[I[i + s2]] = nans === 0 ? f(subarray(I, i, i + k2), v2) : NaN;\n if (isNaN(v2(i))) --nans;\n }\n }\n } : {\n mapIndex(I, S, T) {\n const v2 = (i) => S[i] == null ? NaN : +S[i];\n for (let i = -s2; i < 0; ++i) {\n T[I[i + s2]] = f(subarray(I, 0, i + k2), v2);\n }\n for (let i = 0, n = I.length - s2; i < n; ++i) {\n T[I[i + s2]] = f(subarray(I, i, i + k2), v2);\n }\n }\n };\n}\nfunction reduceArray(f) {\n return (k2, s2, strict) => strict ? {\n mapIndex(I, S, T) {\n let count4 = 0;\n for (let i = 0; i < k2 - 1; ++i) count4 += defined(S[I[i]]);\n for (let i = 0, n = I.length - k2 + 1; i < n; ++i) {\n count4 += defined(S[I[i + k2 - 1]]);\n if (count4 === k2) T[I[i + s2]] = f(subarray(I, i, i + k2), S);\n count4 -= defined(S[I[i]]);\n }\n }\n } : {\n mapIndex(I, S, T) {\n for (let i = -s2; i < 0; ++i) {\n T[I[i + s2]] = f(subarray(I, 0, i + k2), S);\n }\n for (let i = 0, n = I.length - s2; i < n; ++i) {\n T[I[i + s2]] = f(subarray(I, i, i + k2), S);\n }\n }\n };\n}\nfunction reduceSum2(k2, s2, strict) {\n return strict ? {\n mapIndex(I, S, T) {\n let nans = 0;\n let sum4 = 0;\n for (let i = 0; i < k2 - 1; ++i) {\n const v2 = S[I[i]];\n if (v2 === null || isNaN(v2)) ++nans;\n else sum4 += +v2;\n }\n for (let i = 0, n = I.length - k2 + 1; i < n; ++i) {\n const a2 = S[I[i]];\n const b = S[I[i + k2 - 1]];\n if (b === null || isNaN(b)) ++nans;\n else sum4 += +b;\n T[I[i + s2]] = nans === 0 ? sum4 : NaN;\n if (a2 === null || isNaN(a2)) --nans;\n else sum4 -= +a2;\n }\n }\n } : {\n mapIndex(I, S, T) {\n let sum4 = 0;\n const n = I.length;\n for (let i = 0, j = Math.min(n, k2 - s2 - 1); i < j; ++i) {\n sum4 += +S[I[i]] || 0;\n }\n for (let i = -s2, j = n - s2; i < j; ++i) {\n sum4 += +S[I[i + k2 - 1]] || 0;\n T[I[i + s2]] = sum4;\n sum4 -= +S[I[i]] || 0;\n }\n }\n };\n}\nfunction reduceMean(k2, s2, strict) {\n if (strict) {\n const sum4 = reduceSum2(k2, s2, strict);\n return {\n mapIndex(I, S, T) {\n sum4.mapIndex(I, S, T);\n for (let i = 0, n = I.length - k2 + 1; i < n; ++i) {\n T[I[i + s2]] /= k2;\n }\n }\n };\n } else {\n return {\n mapIndex(I, S, T) {\n let sum4 = 0;\n let count4 = 0;\n const n = I.length;\n for (let i = 0, j = Math.min(n, k2 - s2 - 1); i < j; ++i) {\n let v2 = S[I[i]];\n if (v2 !== null && !isNaN(v2 = +v2)) sum4 += v2, ++count4;\n }\n for (let i = -s2, j = n - s2; i < j; ++i) {\n let a2 = S[I[i + k2 - 1]];\n let b = S[I[i]];\n if (a2 !== null && !isNaN(a2 = +a2)) sum4 += a2, ++count4;\n T[I[i + s2]] = sum4 / count4;\n if (b !== null && !isNaN(b = +b)) sum4 -= b, --count4;\n }\n }\n };\n }\n}\nfunction firstDefined(S, I, i, k2) {\n for (let j = i + k2; i < j; ++i) {\n const v2 = S[I[i]];\n if (defined(v2)) return v2;\n }\n}\nfunction lastDefined(S, I, i, k2) {\n for (let j = i + k2 - 1; j >= i; --j) {\n const v2 = S[I[j]];\n if (defined(v2)) return v2;\n }\n}\nfunction firstNumber(S, I, i, k2) {\n for (let j = i + k2; i < j; ++i) {\n let v2 = S[I[i]];\n if (v2 !== null && !isNaN(v2 = +v2)) return v2;\n }\n}\nfunction lastNumber(S, I, i, k2) {\n for (let j = i + k2 - 1; j >= i; --j) {\n let v2 = S[I[j]];\n if (v2 !== null && !isNaN(v2 = +v2)) return v2;\n }\n}\nfunction reduceDifference(k2, s2, strict) {\n return strict ? {\n mapIndex(I, S, T) {\n for (let i = 0, n = I.length - k2; i < n; ++i) {\n const a2 = S[I[i]];\n const b = S[I[i + k2 - 1]];\n T[I[i + s2]] = a2 === null || b === null ? NaN : b - a2;\n }\n }\n } : {\n mapIndex(I, S, T) {\n for (let i = -s2, n = I.length - k2 + s2 + 1; i < n; ++i) {\n T[I[i + s2]] = lastNumber(S, I, i, k2) - firstNumber(S, I, i, k2);\n }\n }\n };\n}\nfunction reduceRatio(k2, s2, strict) {\n return strict ? {\n mapIndex(I, S, T) {\n for (let i = 0, n = I.length - k2; i < n; ++i) {\n const a2 = S[I[i]];\n const b = S[I[i + k2 - 1]];\n T[I[i + s2]] = a2 === null || b === null ? NaN : b / a2;\n }\n }\n } : {\n mapIndex(I, S, T) {\n for (let i = -s2, n = I.length - k2 + s2 + 1; i < n; ++i) {\n T[I[i + s2]] = lastNumber(S, I, i, k2) / firstNumber(S, I, i, k2);\n }\n }\n };\n}\nfunction reduceFirst2(k2, s2, strict) {\n return strict ? {\n mapIndex(I, S, T) {\n for (let i = 0, n = I.length - k2; i < n; ++i) {\n T[I[i + s2]] = S[I[i]];\n }\n }\n } : {\n mapIndex(I, S, T) {\n for (let i = -s2, n = I.length - k2 + s2 + 1; i < n; ++i) {\n T[I[i + s2]] = firstDefined(S, I, i, k2);\n }\n }\n };\n}\nfunction reduceLast2(k2, s2, strict) {\n return strict ? {\n mapIndex(I, S, T) {\n for (let i = 0, n = I.length - k2; i < n; ++i) {\n T[I[i + s2]] = S[I[i + k2 - 1]];\n }\n }\n } : {\n mapIndex(I, S, T) {\n for (let i = -s2, n = I.length - k2 + s2 + 1; i < n; ++i) {\n T[I[i + s2]] = lastDefined(S, I, i, k2);\n }\n }\n };\n}\n\n// ../../node_modules/@observablehq/plot/src/marks/bollinger.js\nvar defaults13 = {\n n: 20,\n k: 2,\n color: \"currentColor\",\n opacity: 0.2,\n strict: true,\n anchor: \"end\"\n};\nfunction bollingerX(data, {\n x: x3 = identity7,\n y: y3,\n k: k2 = defaults13.k,\n color: color3 = defaults13.color,\n opacity: opacity2 = defaults13.opacity,\n fill = color3,\n fillOpacity = opacity2,\n stroke = color3,\n strokeOpacity,\n strokeWidth,\n ...options\n} = {}) {\n return marks(\n isNoneish(fill) ? null : areaX(\n data,\n map4(\n { x1: bollinger({ k: -k2, ...options }), x2: bollinger({ k: k2, ...options }) },\n { x1: x3, x2: x3, y: y3, fill, fillOpacity, ...options }\n )\n ),\n isNoneish(stroke) ? null : lineX(data, map4({ x: bollinger(options) }, { x: x3, y: y3, stroke, strokeOpacity, strokeWidth, ...options }))\n );\n}\nfunction bollingerY(data, {\n x: x3,\n y: y3 = identity7,\n k: k2 = defaults13.k,\n color: color3 = defaults13.color,\n opacity: opacity2 = defaults13.opacity,\n fill = color3,\n fillOpacity = opacity2,\n stroke = color3,\n strokeOpacity,\n strokeWidth,\n ...options\n} = {}) {\n return marks(\n isNoneish(fill) ? null : areaY(\n data,\n map4(\n { y1: bollinger({ k: -k2, ...options }), y2: bollinger({ k: k2, ...options }) },\n { x: x3, y1: y3, y2: y3, fill, fillOpacity, ...options }\n )\n ),\n isNoneish(stroke) ? null : lineY(data, map4({ y: bollinger(options) }, { x: x3, y: y3, stroke, strokeOpacity, strokeWidth, ...options }))\n );\n}\nfunction bollinger({ n = defaults13.n, k: k2 = 0, strict = defaults13.strict, anchor = defaults13.anchor } = {}) {\n return window2({ k: n, reduce: (Y3) => mean2(Y3) + k2 * (deviation(Y3) || 0), strict, anchor });\n}\n\n// ../../node_modules/@observablehq/plot/src/marks/tick.js\nvar defaults14 = {\n ariaLabel: \"tick\",\n fill: null,\n stroke: \"currentColor\"\n};\nvar AbstractTick = class extends Mark {\n constructor(data, channels, options) {\n super(data, channels, options, defaults14);\n markers(this, options);\n }\n render(index2, scales2, channels, dimensions, context) {\n return create4(\"svg:g\", context).call(applyIndirectStyles, this, dimensions, context).call(this._transform, this, scales2).call(\n (g) => g.selectAll().data(index2).enter().append(\"line\").call(applyDirectStyles, this).attr(\"x1\", this._x1(scales2, channels, dimensions)).attr(\"x2\", this._x2(scales2, channels, dimensions)).attr(\"y1\", this._y1(scales2, channels, dimensions)).attr(\"y2\", this._y2(scales2, channels, dimensions)).call(applyChannelStyles, this, channels).call(applyMarkers, this, channels, context)\n ).node();\n }\n};\nvar TickX = class extends AbstractTick {\n constructor(data, options = {}) {\n const { x: x3, y: y3, inset: inset2 = 0, insetTop = inset2, insetBottom = inset2 } = options;\n super(\n data,\n {\n x: { value: x3, scale: \"x\" },\n y: { value: y3, scale: \"y\", type: \"band\", optional: true }\n },\n options\n );\n this.insetTop = number5(insetTop);\n this.insetBottom = number5(insetBottom);\n }\n _transform(selection2, mark2, { x: x3 }) {\n selection2.call(applyTransform, mark2, { x: x3 }, offset, 0);\n }\n _x1(scales2, { x: X3 }) {\n return (i) => X3[i];\n }\n _x2(scales2, { x: X3 }) {\n return (i) => X3[i];\n }\n _y1({ y: y3 }, { y: Y3 }, { marginTop: marginTop2 }) {\n const { insetTop } = this;\n return Y3 && y3 ? (i) => Y3[i] + insetTop : marginTop2 + insetTop;\n }\n _y2({ y: y3 }, { y: Y3 }, { height: height2, marginBottom: marginBottom2 }) {\n const { insetBottom } = this;\n return Y3 && y3 ? (i) => Y3[i] + y3.bandwidth() - insetBottom : height2 - marginBottom2 - insetBottom;\n }\n};\nvar TickY = class extends AbstractTick {\n constructor(data, options = {}) {\n const { x: x3, y: y3, inset: inset2 = 0, insetRight = inset2, insetLeft = inset2 } = options;\n super(\n data,\n {\n y: { value: y3, scale: \"y\" },\n x: { value: x3, scale: \"x\", type: \"band\", optional: true }\n },\n options\n );\n this.insetRight = number5(insetRight);\n this.insetLeft = number5(insetLeft);\n }\n _transform(selection2, mark2, { y: y3 }) {\n selection2.call(applyTransform, mark2, { y: y3 }, 0, offset);\n }\n _x1({ x: x3 }, { x: X3 }, { marginLeft: marginLeft2 }) {\n const { insetLeft } = this;\n return X3 && x3 ? (i) => X3[i] + insetLeft : marginLeft2 + insetLeft;\n }\n _x2({ x: x3 }, { x: X3 }, { width: width2, marginRight: marginRight2 }) {\n const { insetRight } = this;\n return X3 && x3 ? (i) => X3[i] + x3.bandwidth() - insetRight : width2 - marginRight2 - insetRight;\n }\n _y1(scales2, { y: Y3 }) {\n return (i) => Y3[i];\n }\n _y2(scales2, { y: Y3 }) {\n return (i) => Y3[i];\n }\n};\nfunction tickX(data, { x: x3 = identity7, ...options } = {}) {\n return new TickX(data, { ...options, x: x3 });\n}\nfunction tickY(data, { y: y3 = identity7, ...options } = {}) {\n return new TickY(data, { ...options, y: y3 });\n}\n\n// ../../node_modules/@observablehq/plot/src/marks/box.js\nfunction boxX(data, {\n x: x3 = identity7,\n y: y3 = null,\n r,\n fill = \"#ccc\",\n fillOpacity,\n stroke = \"currentColor\",\n strokeOpacity,\n strokeWidth = 2,\n sort: sort3,\n ...options\n} = {}) {\n const group3 = y3 != null ? groupY : groupZ;\n return marks(\n ruleY(data, group3({ x1: loqr1, x2: hiqr2 }, { x: x3, y: y3, stroke, strokeOpacity, ...options })),\n barX(data, group3({ x1: \"p25\", x2: \"p75\" }, { x: x3, y: y3, fill, fillOpacity, ...options })),\n tickX(data, group3({ x: \"p50\" }, { x: x3, y: y3, stroke, strokeOpacity, strokeWidth, sort: sort3, ...options })),\n dot(data, map4({ x: oqr }, { x: x3, y: y3, z: y3, r, stroke, strokeOpacity, ...options }))\n );\n}\nfunction boxY(data, {\n y: y3 = identity7,\n x: x3 = null,\n r,\n fill = \"#ccc\",\n fillOpacity,\n stroke = \"currentColor\",\n strokeOpacity,\n strokeWidth = 2,\n sort: sort3,\n ...options\n} = {}) {\n const group3 = x3 != null ? groupX : groupZ;\n return marks(\n ruleX(data, group3({ y1: loqr1, y2: hiqr2 }, { x: x3, y: y3, stroke, strokeOpacity, ...options })),\n barY(data, group3({ y1: \"p25\", y2: \"p75\" }, { x: x3, y: y3, fill, fillOpacity, ...options })),\n tickY(data, group3({ y: \"p50\" }, { x: x3, y: y3, stroke, strokeOpacity, strokeWidth, sort: sort3, ...options })),\n dot(data, map4({ y: oqr }, { x: x3, y: y3, z: x3, r, stroke, strokeOpacity, ...options }))\n );\n}\nfunction oqr(values2) {\n const r1 = loqr1(values2);\n const r2 = hiqr2(values2);\n return values2.map((v2) => v2 < r1 || v2 > r2 ? v2 : NaN);\n}\nfunction loqr1(values2) {\n const lo = quartile1(values2) * 2.5 - quartile3(values2) * 1.5;\n return min2(values2, (d) => d >= lo ? d : NaN);\n}\nfunction hiqr2(values2) {\n const hi = quartile3(values2) * 2.5 - quartile1(values2) * 1.5;\n return max2(values2, (d) => d <= hi ? d : NaN);\n}\nfunction quartile1(values2) {\n return quantile2(values2, 0.25);\n}\nfunction quartile3(values2) {\n return quantile2(values2, 0.75);\n}\n\n// ../../node_modules/@observablehq/plot/src/marks/raster.js\nvar defaults15 = {\n ariaLabel: \"raster\",\n stroke: null,\n pixelSize: 1\n};\nfunction number6(input3, name2) {\n const x3 = +input3;\n if (isNaN(x3)) throw new Error(`invalid ${name2}: ${input3}`);\n return x3;\n}\nfunction integer(input3, name2) {\n const x3 = Math.floor(input3);\n if (isNaN(x3)) throw new Error(`invalid ${name2}: ${input3}`);\n return x3;\n}\nvar AbstractRaster = class extends Mark {\n constructor(data, channels, options = {}, defaults22) {\n let {\n width: width2,\n height: height2,\n x: x3,\n y: y3,\n x1: x12 = x3 == null ? 0 : void 0,\n y1: y12 = y3 == null ? 0 : void 0,\n x2: x22 = x3 == null ? width2 : void 0,\n y2: y22 = y3 == null ? height2 : void 0,\n pixelSize = defaults22.pixelSize,\n blur: blur3 = 0,\n interpolate\n } = options;\n if (width2 != null) width2 = integer(width2, \"width\");\n if (height2 != null) height2 = integer(height2, \"height\");\n if (x12 != null) x12 = number6(x12, \"x1\");\n if (y12 != null) y12 = number6(y12, \"y1\");\n if (x22 != null) x22 = number6(x22, \"x2\");\n if (y22 != null) y22 = number6(y22, \"y2\");\n if (x3 == null && (x12 == null || x22 == null)) throw new Error(\"missing x\");\n if (y3 == null && (y12 == null || y22 == null)) throw new Error(\"missing y\");\n if (data != null && width2 != null && height2 != null) {\n if (x3 === void 0 && x12 != null && x22 != null) x3 = denseX(x12, x22, width2, height2);\n if (y3 === void 0 && y12 != null && y22 != null) y3 = denseY(y12, y22, width2, height2);\n }\n super(\n data,\n {\n x: { value: x3, scale: \"x\", optional: true },\n y: { value: y3, scale: \"y\", optional: true },\n x1: { value: x12 == null ? null : [x12], scale: \"x\", optional: true, filter: null },\n y1: { value: y12 == null ? null : [y12], scale: \"y\", optional: true, filter: null },\n x2: { value: x22 == null ? null : [x22], scale: \"x\", optional: true, filter: null },\n y2: { value: y22 == null ? null : [y22], scale: \"y\", optional: true, filter: null },\n ...channels\n },\n options,\n defaults22\n );\n this.width = width2;\n this.height = height2;\n this.pixelSize = number6(pixelSize, \"pixelSize\");\n this.blur = number6(blur3, \"blur\");\n this.interpolate = x3 == null || y3 == null ? null : maybeInterpolate(interpolate);\n }\n};\nvar Raster = class extends AbstractRaster {\n constructor(data, options = {}) {\n const { imageRendering } = options;\n if (data == null) {\n const { fill, fillOpacity } = options;\n if (maybeNumberChannel(fillOpacity)[0] !== void 0) options = sampler(\"fillOpacity\", options);\n if (maybeColorChannel(fill)[0] !== void 0) options = sampler(\"fill\", options);\n }\n super(data, void 0, options, defaults15);\n this.imageRendering = impliedString(imageRendering, \"auto\");\n }\n // Ignore the color scale, so the fill channel is returned unscaled.\n scale(channels, { color: color3, ...scales2 }, context) {\n return super.scale(channels, scales2, context);\n }\n render(index2, scales2, values2, dimensions, context) {\n const color3 = scales2[values2.channels.fill?.scale] ?? ((x3) => x3);\n const { x: X3, y: Y3 } = values2;\n const { document: document2 } = context;\n const [x12, y12, x22, y22] = renderBounds(values2, dimensions, context);\n const dx = x22 - x12;\n const dy = y22 - y12;\n const { pixelSize: k2, width: w = Math.round(Math.abs(dx) / k2), height: h = Math.round(Math.abs(dy) / k2) } = this;\n const n = w * h;\n let { fill: F, fillOpacity: FO } = values2;\n let offset2 = 0;\n if (this.interpolate) {\n const kx2 = w / dx;\n const ky2 = h / dy;\n const IX = map3(X3, (x3) => (x3 - x12) * kx2, Float64Array);\n const IY = map3(Y3, (y3) => (y3 - y12) * ky2, Float64Array);\n if (F) F = this.interpolate(index2, w, h, IX, IY, F);\n if (FO) FO = this.interpolate(index2, w, h, IX, IY, FO);\n } else if (this.data == null && index2) offset2 = index2.fi * n;\n const canvas = document2.createElement(\"canvas\");\n canvas.width = w;\n canvas.height = h;\n const context2d = canvas.getContext(\"2d\");\n const image3 = context2d.createImageData(w, h);\n const imageData3 = image3.data;\n let { r, g, b } = rgb(this.fill) ?? { r: 0, g: 0, b: 0 };\n let a2 = (this.fillOpacity ?? 1) * 255;\n for (let i = 0; i < n; ++i) {\n const j = i << 2;\n if (F) {\n const fi = color3(F[i + offset2]);\n if (fi == null) {\n imageData3[j + 3] = 0;\n continue;\n }\n ({ r, g, b } = rgb(fi));\n }\n if (FO) a2 = FO[i + offset2] * 255;\n imageData3[j + 0] = r;\n imageData3[j + 1] = g;\n imageData3[j + 2] = b;\n imageData3[j + 3] = a2;\n }\n if (this.blur > 0) blurImage(image3, this.blur);\n context2d.putImageData(image3, 0, 0);\n return create4(\"svg:g\", context).call(applyIndirectStyles, this, dimensions, context).call(applyTransform, this, scales2).call(\n (g2) => g2.append(\"image\").attr(\"transform\", `translate(${x12},${y12}) scale(${Math.sign(x22 - x12)},${Math.sign(y22 - y12)})`).attr(\"width\", Math.abs(dx)).attr(\"height\", Math.abs(dy)).attr(\"preserveAspectRatio\", \"none\").call(applyAttr, \"image-rendering\", this.imageRendering).call(applyDirectStyles, this).attr(\"xlink:href\", canvas.toDataURL())\n ).node();\n }\n};\nfunction maybeTuples(k2, data, options) {\n if (arguments.length < 3) options = data, data = null;\n let { x: x3, y: y3, [k2]: z, ...rest } = options;\n if (x3 === void 0 && y3 === void 0 && isTuples(data)) {\n x3 = first2, y3 = second2;\n if (z === void 0) z = third;\n }\n return [data, { ...rest, x: x3, y: y3, [k2]: z }];\n}\nfunction raster() {\n const [data, options] = maybeTuples(\"fill\", ...arguments);\n return new Raster(\n data,\n data == null || options.fill !== void 0 || options.fillOpacity !== void 0 ? options : { ...options, fill: identity7 }\n );\n}\nfunction renderBounds({ x1: x12, y1: y12, x2: x22, y2: y22 }, dimensions, { projection: projection3 }) {\n const { width: width2, height: height2, marginTop: marginTop2, marginRight: marginRight2, marginBottom: marginBottom2, marginLeft: marginLeft2 } = dimensions;\n return [\n x12 && projection3 == null ? x12[0] : marginLeft2,\n y12 && projection3 == null ? y12[0] : marginTop2,\n x22 && projection3 == null ? x22[0] : width2 - marginRight2,\n y22 && projection3 == null ? y22[0] : height2 - marginBottom2\n ];\n}\nfunction rasterBounds({ x1: x12, y1: y12, x2: x22, y2: y22 }, scales2, dimensions, context) {\n const channels = {};\n if (x12) channels.x1 = x12;\n if (y12) channels.y1 = y12;\n if (x22) channels.x2 = x22;\n if (y22) channels.y2 = y22;\n return renderBounds(valueObject(channels, scales2), dimensions, context);\n}\nfunction sampler(name2, options = {}) {\n const { [name2]: value } = options;\n if (typeof value !== \"function\") throw new Error(`invalid ${name2}: not a function`);\n return initializer({ ...options, [name2]: void 0 }, function(data, facets, channels, scales2, dimensions, context) {\n const { x: x3, y: y3 } = scales2;\n if (!x3) throw new Error(\"missing scale: x\");\n if (!y3) throw new Error(\"missing scale: y\");\n const [x12, y12, x22, y22] = rasterBounds(channels, scales2, dimensions, context);\n const dx = x22 - x12;\n const dy = y22 - y12;\n const { pixelSize: k2 } = this;\n const { width: w = Math.round(Math.abs(dx) / k2), height: h = Math.round(Math.abs(dy) / k2) } = options;\n const V = new Array(w * h * (facets ? facets.length : 1));\n const kx2 = dx / w;\n const ky2 = dy / h;\n let i = 0;\n for (const facet of facets ?? [void 0]) {\n for (let yi = 0.5; yi < h; ++yi) {\n for (let xi = 0.5; xi < w; ++xi, ++i) {\n V[i] = value(x3.invert(x12 + xi * kx2), y3.invert(y12 + yi * ky2), facet);\n }\n }\n }\n return { data: V, facets, channels: { [name2]: { value: V, scale: \"auto\" } } };\n });\n}\nfunction maybeInterpolate(interpolate) {\n if (typeof interpolate === \"function\") return interpolate;\n if (interpolate == null) return interpolateNone;\n switch (`${interpolate}`.toLowerCase()) {\n case \"none\":\n return interpolateNone;\n case \"nearest\":\n return interpolateNearest;\n case \"barycentric\":\n return interpolatorBarycentric();\n case \"random-walk\":\n return interpolatorRandomWalk();\n }\n throw new Error(`invalid interpolate: ${interpolate}`);\n}\nfunction interpolateNone(index2, width2, height2, X3, Y3, V) {\n const W = new Array(width2 * height2);\n for (const i of index2) {\n if (X3[i] < 0 || X3[i] >= width2 || Y3[i] < 0 || Y3[i] >= height2) continue;\n W[Math.floor(Y3[i]) * width2 + Math.floor(X3[i])] = V[i];\n }\n return W;\n}\nfunction interpolatorBarycentric({ random = lcg(42) } = {}) {\n return (index2, width2, height2, X3, Y3, V) => {\n const { points: points2, triangles, hull: hull3 } = Delaunay.from(\n index2,\n (i) => X3[i],\n (i) => Y3[i]\n );\n const W = new V.constructor(width2 * height2).fill(NaN);\n const S = new Uint8Array(width2 * height2);\n const mix = mixer(V, random);\n for (let i = 0; i < triangles.length; i += 3) {\n const ta = triangles[i];\n const tb = triangles[i + 1];\n const tc = triangles[i + 2];\n const Ax = points2[2 * ta];\n const Bx = points2[2 * tb];\n const Cx = points2[2 * tc];\n const Ay = points2[2 * ta + 1];\n const By = points2[2 * tb + 1];\n const Cy = points2[2 * tc + 1];\n const x12 = Math.min(Ax, Bx, Cx);\n const x22 = Math.max(Ax, Bx, Cx);\n const y12 = Math.min(Ay, By, Cy);\n const y22 = Math.max(Ay, By, Cy);\n const z = (By - Cy) * (Ax - Cx) + (Ay - Cy) * (Cx - Bx);\n if (!z) continue;\n const va = V[index2[ta]];\n const vb = V[index2[tb]];\n const vc = V[index2[tc]];\n for (let x3 = Math.floor(x12); x3 < x22; ++x3) {\n for (let y3 = Math.floor(y12); y3 < y22; ++y3) {\n if (x3 < 0 || x3 >= width2 || y3 < 0 || y3 >= height2) continue;\n const xp = x3 + 0.5;\n const yp = y3 + 0.5;\n const s2 = Math.sign(z);\n const ga = (By - Cy) * (xp - Cx) + (yp - Cy) * (Cx - Bx);\n if (ga * s2 < 0) continue;\n const gb = (Cy - Ay) * (xp - Cx) + (yp - Cy) * (Ax - Cx);\n if (gb * s2 < 0) continue;\n const gc = z - (ga + gb);\n if (gc * s2 < 0) continue;\n const i2 = x3 + width2 * y3;\n W[i2] = mix(va, ga / z, vb, gb / z, vc, gc / z, x3, y3);\n S[i2] = 1;\n }\n }\n }\n extrapolateBarycentric(W, S, X3, Y3, V, width2, height2, hull3, index2, mix);\n return W;\n };\n}\nfunction extrapolateBarycentric(W, S, X3, Y3, V, width2, height2, hull3, index2, mix) {\n X3 = Float64Array.from(hull3, (i) => X3[index2[i]]);\n Y3 = Float64Array.from(hull3, (i) => Y3[index2[i]]);\n V = Array.from(hull3, (i) => V[index2[i]]);\n const n = X3.length;\n const rays = Array.from({ length: n }, (_, j) => ray(j, X3, Y3));\n let k2 = 0;\n for (let y3 = 0; y3 < height2; ++y3) {\n const yp = y3 + 0.5;\n for (let x3 = 0; x3 < width2; ++x3) {\n const i = x3 + width2 * y3;\n if (!S[i]) {\n const xp = x3 + 0.5;\n for (let l = 0; l < n; ++l) {\n const j = (n + k2 + (l % 2 ? (l + 1) / 2 : -l / 2)) % n;\n if (rays[j](xp, yp)) {\n const t = segmentProject(X3.at(j - 1), Y3.at(j - 1), X3[j], Y3[j], xp, yp);\n W[i] = mix(V.at(j - 1), t, V[j], 1 - t, V[j], 0, x3, y3);\n k2 = j;\n break;\n }\n }\n }\n }\n }\n}\nfunction segmentProject(x12, y12, x22, y22, x3, y3) {\n const dx = x22 - x12;\n const dy = y22 - y12;\n const a2 = dx * (x22 - x3) + dy * (y22 - y3);\n const b = dx * (x3 - x12) + dy * (y3 - y12);\n return a2 > 0 && b > 0 ? a2 / (a2 + b) : +(a2 > b);\n}\nfunction cross2(xa, ya, xb, yb) {\n return xa * yb - xb * ya;\n}\nfunction ray(j, X3, Y3) {\n const n = X3.length;\n const xc = X3.at(j - 2);\n const yc = Y3.at(j - 2);\n const xa = X3.at(j - 1);\n const ya = Y3.at(j - 1);\n const xb = X3[j];\n const yb = Y3[j];\n const xd = X3.at(j + 1 - n);\n const yd = Y3.at(j + 1 - n);\n const dxab = xa - xb;\n const dyab = ya - yb;\n const dxca = xc - xa;\n const dyca = yc - ya;\n const dxbd = xb - xd;\n const dybd = yb - yd;\n const hab = Math.hypot(dxab, dyab);\n const hca = Math.hypot(dxca, dyca);\n const hbd = Math.hypot(dxbd, dybd);\n return (x3, y3) => {\n const dxa = x3 - xa;\n const dya = y3 - ya;\n const dxb = x3 - xb;\n const dyb = y3 - yb;\n return cross2(dxa, dya, dxb, dyb) > -1e-6 && cross2(dxa, dya, dxab, dyab) * hca - cross2(dxa, dya, dxca, dyca) * hab > -1e-6 && cross2(dxb, dyb, dxbd, dybd) * hab - cross2(dxb, dyb, dxab, dyab) * hbd <= 0;\n };\n}\nfunction interpolateNearest(index2, width2, height2, X3, Y3, V) {\n const W = new V.constructor(width2 * height2);\n const delaunay = Delaunay.from(\n index2,\n (i) => X3[i],\n (i) => Y3[i]\n );\n let iy, ix;\n for (let y3 = 0.5, k2 = 0; y3 < height2; ++y3) {\n ix = iy;\n for (let x3 = 0.5; x3 < width2; ++x3, ++k2) {\n ix = delaunay.find(x3, y3, ix);\n if (x3 === 0.5) iy = ix;\n W[k2] = V[index2[ix]];\n }\n }\n return W;\n}\nfunction interpolatorRandomWalk({ random = lcg(42), minDistance = 0.5, maxSteps = 2 } = {}) {\n return (index2, width2, height2, X3, Y3, V) => {\n const W = new V.constructor(width2 * height2);\n const delaunay = Delaunay.from(\n index2,\n (i) => X3[i],\n (i) => Y3[i]\n );\n let iy, ix, iw;\n for (let y3 = 0.5, k2 = 0; y3 < height2; ++y3) {\n ix = iy;\n for (let x3 = 0.5; x3 < width2; ++x3, ++k2) {\n let cx = x3;\n let cy = y3;\n iw = ix = delaunay.find(cx, cy, ix);\n if (x3 === 0.5) iy = ix;\n let distance;\n let step = 0;\n while ((distance = Math.hypot(X3[index2[iw]] - cx, Y3[index2[iw]] - cy)) > minDistance && step < maxSteps) {\n const angle = random(x3, y3, step) * 2 * Math.PI;\n cx += Math.cos(angle) * distance;\n cy += Math.sin(angle) * distance;\n iw = delaunay.find(cx, cy, iw);\n ++step;\n }\n W[k2] = V[index2[iw]];\n }\n }\n return W;\n };\n}\nfunction blend(a2, ca3, b, cb, c4, cc2) {\n return ca3 * a2 + cb * b + cc2 * c4;\n}\nfunction pick(random) {\n return (a2, ca3, b, cb, c4, cc2, x3, y3) => {\n const u4 = random(x3, y3);\n return u4 < ca3 ? a2 : u4 < ca3 + cb ? b : c4;\n };\n}\nfunction mixer(F, random) {\n return isNumeric(F) || isTemporal(F) ? blend : pick(random);\n}\nfunction denseX(x12, x22, width2) {\n return {\n transform(data) {\n const n = data.length;\n const X3 = new Float64Array(n);\n const kx2 = (x22 - x12) / width2;\n const x06 = x12 + kx2 / 2;\n for (let i = 0; i < n; ++i) X3[i] = i % width2 * kx2 + x06;\n return X3;\n }\n };\n}\nfunction denseY(y12, y22, width2, height2) {\n return {\n transform(data) {\n const n = data.length;\n const Y3 = new Float64Array(n);\n const ky2 = (y22 - y12) / height2;\n const y06 = y12 + ky2 / 2;\n for (let i = 0; i < n; ++i) Y3[i] = Math.floor(i / width2) % height2 * ky2 + y06;\n return Y3;\n }\n };\n}\n\n// ../../node_modules/@observablehq/plot/src/marks/contour.js\nvar defaults16 = {\n ariaLabel: \"contour\",\n fill: \"none\",\n stroke: \"currentColor\",\n strokeMiterlimit: 1,\n pixelSize: 2\n};\nvar Contour = class extends AbstractRaster {\n constructor(data, { smooth = true, value, ...options } = {}) {\n const channels = styles({}, options, defaults16);\n if (value === void 0) {\n for (const key in channels) {\n if (channels[key].value != null) {\n if (value !== void 0) throw new Error(\"ambiguous contour value\");\n value = options[key];\n options[key] = \"value\";\n }\n }\n }\n if (value != null) {\n const v2 = { transform: (D3) => D3.map((d) => d.value), label: labelof(value) };\n for (const key in channels) {\n if (options[key] === \"value\") {\n options[key] = v2;\n }\n }\n }\n if (data == null) {\n if (value == null) throw new Error(\"missing contour value\");\n options = sampler(\"value\", { value, ...options });\n value = null;\n } else {\n let { interpolate } = options;\n if (value === void 0) value = identity7;\n if (interpolate === void 0) options.interpolate = \"nearest\";\n }\n super(data, { value: { value, optional: true } }, contourGeometry(options), defaults16);\n const contourChannels = { geometry: { value: identity7 } };\n for (const key in this.channels) {\n const channel = this.channels[key];\n const { scale: scale3 } = channel;\n if (scale3 === \"x\" || scale3 === \"y\" || key === \"value\") continue;\n contourChannels[key] = channel;\n delete this.channels[key];\n }\n this.contourChannels = contourChannels;\n this.smooth = !!smooth;\n }\n filter(index2, { x: x3, y: y3, value, ...channels }, values2) {\n return super.filter(index2, channels, values2);\n }\n render(index2, scales2, channels, dimensions, context) {\n const { geometry: G } = channels;\n const path2 = path_default();\n return create4(\"svg:g\", context).call(applyIndirectStyles, this, dimensions, context).call(applyTransform, this, scales2).call((g) => {\n g.selectAll().data(index2).enter().append(\"path\").call(applyDirectStyles, this).attr(\"d\", (i) => path2(G[i])).call(applyChannelStyles, this, channels);\n }).node();\n }\n};\nfunction contourGeometry({ thresholds, interval: interval3, ...options }) {\n thresholds = maybeThresholds(thresholds, interval3, thresholdSturges);\n return initializer(options, function(data, facets, channels, scales2, dimensions, context) {\n const [x12, y12, x22, y22] = rasterBounds(channels, scales2, dimensions, context);\n const dx = x22 - x12;\n const dy = y22 - y12;\n const { pixelSize: k2, width: w = Math.round(Math.abs(dx) / k2), height: h = Math.round(Math.abs(dy) / k2) } = this;\n const kx2 = w / dx;\n const ky2 = h / dy;\n const V = channels.value.value;\n const VV = [];\n if (this.interpolate) {\n const { x: X3, y: Y3 } = applyPosition(channels, scales2, context);\n const IX = map3(X3, (x3) => (x3 - x12) * kx2, Float64Array);\n const IY = map3(Y3, (y3) => (y3 - y12) * ky2, Float64Array);\n const ichannels = [channels.x, channels.y, channels.value];\n const ivalues = [IX, IY, V];\n for (const facet of facets) {\n const index2 = this.filter(facet, ichannels, ivalues);\n VV.push(this.interpolate(index2, w, h, IX, IY, V));\n }\n } else if (facets) {\n const n = w * h;\n const m = facets.length;\n for (let i = 0; i < m; ++i) VV.push(V.slice(i * n, i * n + n));\n } else {\n VV.push(V);\n }\n if (this.blur > 0) for (const V2 of VV) blur2({ data: V2, width: w, height: h }, this.blur);\n const T = maybeTicks(thresholds, V, ...finiteExtent(VV));\n if (T === null) throw new Error(`unsupported thresholds: ${thresholds}`);\n const { contour: contour3 } = contours_default().size([w, h]).smooth(this.smooth);\n const contourData = [];\n const contourFacets = [];\n for (const V2 of VV) {\n contourFacets.push(range(contourData.length, contourData.push(...map3(T, (t) => contour3(V2, t)))));\n }\n for (const { coordinates } of contourData) {\n for (const rings of coordinates) {\n for (const ring of rings) {\n for (const point6 of ring) {\n point6[0] = point6[0] / kx2 + x12;\n point6[1] = point6[1] / ky2 + y12;\n }\n }\n }\n }\n return {\n data: contourData,\n facets: contourFacets,\n channels: createChannels(this.contourChannels, contourData)\n };\n });\n}\nfunction maybeTicks(thresholds, V, min5, max4) {\n if (typeof thresholds?.range === \"function\") return thresholds.range(thresholds.floor(min5), max4);\n if (typeof thresholds === \"function\") thresholds = thresholds(V, min5, max4);\n if (typeof thresholds !== \"number\") return arrayify2(thresholds);\n const tz = ticks(...nice(min5, max4, thresholds), thresholds);\n while (tz[tz.length - 1] >= max4) tz.pop();\n while (tz[1] < min5) tz.shift();\n return tz;\n}\nfunction contour() {\n return new Contour(...maybeTuples(\"value\", ...arguments));\n}\nfunction finiteExtent(VV) {\n return [min2(VV, (V) => min2(V, finite3)), max2(VV, (V) => max2(V, finite3))];\n}\nfunction finite3(x3) {\n return isFinite(x3) ? x3 : NaN;\n}\n\n// ../../node_modules/@observablehq/plot/src/marks/crosshair.js\nfunction crosshair(data, options) {\n return crosshairK(pointer, data, options);\n}\nfunction crosshairX(data, options = {}) {\n return crosshairK(pointerX, data, options);\n}\nfunction crosshairY(data, options = {}) {\n return crosshairK(pointerY, data, options);\n}\nfunction crosshairK(pointer2, data, options = {}) {\n const { x: x3, y: y3, maxRadius } = options;\n const p = pointer2({ px: x3, py: y3, maxRadius });\n const M2 = [];\n if (x3 != null) M2.push(ruleX(data, ruleOptions(\"x\", { ...p, inset: -6 }, options)));\n if (y3 != null) M2.push(ruleY(data, ruleOptions(\"y\", { ...p, inset: -6 }, options)));\n if (x3 != null) M2.push(text(data, textOptions(\"x\", { ...p, dy: 9, frameAnchor: \"bottom\", lineAnchor: \"top\" }, options)));\n if (y3 != null) M2.push(text(data, textOptions(\"y\", { ...p, dx: -9, frameAnchor: \"left\", textAnchor: \"end\" }, options)));\n for (const m of M2) m.ariaLabel = `crosshair ${m.ariaLabel}`;\n return marks(...M2);\n}\nfunction markOptions(k2, { channels: pointerChannels, ...pointerOptions }, { facet, facetAnchor, fx, fy, [k2]: p, channels, transform: transform3, initializer: initializer2 }) {\n return {\n ...pointerOptions,\n facet,\n facetAnchor,\n fx,\n fy,\n [k2]: p,\n channels: { ...pointerChannels, ...channels },\n transform: transform3,\n initializer: pxpy(k2, initializer2)\n };\n}\nfunction pxpy(k2, i) {\n if (i == null) return i;\n return function(data, facets, { x: x12, y: y12, px, py, ...c1 }, ...args) {\n const { channels: { x: x3, y: y3, ...c4 } = {}, ...rest } = i.call(this, data, facets, { ...c1, x: px, y: py }, ...args);\n return {\n channels: {\n ...c4,\n ...x3 && { px: x3, ...k2 === \"x\" && { x: x3 } },\n ...y3 && { py: y3, ...k2 === \"y\" && { y: y3 } }\n },\n ...rest\n };\n };\n}\nfunction ruleOptions(k2, pointerOptions, options) {\n const {\n color: color3 = \"currentColor\",\n opacity: opacity2 = 0.2,\n ruleStroke: stroke = color3,\n ruleStrokeOpacity: strokeOpacity = opacity2,\n ruleStrokeWidth: strokeWidth\n } = options;\n return {\n ...markOptions(k2, pointerOptions, options),\n stroke,\n strokeOpacity,\n strokeWidth\n };\n}\nfunction textOptions(k2, pointerOptions, options) {\n const {\n color: color3 = \"currentColor\",\n textFill: fill = color3,\n textFillOpacity: fillOpacity,\n textStroke: stroke = \"var(--plot-background)\",\n textStrokeOpacity: strokeOpacity,\n textStrokeWidth: strokeWidth = 5\n } = options;\n return {\n ...markOptions(k2, pointerOptions, textChannel(k2, options)),\n fill,\n fillOpacity,\n stroke,\n strokeOpacity,\n strokeWidth\n };\n}\nfunction textChannel(source, options) {\n return initializer(options, (data, facets, channels) => {\n return { channels: { text: { value: getSource(channels, source)?.value } } };\n });\n}\n\n// ../../node_modules/@observablehq/plot/src/marks/delaunay.js\nvar delaunayLinkDefaults = {\n ariaLabel: \"delaunay link\",\n fill: \"none\",\n stroke: \"currentColor\",\n strokeMiterlimit: 1\n};\nvar delaunayMeshDefaults = {\n ariaLabel: \"delaunay mesh\",\n fill: null,\n stroke: \"currentColor\",\n strokeOpacity: 0.2\n};\nvar hullDefaults = {\n ariaLabel: \"hull\",\n fill: \"none\",\n stroke: \"currentColor\",\n strokeWidth: 1.5,\n strokeMiterlimit: 1\n};\nvar voronoiDefaults = {\n ariaLabel: \"voronoi\",\n fill: \"none\",\n stroke: \"currentColor\",\n strokeMiterlimit: 1\n};\nvar voronoiMeshDefaults = {\n ariaLabel: \"voronoi mesh\",\n fill: null,\n stroke: \"currentColor\",\n strokeOpacity: 0.2\n};\nvar DelaunayLink = class extends Mark {\n constructor(data, options = {}) {\n const { x: x3, y: y3, z, curve, tension } = options;\n super(\n data,\n {\n x: { value: x3, scale: \"x\", optional: true },\n y: { value: y3, scale: \"y\", optional: true },\n z: { value: z, optional: true }\n },\n options,\n delaunayLinkDefaults\n );\n this.curve = maybeCurve(curve, tension);\n markers(this, options);\n }\n render(index2, scales2, channels, dimensions, context) {\n const { x: x3, y: y3 } = scales2;\n const { x: X3, y: Y3, z: Z } = channels;\n const { curve } = this;\n const [cx, cy] = applyFrameAnchor(this, dimensions);\n const xi = X3 ? (i) => X3[i] : constant(cx);\n const yi = Y3 ? (i) => Y3[i] : constant(cy);\n const mark2 = this;\n function links(index3) {\n let i = -1;\n const newIndex = [];\n const newChannels = {};\n for (const k2 in channels) newChannels[k2] = [];\n const X13 = [];\n const X23 = [];\n const Y13 = [];\n const Y23 = [];\n function link4(ti, tj) {\n ti = index3[ti];\n tj = index3[tj];\n newIndex.push(++i);\n X13[i] = xi(ti);\n Y13[i] = yi(ti);\n X23[i] = xi(tj);\n Y23[i] = yi(tj);\n for (const k2 in channels) newChannels[k2].push(channels[k2][tj]);\n }\n const { halfedges, hull: hull3, triangles } = Delaunay.from(index3, xi, yi);\n for (let i2 = 0; i2 < halfedges.length; ++i2) {\n const j = halfedges[i2];\n if (j > i2) link4(triangles[i2], triangles[j]);\n }\n for (let i2 = 0; i2 < hull3.length; ++i2) {\n link4(hull3[i2], hull3[(i2 + 1) % hull3.length]);\n }\n select_default2(this).selectAll().data(newIndex).enter().append(\"path\").call(applyDirectStyles, mark2).attr(\"d\", (i2) => {\n const p = pathRound();\n const c4 = curve(p);\n c4.lineStart();\n c4.point(X13[i2], Y13[i2]);\n c4.point(X23[i2], Y23[i2]);\n c4.lineEnd();\n return p;\n }).call(applyChannelStyles, mark2, newChannels).call(applyMarkers, mark2, newChannels, context);\n }\n return create4(\"svg:g\", context).call(applyIndirectStyles, this, dimensions, context).call(applyTransform, this, { x: X3 && x3, y: Y3 && y3 }).call(\n Z ? (g) => g.selectAll().data(group(index2, (i) => Z[i]).values()).enter().append(\"g\").each(links) : (g) => g.datum(index2).each(links)\n ).node();\n }\n};\nvar AbstractDelaunayMark = class extends Mark {\n constructor(data, options = {}, defaults22, zof = ({ z }) => z) {\n const { x: x3, y: y3 } = options;\n super(\n data,\n {\n x: { value: x3, scale: \"x\", optional: true },\n y: { value: y3, scale: \"y\", optional: true },\n z: { value: zof(options), optional: true }\n },\n options,\n defaults22\n );\n }\n render(index2, scales2, channels, dimensions, context) {\n const { x: x3, y: y3 } = scales2;\n const { x: X3, y: Y3, z: Z } = channels;\n const [cx, cy] = applyFrameAnchor(this, dimensions);\n const xi = X3 ? (i) => X3[i] : constant(cx);\n const yi = Y3 ? (i) => Y3[i] : constant(cy);\n const mark2 = this;\n function mesh(index3) {\n const delaunay = Delaunay.from(index3, xi, yi);\n select_default2(this).append(\"path\").datum(index3[0]).call(applyDirectStyles, mark2).attr(\"d\", mark2._render(delaunay, dimensions)).call(applyChannelStyles, mark2, channels);\n }\n return create4(\"svg:g\", context).call(applyIndirectStyles, this, dimensions, context).call(applyTransform, this, { x: X3 && x3, y: Y3 && y3 }).call(\n Z ? (g) => g.selectAll().data(group(index2, (i) => Z[i]).values()).enter().append(\"g\").each(mesh) : (g) => g.datum(index2).each(mesh)\n ).node();\n }\n};\nvar DelaunayMesh = class extends AbstractDelaunayMark {\n constructor(data, options = {}) {\n super(data, options, delaunayMeshDefaults);\n this.fill = \"none\";\n }\n _render(delaunay) {\n return delaunay.render();\n }\n};\nvar Hull = class extends AbstractDelaunayMark {\n constructor(data, options = {}) {\n super(data, options, hullDefaults, maybeZ);\n }\n _render(delaunay) {\n return delaunay.renderHull();\n }\n};\nvar Voronoi2 = class extends Mark {\n constructor(data, options = {}) {\n const { x: x3, y: y3, z } = options;\n super(\n data,\n {\n x: { value: x3, scale: \"x\", optional: true },\n y: { value: y3, scale: \"y\", optional: true },\n z: { value: z, optional: true }\n },\n initializer(options, function(data2, facets, channels, scales2, dimensions, context) {\n let { x: X3, y: Y3, z: Z } = channels;\n ({ x: X3, y: Y3 } = applyPosition(channels, scales2, context));\n Z = Z?.value;\n const C3 = new Array((X3 ?? Y3).length).fill(null);\n const [cx, cy] = applyFrameAnchor(this, dimensions);\n const xi = X3 ? (i) => X3[i] : constant(cx);\n const yi = Y3 ? (i) => Y3[i] : constant(cy);\n for (let I of facets) {\n if (X3) I = I.filter((i) => defined(xi(i)));\n if (Y3) I = I.filter((i) => defined(yi(i)));\n for (const [, J] of maybeGroup(I, Z)) {\n const delaunay = Delaunay.from(J, xi, yi);\n const voronoi3 = voronoiof(delaunay, dimensions);\n for (let i = 0, n = J.length; i < n; ++i) {\n C3[J[i]] = voronoi3.renderCell(i);\n }\n }\n }\n return { data: data2, facets, channels: { cells: { value: C3 } } };\n }),\n voronoiDefaults\n );\n }\n render(index2, scales2, channels, dimensions, context) {\n const { x: x3, y: y3 } = scales2;\n const { x: X3, y: Y3, cells: C3 } = channels;\n return create4(\"svg:g\", context).call(applyIndirectStyles, this, dimensions, context).call(applyTransform, this, { x: X3 && x3, y: Y3 && y3 }).call((g) => {\n g.selectAll().data(index2).enter().append(\"path\").call(applyDirectStyles, this).attr(\"d\", (i) => C3[i]).call(applyChannelStyles, this, channels);\n }).node();\n }\n};\nvar VoronoiMesh = class extends AbstractDelaunayMark {\n constructor(data, options) {\n super(data, options, voronoiMeshDefaults);\n this.fill = \"none\";\n }\n _render(delaunay, dimensions) {\n return voronoiof(delaunay, dimensions).render();\n }\n};\nfunction voronoiof(delaunay, dimensions) {\n const { width: width2, height: height2, marginTop: marginTop2, marginRight: marginRight2, marginBottom: marginBottom2, marginLeft: marginLeft2 } = dimensions;\n return delaunay.voronoi([marginLeft2, marginTop2, width2 - marginRight2, height2 - marginBottom2]);\n}\nfunction delaunayMark(DelaunayMark, data, { x: x3, y: y3, ...options } = {}) {\n [x3, y3] = maybeTuple(x3, y3);\n return new DelaunayMark(data, { ...options, x: x3, y: y3 });\n}\nfunction delaunayLink(data, options) {\n return delaunayMark(DelaunayLink, data, options);\n}\nfunction delaunayMesh(data, options) {\n return delaunayMark(DelaunayMesh, data, options);\n}\nfunction hull(data, options) {\n return delaunayMark(Hull, data, options);\n}\nfunction voronoi(data, { x: x3, y: y3, initializer: initializer2, ...options } = {}) {\n return delaunayMark(Voronoi2, data, { ...basic({ ...options, x: x3, y: y3 }, exclusiveFacets), initializer: initializer2 });\n}\nfunction voronoiMesh(data, options) {\n return delaunayMark(VoronoiMesh, data, options);\n}\n\n// ../../node_modules/@observablehq/plot/src/marks/density.js\nvar defaults17 = {\n ariaLabel: \"density\",\n fill: \"none\",\n stroke: \"currentColor\",\n strokeMiterlimit: 1\n};\nvar Density = class extends Mark {\n constructor(data, { x: x3, y: y3, z, weight, fill, stroke, ...options } = {}) {\n const fillDensity = isDensity(fill) && (fill = \"currentColor\", true);\n const strokeDensity = isDensity(stroke) && (stroke = \"currentColor\", true);\n super(\n data,\n {\n x: { value: x3, scale: \"x\", optional: true },\n y: { value: y3, scale: \"y\", optional: true },\n z: { value: maybeZ({ z, fill, stroke }), optional: true },\n weight: { value: weight, optional: true }\n },\n densityInitializer({ ...options, fill, stroke }, fillDensity, strokeDensity),\n defaults17\n );\n if (fillDensity) this.fill = void 0;\n if (strokeDensity) this.stroke = void 0;\n this.z = z;\n }\n filter(index2) {\n return index2;\n }\n render(index2, scales2, channels, dimensions, context) {\n const { contours } = channels;\n const path2 = path_default();\n return create4(\"svg:g\", context).call(applyIndirectStyles, this, dimensions, context).call(applyTransform, this, {}).call(\n (g) => g.selectAll().data(index2).enter().append(\"path\").call(applyDirectStyles, this).call(applyChannelStyles, this, channels).attr(\"d\", (i) => path2(contours[i]))\n ).node();\n }\n};\nfunction density(data, { x: x3, y: y3, ...options } = {}) {\n [x3, y3] = maybeTuple(x3, y3);\n return new Density(data, { ...options, x: x3, y: y3 });\n}\nvar dropChannels = /* @__PURE__ */ new Set([\"x\", \"y\", \"z\", \"weight\"]);\nfunction densityInitializer(options, fillDensity, strokeDensity) {\n const k2 = 100;\n let { bandwidth, thresholds } = options;\n bandwidth = bandwidth === void 0 ? 20 : +bandwidth;\n thresholds = thresholds === void 0 ? 20 : typeof thresholds?.[Symbol.iterator] === \"function\" ? coerceNumbers(thresholds) : +thresholds;\n return initializer(options, function(data, facets, channels, scales2, dimensions, context) {\n const W = channels.weight ? coerceNumbers(channels.weight.value) : null;\n const Z = channels.z?.value;\n const { z } = this;\n const [cx, cy] = applyFrameAnchor(this, dimensions);\n const { width: width2, height: height2 } = dimensions;\n const { x: X3, y: Y3 } = applyPosition(channels, scales2, context);\n const newChannels = Object.fromEntries(\n Object.entries(channels).filter(([key]) => !dropChannels.has(key)).map(([key, channel]) => [key, { ...channel, value: [] }])\n );\n const FD = fillDensity && [];\n const SD = strokeDensity && [];\n const density3 = density_default().x(X3 ? (i) => X3[i] : cx).y(Y3 ? (i) => Y3[i] : cy).weight(W ? (i) => W[i] : 1).size([width2, height2]).bandwidth(bandwidth);\n const facetsContours = [];\n for (const facet of facets) {\n const facetContours = [];\n facetsContours.push(facetContours);\n for (const index2 of Z ? groupZ2(facet, Z, z) : [facet]) {\n const contour3 = density3.contours(index2);\n facetContours.push([index2, contour3]);\n }\n }\n let T = thresholds;\n if (!(T instanceof TypedArray2)) {\n let maxValue = 0;\n for (const facetContours of facetsContours) {\n for (const [, contour3] of facetContours) {\n const max4 = contour3.max;\n if (max4 > maxValue) maxValue = max4;\n }\n }\n T = Float64Array.from({ length: thresholds - 1 }, (_, i) => maxValue * k2 * (i + 1) / thresholds);\n }\n const newFacets = [];\n const contours = [];\n for (const facetContours of facetsContours) {\n const newFacet = [];\n newFacets.push(newFacet);\n for (const [index2, contour3] of facetContours) {\n for (const t of T) {\n newFacet.push(contours.length);\n contours.push(contour3(t / k2));\n if (FD) FD.push(t);\n if (SD) SD.push(t);\n for (const key in newChannels) {\n newChannels[key].value.push(channels[key].value[index2[0]]);\n }\n }\n }\n }\n if (FD) FD.push(0);\n if (SD) SD.push(0);\n return {\n data,\n facets: newFacets,\n channels: {\n ...newChannels,\n ...FD && { fill: { value: FD, scale: \"color\" } },\n ...SD && { stroke: { value: SD, scale: \"color\" } },\n contours: { value: contours }\n }\n };\n });\n}\nfunction isDensity(value) {\n return /^density$/i.test(value);\n}\n\n// ../../node_modules/@observablehq/plot/src/marks/difference.js\nfunction differenceX(data, options) {\n return differenceK(\"x\", data, options);\n}\nfunction differenceY(data, options) {\n return differenceK(\"y\", data, options);\n}\nfunction differenceK(k2, data, {\n x1: x12,\n x2: x22,\n y1: y12,\n y2: y22,\n x: x3 = x12 === void 0 && x22 === void 0 ? k2 === \"y\" ? indexOf : identity7 : void 0,\n y: y3 = y12 === void 0 && y22 === void 0 ? k2 === \"x\" ? indexOf : identity7 : void 0,\n fill,\n // ignored\n positiveFill = \"#3ca951\",\n negativeFill = \"#4269d0\",\n fillOpacity = 1,\n positiveFillOpacity = fillOpacity,\n negativeFillOpacity = fillOpacity,\n stroke,\n strokeOpacity,\n z = maybeColorChannel(stroke)[0],\n clip,\n // optional additional clip for area\n tip: tip2,\n render,\n ...options\n} = {}) {\n [x12, x22] = memoTuple(x3, x12, x22);\n [y12, y22] = memoTuple(y3, y12, y22);\n if (x12 === x22 && y12 === y22) {\n if (k2 === \"y\") y12 = memo(0);\n else x12 = memo(0);\n }\n ({ tip: tip2 } = withTip({ tip: tip2 }, k2 === \"y\" ? \"x\" : \"y\"));\n return marks(\n !isNoneish(positiveFill) ? Object.assign(\n area(data, {\n x1: x12,\n x2: x22,\n y1: y12,\n y2: y22,\n z,\n fill: positiveFill,\n fillOpacity: positiveFillOpacity,\n render: composeRender(render, clipDifference(k2, true)),\n clip,\n ...options\n }),\n { ariaLabel: \"positive difference\" }\n ) : null,\n !isNoneish(negativeFill) ? Object.assign(\n area(data, {\n x1: x12,\n x2: x22,\n y1: y12,\n y2: y22,\n z,\n fill: negativeFill,\n fillOpacity: negativeFillOpacity,\n render: composeRender(render, clipDifference(k2, false)),\n clip,\n ...options\n }),\n { ariaLabel: \"negative difference\" }\n ) : null,\n line(data, {\n x: x22,\n y: y22,\n z,\n stroke,\n strokeOpacity,\n tip: tip2,\n clip: true,\n ...options\n })\n );\n}\nfunction memoTuple(x3, x12, x22) {\n if (x12 === void 0 && x22 === void 0) {\n x12 = x22 = memo(x3);\n } else if (x12 === void 0) {\n x22 = memo(x22);\n x12 = x3 === void 0 ? x22 : memo(x3);\n } else if (x22 === void 0) {\n x12 = memo(x12);\n x22 = x3 === void 0 ? x12 : memo(x3);\n } else {\n x12 = memo(x12);\n x22 = memo(x22);\n }\n return [x12, x22];\n}\nfunction memo(v2) {\n let V;\n const { value, label: label2 = labelof(value) } = maybeValue(v2);\n return { transform: (data) => V || (V = valueof(data, value)), label: label2 };\n}\nfunction clipDifference(k2, positive2) {\n const f = k2 === \"x\" ? \"y\" : \"x\";\n const f1 = `${f}1`;\n const f2 = `${f}2`;\n const k1 = `${k2}1`;\n const k22 = `${k2}2`;\n return (index2, scales2, channels, dimensions, context, next) => {\n const { [f1]: F1, [f2]: F2 } = channels;\n const K1 = new Float32Array(F1.length);\n const K2 = new Float32Array(F2.length);\n const m = dimensions[k2 === \"y\" ? \"height\" : \"width\"];\n (positive2 === inferScaleOrder(scales2[k2]) < 0 ? K1 : K2).fill(m);\n const oc = next(index2, scales2, { ...channels, [f2]: F1, [k22]: K2 }, dimensions, context);\n const og = next(index2, scales2, { ...channels, [f1]: F2, [k1]: K1 }, dimensions, context);\n const c4 = oc.querySelector(\"g\") ?? oc;\n const g = og.querySelector(\"g\") ?? og;\n for (let i = 0; c4.firstChild; i += 2) {\n const id2 = getClipId();\n const clipPath = create4(\"svg:clipPath\", context).attr(\"id\", id2).node();\n clipPath.appendChild(c4.firstChild);\n g.childNodes[i].setAttribute(\"clip-path\", `url(#${id2})`);\n g.insertBefore(clipPath, g.childNodes[i]);\n }\n return og;\n };\n}\n\n// ../../node_modules/@observablehq/plot/src/transforms/centroid.js\nfunction centroid2({ geometry = identity7, ...options } = {}) {\n const getG = memoize1((data) => valueof(data, geometry));\n return initializer(\n // Suppress defaults for x and y since they will be computed by the initializer.\n // Propagate the (memoized) geometry channel in case it’s still needed.\n { ...options, x: null, y: null, geometry: { transform: getG } },\n (data, facets, channels, scales2, dimensions, { projection: projection3 }) => {\n const G = getG(data);\n const n = G.length;\n const X3 = new Float64Array(n);\n const Y3 = new Float64Array(n);\n const path2 = path_default(projection3);\n for (let i = 0; i < n; ++i) [X3[i], Y3[i]] = path2.centroid(G[i]);\n return {\n data,\n facets,\n channels: {\n x: { value: X3, scale: projection3 == null ? \"x\" : null, source: null },\n y: { value: Y3, scale: projection3 == null ? \"y\" : null, source: null }\n }\n };\n }\n );\n}\nfunction geoCentroid({ geometry = identity7, ...options } = {}) {\n const getG = memoize1((data) => valueof(data, geometry));\n const getC = memoize1((data) => valueof(getG(data), centroid_default));\n return {\n ...options,\n x: { transform: (data) => Float64Array.from(getC(data), ([x3]) => x3) },\n y: { transform: (data) => Float64Array.from(getC(data), ([, y3]) => y3) },\n geometry: { transform: getG }\n };\n}\n\n// ../../node_modules/@observablehq/plot/src/marks/geo.js\nvar defaults18 = {\n ariaLabel: \"geo\",\n fill: \"none\",\n stroke: \"currentColor\",\n strokeWidth: 1,\n strokeLinecap: \"round\",\n strokeLinejoin: \"round\",\n strokeMiterlimit: 1\n};\nvar Geo = class extends Mark {\n constructor(data, options = {}) {\n const [vr, cr] = maybeNumberChannel(options.r, 3);\n super(\n data,\n {\n x: { value: options.tip ? options.x : null, scale: \"x\", optional: true },\n y: { value: options.tip ? options.y : null, scale: \"y\", optional: true },\n r: { value: vr, scale: \"r\", filter: positive, optional: true },\n geometry: { value: options.geometry, scale: \"projection\" }\n },\n withDefaultSort(options),\n defaults18\n );\n this.r = cr;\n }\n render(index2, scales2, channels, dimensions, context) {\n const { geometry: G, r: R } = channels;\n const path2 = path_default(context.projection ?? scaleProjection2(scales2));\n const { r } = this;\n if (negative(r)) index2 = [];\n else if (r !== void 0) path2.pointRadius(r);\n return create4(\"svg:g\", context).call(applyIndirectStyles, this, dimensions, context).call(applyTransform, this, scales2).call((g) => {\n g.selectAll().data(index2).enter().append(\"path\").call(applyDirectStyles, this).attr(\"d\", R ? (i) => path2.pointRadius(R[i])(G[i]) : (i) => path2(G[i])).call(applyChannelStyles, this, channels);\n }).node();\n }\n};\nfunction scaleProjection2({ x: X3, y: Y3 }) {\n if (X3 || Y3) {\n X3 ??= (x3) => x3;\n Y3 ??= (y3) => y3;\n return transform_default({\n point(x3, y3) {\n this.stream.point(X3(x3), Y3(y3));\n }\n });\n }\n}\nfunction geo(data, options = {}) {\n if (options.tip && options.x === void 0 && options.y === void 0) options = centroid2(options);\n else if (options.geometry === void 0) options = { ...options, geometry: identity7 };\n return new Geo(data, options);\n}\nfunction sphere({ strokeWidth = 1.5, ...options } = {}) {\n return geo({ type: \"Sphere\" }, { strokeWidth, ...options });\n}\nfunction graticule2({ strokeOpacity = 0.1, ...options } = {}) {\n return geo(graticule10(), { strokeOpacity, ...options });\n}\n\n// ../../node_modules/@observablehq/plot/src/transforms/hexbin.js\nvar ox = 0.5;\nvar oy = 0;\nfunction hexbin(outputs = { fill: \"count\" }, { binWidth, ...options } = {}) {\n const { z } = options;\n binWidth = binWidth === void 0 ? 20 : number5(binWidth);\n outputs = maybeGroupOutputs(outputs, options);\n if (hasOutput(outputs, \"fill\")) options.channels = { ...options.channels, fill: { value: [] } };\n if (options.symbol === void 0) options.symbol = \"hexagon\";\n if (options.r === void 0 && !hasOutput(outputs, \"r\")) options.r = binWidth / 2;\n return initializer(options, (data, facets, channels, scales2, _, context) => {\n let { x: X3, y: Y3, z: Z, fill: F, stroke: S, symbol: Q } = channels;\n if (X3 === void 0) throw new Error(\"missing channel: x\");\n if (Y3 === void 0) throw new Error(\"missing channel: y\");\n ({ x: X3, y: Y3 } = applyPosition(channels, scales2, context));\n Z = Z ? Z.value : valueof(data, z);\n F = F?.value;\n S = S?.value;\n Q = Q?.value;\n const G = maybeSubgroup(outputs, { z: Z, fill: F, stroke: S, symbol: Q });\n const GZ = Z && [];\n const GF = F && [];\n const GS = S && [];\n const GQ = Q && [];\n const binFacets = [];\n const BX = [];\n const BY = [];\n let i = -1;\n for (const o of outputs) o.initialize(data);\n for (const facet of facets) {\n const binFacet = [];\n for (const o of outputs) o.scope(\"facet\", facet);\n for (const [f, I] of maybeGroup(facet, G)) {\n for (const { index: b, extent: extent4 } of hbin(data, I, X3, Y3, binWidth)) {\n binFacet.push(++i);\n BX.push(extent4.x);\n BY.push(extent4.y);\n if (Z) GZ.push(G === Z ? f : Z[b[0]]);\n if (F) GF.push(G === F ? f : F[b[0]]);\n if (S) GS.push(G === S ? f : S[b[0]]);\n if (Q) GQ.push(G === Q ? f : Q[b[0]]);\n for (const o of outputs) o.reduce(b, extent4);\n }\n }\n binFacets.push(binFacet);\n }\n const sx = channels.x.scale;\n const sy = channels.y.scale;\n const binChannels = {\n x: { value: BX, source: scales2[sx] ? { value: map3(BX, scales2[sx].invert), scale: sx } : null },\n y: { value: BY, source: scales2[sy] ? { value: map3(BY, scales2[sy].invert), scale: sy } : null },\n ...Z && { z: { value: GZ } },\n ...F && { fill: { value: GF, scale: \"auto\" } },\n ...S && { stroke: { value: GS, scale: \"auto\" } },\n ...Q && { symbol: { value: GQ, scale: \"auto\" } },\n ...Object.fromEntries(\n outputs.map(({ name: name2, output }) => [\n name2,\n {\n scale: \"auto\",\n label: output.label,\n radius: name2 === \"r\" ? binWidth / 2 : void 0,\n value: output.transform()\n }\n ])\n )\n };\n return { data, facets: binFacets, channels: binChannels };\n });\n}\nfunction hbin(data, I, X3, Y3, dx) {\n const dy = dx * (1.5 / sqrt35);\n const bins2 = /* @__PURE__ */ new Map();\n for (const i of I) {\n let px = X3[i], py = Y3[i];\n if (isNaN(px) || isNaN(py)) continue;\n let pj = Math.round(py = (py - oy) / dy), pi5 = Math.round(px = (px - ox) / dx - (pj & 1) / 2), py1 = py - pj;\n if (Math.abs(py1) * 3 > 1) {\n let px1 = px - pi5, pi22 = pi5 + (px < pi5 ? -1 : 1) / 2, pj2 = pj + (py < pj ? -1 : 1), px2 = px - pi22, py2 = py - pj2;\n if (px1 * px1 + py1 * py1 > px2 * px2 + py2 * py2) pi5 = pi22 + (pj & 1 ? 1 : -1) / 2, pj = pj2;\n }\n const key = `${pi5},${pj}`;\n let bin3 = bins2.get(key);\n if (bin3 === void 0) {\n bin3 = { index: [], extent: { data, x: (pi5 + (pj & 1) / 2) * dx + ox, y: pj * dy + oy } };\n bins2.set(key, bin3);\n }\n bin3.index.push(i);\n }\n return bins2.values();\n}\n\n// ../../node_modules/@observablehq/plot/src/marks/hexgrid.js\nvar defaults19 = {\n ariaLabel: \"hexgrid\",\n fill: \"none\",\n stroke: \"currentColor\",\n strokeOpacity: 0.1\n};\nfunction hexgrid(options) {\n return new Hexgrid(options);\n}\nvar Hexgrid = class extends Mark {\n constructor({ binWidth = 20, clip = true, ...options } = {}) {\n super(singleton, void 0, { clip, ...options }, defaults19);\n this.binWidth = number5(binWidth);\n }\n render(index2, scales2, channels, dimensions, context) {\n const { binWidth } = this;\n const { marginTop: marginTop2, marginRight: marginRight2, marginBottom: marginBottom2, marginLeft: marginLeft2, width: width2, height: height2 } = dimensions;\n const x06 = marginLeft2 - ox, x12 = width2 - marginRight2 - ox, y06 = marginTop2 - oy, y12 = height2 - marginBottom2 - oy, rx = binWidth / 2, ry = rx * sqrt4_3, hy = ry / 2, wx = rx * 2, wy = ry * 1.5, i0 = Math.floor(x06 / wx), i1 = Math.ceil(x12 / wx), j0 = Math.floor((y06 + hy) / wy), j1 = Math.ceil((y12 - hy) / wy) + 1, path2 = `m0,${round(-ry)}l${round(rx)},${round(hy)}v${round(ry)}l${round(-rx)},${round(hy)}`;\n let d = path2;\n for (let j = j0; j < j1; ++j) {\n for (let i = i0; i < i1; ++i) {\n d += `M${round(i * wx + (j & 1) * rx)},${round(j * wy)}${path2}`;\n }\n }\n return create4(\"svg:g\", context).datum(0).call(applyIndirectStyles, this, dimensions, context).call(applyTransform, this, {}, offset + ox, offset + oy).call((g) => g.append(\"path\").call(applyDirectStyles, this).call(applyChannelStyles, this, channels).attr(\"d\", d)).node();\n }\n};\nfunction round(x3) {\n return Math.round(x3 * 1e3) / 1e3;\n}\n\n// ../../node_modules/@observablehq/plot/src/marks/image.js\nvar defaults20 = {\n ariaLabel: \"image\",\n fill: null,\n stroke: null\n};\nfunction isPath(string2) {\n return /^\\.*\\//.test(string2);\n}\nfunction isUrl(string2) {\n return /^(blob|data|file|http|https):/i.test(string2);\n}\nfunction maybePathChannel(value) {\n return typeof value === \"string\" && (isPath(value) || isUrl(value)) ? [void 0, value] : [value, void 0];\n}\nvar Image = class extends Mark {\n constructor(data, options = {}) {\n let { x: x3, y: y3, r, width: width2, height: height2, rotate, src, preserveAspectRatio, crossOrigin, frameAnchor, imageRendering } = options;\n if (r == null) r = void 0;\n if (r === void 0 && width2 === void 0 && height2 === void 0) width2 = height2 = 16;\n else if (width2 === void 0 && height2 !== void 0) width2 = height2;\n else if (height2 === void 0 && width2 !== void 0) height2 = width2;\n const [vs, cs] = maybePathChannel(src);\n const [vr, cr] = maybeNumberChannel(r);\n const [vw, cw] = maybeNumberChannel(width2, cr !== void 0 ? cr * 2 : void 0);\n const [vh, ch] = maybeNumberChannel(height2, cr !== void 0 ? cr * 2 : void 0);\n const [va, ca3] = maybeNumberChannel(rotate, 0);\n super(\n data,\n {\n x: { value: x3, scale: \"x\", optional: true },\n y: { value: y3, scale: \"y\", optional: true },\n r: { value: vr, scale: \"r\", filter: positive, optional: true },\n width: { value: vw, filter: positive, optional: true },\n height: { value: vh, filter: positive, optional: true },\n rotate: { value: va, optional: true },\n src: { value: vs, optional: true }\n },\n withDefaultSort(options),\n defaults20\n );\n this.src = cs;\n this.width = cw;\n this.rotate = ca3;\n this.height = ch;\n this.r = cr;\n this.preserveAspectRatio = impliedString(preserveAspectRatio, \"xMidYMid\");\n this.crossOrigin = string(crossOrigin);\n this.frameAnchor = maybeFrameAnchor(frameAnchor);\n this.imageRendering = impliedString(imageRendering, \"auto\");\n }\n render(index2, scales2, channels, dimensions, context) {\n const { x: x3, y: y3 } = scales2;\n const { x: X3, y: Y3, width: W, height: H, r: R, rotate: A5, src: S } = channels;\n const { r, width: width2, height: height2, rotate } = this;\n const [cx, cy] = applyFrameAnchor(this, dimensions);\n return create4(\"svg:g\", context).call(applyIndirectStyles, this, dimensions, context).call(applyTransform, this, { x: X3 && x3, y: Y3 && y3 }).call(\n (g) => g.selectAll().data(index2).enter().append(\"image\").call(applyDirectStyles, this).attr(\"x\", position2(X3, W, R, cx, width2, r)).attr(\"y\", position2(Y3, H, R, cy, height2, r)).attr(\"width\", W ? (i) => W[i] : width2 !== void 0 ? width2 : R ? (i) => R[i] * 2 : r * 2).attr(\"height\", H ? (i) => H[i] : height2 !== void 0 ? height2 : R ? (i) => R[i] * 2 : r * 2).attr(\"transform\", A5 ? (i) => `rotate(${A5[i]})` : rotate ? `rotate(${rotate})` : null).attr(\"transform-origin\", A5 || rotate ? template`${X3 ? (i) => X3[i] : cx}px ${Y3 ? (i) => Y3[i] : cy}px` : null).call(applyAttr, \"href\", S ? (i) => S[i] : this.src).call(applyAttr, \"preserveAspectRatio\", this.preserveAspectRatio).call(applyAttr, \"crossorigin\", this.crossOrigin).call(applyAttr, \"image-rendering\", this.imageRendering).call(applyAttr, \"clip-path\", R ? (i) => `circle(${R[i]}px)` : r !== void 0 ? `circle(${r}px)` : null).call(applyChannelStyles, this, channels)\n ).node();\n }\n};\nfunction position2(X3, W, R, x3, w, r) {\n return W && X3 ? (i) => X3[i] - W[i] / 2 : W ? (i) => x3 - W[i] / 2 : X3 && w !== void 0 ? (i) => X3[i] - w / 2 : w !== void 0 ? x3 - w / 2 : R && X3 ? (i) => X3[i] - R[i] : R ? (i) => x3 - R[i] : X3 ? (i) => X3[i] - r : x3 - r;\n}\nfunction image(data, { x: x3, y: y3, ...options } = {}) {\n if (options.frameAnchor === void 0) [x3, y3] = maybeTuple(x3, y3);\n return new Image(data, { ...options, x: x3, y: y3 });\n}\n\n// ../../node_modules/@observablehq/plot/src/stats.js\nfunction ibetainv(p, a2, b) {\n var EPS2 = 1e-8;\n var a1 = a2 - 1;\n var b1 = b - 1;\n var j = 0;\n var lna, lnb, pp, t, u4, err, x3, al, h, w, afac;\n if (p <= 0) return 0;\n if (p >= 1) return 1;\n if (a2 >= 1 && b >= 1) {\n pp = p < 0.5 ? p : 1 - p;\n t = Math.sqrt(-2 * Math.log(pp));\n x3 = (2.30753 + t * 0.27061) / (1 + t * (0.99229 + t * 0.04481)) - t;\n if (p < 0.5) x3 = -x3;\n al = (x3 * x3 - 3) / 6;\n h = 2 / (1 / (2 * a2 - 1) + 1 / (2 * b - 1));\n w = x3 * Math.sqrt(al + h) / h - (1 / (2 * b - 1) - 1 / (2 * a2 - 1)) * (al + 5 / 6 - 2 / (3 * h));\n x3 = a2 / (a2 + b * Math.exp(2 * w));\n } else {\n lna = Math.log(a2 / (a2 + b));\n lnb = Math.log(b / (a2 + b));\n t = Math.exp(a2 * lna) / a2;\n u4 = Math.exp(b * lnb) / b;\n w = t + u4;\n if (p < t / w) x3 = Math.pow(a2 * w * p, 1 / a2);\n else x3 = 1 - Math.pow(b * w * (1 - p), 1 / b);\n }\n afac = -gammaln(a2) - gammaln(b) + gammaln(a2 + b);\n for (; j < 10; j++) {\n if (x3 === 0 || x3 === 1) return x3;\n err = ibeta(x3, a2, b) - p;\n t = Math.exp(a1 * Math.log(x3) + b1 * Math.log(1 - x3) + afac);\n u4 = err / t;\n x3 -= t = u4 / (1 - 0.5 * Math.min(1, u4 * (a1 / x3 - b1 / (1 - x3))));\n if (x3 <= 0) x3 = 0.5 * (x3 + t);\n if (x3 >= 1) x3 = 0.5 * (x3 + t + 1);\n if (Math.abs(t) < EPS2 * x3 && j > 0) break;\n }\n return x3;\n}\nfunction ibeta(x3, a2, b) {\n var bt = x3 === 0 || x3 === 1 ? 0 : Math.exp(gammaln(a2 + b) - gammaln(a2) - gammaln(b) + a2 * Math.log(x3) + b * Math.log(1 - x3));\n if (x3 < 0 || x3 > 1) return false;\n if (x3 < (a2 + 1) / (a2 + b + 2))\n return bt * betacf(x3, a2, b) / a2;\n return 1 - bt * betacf(1 - x3, b, a2) / b;\n}\nfunction betacf(x3, a2, b) {\n var fpmin = 1e-30;\n var m = 1;\n var qab = a2 + b;\n var qap = a2 + 1;\n var qam = a2 - 1;\n var c4 = 1;\n var d = 1 - qab * x3 / qap;\n var m2, aa2, del, h;\n if (Math.abs(d) < fpmin) d = fpmin;\n d = 1 / d;\n h = d;\n for (; m <= 100; m++) {\n m2 = 2 * m;\n aa2 = m * (b - m) * x3 / ((qam + m2) * (a2 + m2));\n d = 1 + aa2 * d;\n if (Math.abs(d) < fpmin) d = fpmin;\n c4 = 1 + aa2 / c4;\n if (Math.abs(c4) < fpmin) c4 = fpmin;\n d = 1 / d;\n h *= d * c4;\n aa2 = -(a2 + m) * (qab + m) * x3 / ((a2 + m2) * (qap + m2));\n d = 1 + aa2 * d;\n if (Math.abs(d) < fpmin) d = fpmin;\n c4 = 1 + aa2 / c4;\n if (Math.abs(c4) < fpmin) c4 = fpmin;\n d = 1 / d;\n del = d * c4;\n h *= del;\n if (Math.abs(del - 1) < 3e-7) break;\n }\n return h;\n}\nfunction gammaln(x3) {\n var j = 0;\n var cof = [\n 76.18009172947146,\n -86.5053203294167,\n 24.01409824083091,\n -1.231739572450155,\n 0.001208650973866179,\n -5395239384953e-18\n ];\n var ser = 1.000000000190015;\n var xx, y3, tmp;\n tmp = (y3 = xx = x3) + 5.5;\n tmp -= (xx + 0.5) * Math.log(tmp);\n for (; j < 6; j++) ser += cof[j] / ++y3;\n return Math.log(2.506628274631 * ser / xx) - tmp;\n}\nfunction qt(p, dof) {\n var x3 = ibetainv(2 * Math.min(p, 1 - p), 0.5 * dof, 0.5);\n x3 = Math.sqrt(dof * (1 - x3) / x3);\n return p > 0.5 ? x3 : -x3;\n}\n\n// ../../node_modules/@observablehq/plot/src/marks/linearRegression.js\nvar defaults21 = {\n ariaLabel: \"linear-regression\",\n fill: \"currentColor\",\n fillOpacity: 0.1,\n stroke: \"currentColor\",\n strokeWidth: 1.5,\n strokeLinecap: \"round\",\n strokeLinejoin: \"round\",\n strokeMiterlimit: 1\n};\nvar LinearRegression = class extends Mark {\n constructor(data, options = {}) {\n const { x: x3, y: y3, z, ci = 0.95, precision = 4 } = options;\n super(\n data,\n {\n x: { value: x3, scale: \"x\" },\n y: { value: y3, scale: \"y\" },\n z: { value: maybeZ(options), optional: true }\n },\n options,\n defaults21\n );\n this.z = z;\n this.ci = +ci;\n this.precision = +precision;\n if (!(0 <= this.ci && this.ci < 1)) throw new Error(`invalid ci; not in [0, 1): ${ci}`);\n if (!(this.precision > 0)) throw new Error(`invalid precision: ${precision}`);\n }\n render(index2, scales2, channels, dimensions, context) {\n const { x: X3, y: Y3, z: Z } = channels;\n const { ci } = this;\n return create4(\"svg:g\", context).call(applyIndirectStyles, this, dimensions, context).call(applyTransform, this, scales2).call(\n (g) => g.selectAll().data(Z ? groupZ2(index2, Z, this.z) : [index2]).enter().call(\n (enter) => enter.append(\"path\").attr(\"fill\", \"none\").call(applyDirectStyles, this).call(applyGroupedChannelStyles, this, { ...channels, fill: null, fillOpacity: null }).attr(\"d\", (I) => this._renderLine(I, X3, Y3)).call(\n ci && !isNone(this.fill) ? (path2) => path2.select(pathBefore).attr(\"stroke\", \"none\").call(applyDirectStyles, this).call(applyGroupedChannelStyles, this, {\n ...channels,\n stroke: null,\n strokeOpacity: null,\n strokeWidth: null\n }).attr(\"d\", (I) => this._renderBand(I, X3, Y3)) : () => {\n }\n )\n )\n ).node();\n }\n};\nfunction pathBefore() {\n return this.parentNode.insertBefore(this.ownerDocument.createElementNS(namespaces_default.svg, \"path\"), this);\n}\nvar LinearRegressionX = class extends LinearRegression {\n constructor(data, options) {\n super(data, options);\n }\n _renderBand(I, X3, Y3) {\n const { ci, precision } = this;\n const [y12, y22] = extent(I, (i) => Y3[i]);\n const f = linearRegressionF(I, Y3, X3);\n const g = confidenceIntervalF(I, Y3, X3, (1 - ci) / 2, f);\n return area_default3().y((y3) => y3).x0((y3) => g(y3, -1)).x1((y3) => g(y3, 1))(range(y12, y22 - precision / 2, precision).concat(y22));\n }\n _renderLine(I, X3, Y3) {\n const [y12, y22] = extent(I, (i) => Y3[i]);\n const f = linearRegressionF(I, Y3, X3);\n return `M${f(y12)},${y12}L${f(y22)},${y22}`;\n }\n};\nvar LinearRegressionY = class extends LinearRegression {\n constructor(data, options) {\n super(data, options);\n }\n _renderBand(I, X3, Y3) {\n const { ci, precision } = this;\n const [x12, x22] = extent(I, (i) => X3[i]);\n const f = linearRegressionF(I, X3, Y3);\n const g = confidenceIntervalF(I, X3, Y3, (1 - ci) / 2, f);\n return area_default3().x((x3) => x3).y0((x3) => g(x3, -1)).y1((x3) => g(x3, 1))(range(x12, x22 - precision / 2, precision).concat(x22));\n }\n _renderLine(I, X3, Y3) {\n const [x12, x22] = extent(I, (i) => X3[i]);\n const f = linearRegressionF(I, X3, Y3);\n return `M${x12},${f(x12)}L${x22},${f(x22)}`;\n }\n};\nfunction linearRegressionX(data, { y: y3 = indexOf, x: x3 = identity7, stroke, fill = isNoneish(stroke) ? \"currentColor\" : stroke, ...options } = {}) {\n return new LinearRegressionX(data, maybeDenseIntervalY({ ...options, x: x3, y: y3, fill, stroke }));\n}\nfunction linearRegressionY(data, { x: x3 = indexOf, y: y3 = identity7, stroke, fill = isNoneish(stroke) ? \"currentColor\" : stroke, ...options } = {}) {\n return new LinearRegressionY(data, maybeDenseIntervalX({ ...options, x: x3, y: y3, fill, stroke }));\n}\nfunction linearRegressionF(I, X3, Y3) {\n let sumX = 0, sumY = 0, sumXY = 0, sumX2 = 0;\n for (const i of I) {\n const xi = X3[i];\n const yi = Y3[i];\n sumX += xi;\n sumY += yi;\n sumXY += xi * yi;\n sumX2 += xi * xi;\n }\n const n = I.length;\n const slope = (n * sumXY - sumX * sumY) / (n * sumX2 - sumX * sumX);\n const intercept = (sumY - slope * sumX) / n;\n return (x3) => slope * x3 + intercept;\n}\nfunction confidenceIntervalF(I, X3, Y3, p, f) {\n const mean3 = sum2(I, (i) => X3[i]) / I.length;\n let a2 = 0, b = 0;\n for (const i of I) {\n a2 += (X3[i] - mean3) ** 2;\n b += (Y3[i] - f(X3[i])) ** 2;\n }\n const sy = Math.sqrt(b / (I.length - 2));\n const t = qt(p, I.length - 2);\n return (x3, k2) => {\n const Y4 = f(x3);\n const se = sy * Math.sqrt(1 / I.length + (x3 - mean3) ** 2 / a2);\n return Y4 + k2 * t * se;\n };\n}\n\n// ../../node_modules/@observablehq/plot/src/transforms/tree.js\nfunction treeNode({\n path: path2 = identity7,\n // the delimited path\n delimiter,\n // how the path is separated\n frameAnchor,\n treeLayout = tree_default,\n treeSort,\n treeSeparation,\n treeAnchor,\n treeFilter,\n ...options\n} = {}) {\n treeAnchor = maybeTreeAnchor(treeAnchor);\n treeSort = maybeTreeSort(treeSort);\n if (treeFilter != null) treeFilter = maybeNodeValue(treeFilter);\n if (frameAnchor === void 0) frameAnchor = treeAnchor.frameAnchor;\n const normalize4 = normalizer(delimiter);\n const outputs = treeOutputs(options, maybeNodeValue);\n const [X3, setX] = column2();\n const [Y3, setY] = column2();\n return {\n x: X3,\n y: Y3,\n frameAnchor,\n ...basic(options, (data, facets) => {\n const P = normalize4(valueof(data, path2));\n const X4 = setX([]);\n const Y4 = setY([]);\n let treeIndex = -1;\n const treeData = [];\n const treeFacets = [];\n const rootof = stratify_default().path((i) => P[i]);\n const setData = isArray2(data) ? (node) => node.data = data[node.data] : (node) => node.data = data.get(node.data);\n const layout = treeLayout();\n if (layout.nodeSize) layout.nodeSize([1, 1]);\n if (layout.separation && treeSeparation !== void 0) layout.separation(treeSeparation ?? one2);\n for (const o of outputs) o[output_values] = o[output_setValues]([]);\n for (const facet of facets) {\n const treeFacet = [];\n const root2 = rootof(facet.filter((i) => P[i] != null)).each(setData);\n if (treeSort != null) root2.sort(treeSort);\n layout(root2);\n for (const node of root2.descendants()) {\n if (treeFilter != null && !treeFilter(node)) continue;\n treeFacet.push(++treeIndex);\n treeData[treeIndex] = node.data;\n treeAnchor.position(node, treeIndex, X4, Y4);\n for (const o of outputs) o[output_values][treeIndex] = o[output_evaluate](node);\n }\n treeFacets.push(treeFacet);\n }\n return { data: treeData, facets: treeFacets };\n }),\n ...Object.fromEntries(outputs)\n };\n}\nfunction treeLink({\n path: path2 = identity7,\n // the delimited path\n delimiter,\n // how the path is separated\n curve = \"bump-x\",\n stroke = \"#555\",\n strokeWidth = 1.5,\n strokeOpacity = 0.5,\n treeLayout = tree_default,\n treeSort,\n treeSeparation,\n treeAnchor,\n treeFilter,\n ...options\n} = {}) {\n treeAnchor = maybeTreeAnchor(treeAnchor);\n treeSort = maybeTreeSort(treeSort);\n if (treeFilter != null) treeFilter = maybeLinkValue(treeFilter);\n options = { curve, stroke, strokeWidth, strokeOpacity, ...options };\n const normalize4 = normalizer(delimiter);\n const outputs = treeOutputs(options, maybeLinkValue);\n const [X13, setX1] = column2();\n const [X23, setX2] = column2();\n const [Y13, setY1] = column2();\n const [Y23, setY2] = column2();\n return {\n x1: X13,\n x2: X23,\n y1: Y13,\n y2: Y23,\n ...basic(options, (data, facets) => {\n const P = normalize4(valueof(data, path2));\n const X14 = setX1([]);\n const X24 = setX2([]);\n const Y14 = setY1([]);\n const Y24 = setY2([]);\n let treeIndex = -1;\n const treeData = [];\n const treeFacets = [];\n const rootof = stratify_default().path((i) => P[i]);\n const layout = treeLayout();\n if (layout.nodeSize) layout.nodeSize([1, 1]);\n if (layout.separation && treeSeparation !== void 0) layout.separation(treeSeparation ?? one2);\n for (const o of outputs) o[output_values] = o[output_setValues]([]);\n for (const facet of facets) {\n const treeFacet = [];\n const root2 = rootof(facet.filter((i) => P[i] != null)).each((node) => node.data = data[node.data]);\n if (treeSort != null) root2.sort(treeSort);\n layout(root2);\n for (const { source, target } of root2.links()) {\n if (treeFilter != null && !treeFilter(target, source)) continue;\n treeFacet.push(++treeIndex);\n treeData[treeIndex] = target.data;\n treeAnchor.position(source, treeIndex, X14, Y14);\n treeAnchor.position(target, treeIndex, X24, Y24);\n for (const o of outputs) o[output_values][treeIndex] = o[output_evaluate](target, source);\n }\n treeFacets.push(treeFacet);\n }\n return { data: treeData, facets: treeFacets };\n }),\n ...Object.fromEntries(outputs)\n };\n}\nfunction maybeTreeAnchor(anchor = \"left\") {\n switch (`${anchor}`.trim().toLowerCase()) {\n case \"left\":\n return treeAnchorLeft;\n case \"right\":\n return treeAnchorRight;\n }\n throw new Error(`invalid tree anchor: ${anchor}`);\n}\nvar treeAnchorLeft = {\n frameAnchor: \"left\",\n dx: 6,\n position({ x: x3, y: y3 }, i, X3, Y3) {\n X3[i] = y3;\n Y3[i] = -x3;\n }\n};\nvar treeAnchorRight = {\n frameAnchor: \"right\",\n dx: -6,\n position({ x: x3, y: y3 }, i, X3, Y3) {\n X3[i] = -y3;\n Y3[i] = -x3;\n }\n};\nfunction maybeTreeSort(sort3) {\n return sort3 == null || typeof sort3 === \"function\" ? sort3 : `${sort3}`.trim().toLowerCase().startsWith(\"node:\") ? nodeSort(maybeNodeValue(sort3)) : nodeSort(nodeData(sort3));\n}\nfunction nodeSort(value) {\n return (a2, b) => ascendingDefined2(value(a2), value(b));\n}\nfunction nodeData(field3) {\n return (node) => node.data?.[field3];\n}\nfunction normalizer(delimiter = \"/\") {\n delimiter = `${delimiter}`;\n if (delimiter === \"/\") return (P) => P;\n if (delimiter.length !== 1) throw new Error(\"delimiter must be exactly one character\");\n const delimiterCode = delimiter.charCodeAt(0);\n return (P) => P.map((p) => slashDelimiter(p, delimiterCode));\n}\nvar CODE_BACKSLASH = 92;\nvar CODE_SLASH = 47;\nfunction slashDelimiter(input3, delimiterCode) {\n if (delimiterCode === CODE_BACKSLASH) throw new Error(\"delimiter cannot be backslash\");\n let afterBackslash = false;\n for (let i = 0, n = input3.length; i < n; ++i) {\n switch (input3.charCodeAt(i)) {\n case CODE_BACKSLASH:\n if (!afterBackslash) {\n afterBackslash = true;\n continue;\n }\n break;\n case delimiterCode:\n if (afterBackslash) {\n input3 = input3.slice(0, i - 1) + input3.slice(i), --i, --n;\n } else {\n input3 = input3.slice(0, i) + \"/\" + input3.slice(i + 1);\n }\n break;\n case CODE_SLASH:\n if (afterBackslash) {\n input3 = input3.slice(0, i) + \"\\\\\\\\\" + input3.slice(i), i += 2, n += 2;\n } else {\n input3 = input3.slice(0, i) + \"\\\\\" + input3.slice(i), ++i, ++n;\n }\n break;\n }\n afterBackslash = false;\n }\n return input3;\n}\nfunction slashUnescape(input3) {\n let afterBackslash = false;\n for (let i = 0, n = input3.length; i < n; ++i) {\n switch (input3.charCodeAt(i)) {\n case CODE_BACKSLASH:\n if (!afterBackslash) {\n afterBackslash = true;\n continue;\n }\n // eslint-disable-next-line no-fallthrough\n case CODE_SLASH:\n if (afterBackslash) {\n input3 = input3.slice(0, i - 1) + input3.slice(i), --i, --n;\n }\n break;\n }\n afterBackslash = false;\n }\n return input3;\n}\nfunction isNodeValue(option) {\n return isObject(option) && typeof option.node === \"function\";\n}\nfunction isLinkValue(option) {\n return isObject(option) && typeof option.link === \"function\";\n}\nfunction maybeNodeValue(value) {\n if (isNodeValue(value)) return value.node;\n value = `${value}`.trim().toLowerCase();\n if (!value.startsWith(\"node:\")) return;\n switch (value) {\n case \"node:name\":\n return nodeName;\n case \"node:path\":\n return nodePath;\n case \"node:internal\":\n return nodeInternal;\n case \"node:external\":\n return nodeExternal;\n case \"node:depth\":\n return nodeDepth;\n case \"node:height\":\n return nodeHeight;\n }\n throw new Error(`invalid node value: ${value}`);\n}\nfunction maybeLinkValue(value) {\n if (isNodeValue(value)) return value.node;\n if (isLinkValue(value)) return value.link;\n value = `${value}`.trim().toLowerCase();\n if (!value.startsWith(\"node:\") && !value.startsWith(\"parent:\")) return;\n switch (value) {\n case \"parent:name\":\n return parentValue(nodeName);\n case \"parent:path\":\n return parentValue(nodePath);\n case \"parent:depth\":\n return parentValue(nodeDepth);\n case \"parent:height\":\n return parentValue(nodeHeight);\n case \"node:name\":\n return nodeName;\n case \"node:path\":\n return nodePath;\n case \"node:internal\":\n return nodeInternal;\n case \"node:external\":\n return nodeExternal;\n case \"node:depth\":\n return nodeDepth;\n case \"node:height\":\n return nodeHeight;\n }\n throw new Error(`invalid link value: ${value}`);\n}\nfunction nodePath(node) {\n return node.id;\n}\nfunction nodeName(node) {\n return nameof(node.id);\n}\nfunction nodeDepth(node) {\n return node.depth;\n}\nfunction nodeHeight(node) {\n return node.height;\n}\nfunction nodeInternal(node) {\n return !!node.children;\n}\nfunction nodeExternal(node) {\n return !node.children;\n}\nfunction parentValue(evaluate) {\n return (child, parent) => parent == null ? void 0 : evaluate(parent);\n}\nfunction nameof(path2) {\n let i = path2.length;\n while (--i > 0) if (slash2(path2, i)) break;\n return slashUnescape(path2.slice(i + 1));\n}\nfunction slash2(path2, i) {\n if (path2[i] === \"/\") {\n let k2 = 0;\n while (i > 0 && path2[--i] === \"\\\\\") ++k2;\n if ((k2 & 1) === 0) return true;\n }\n return false;\n}\nvar output_setValues = 2;\nvar output_evaluate = 3;\nvar output_values = 4;\nfunction treeOutputs(options, maybeTreeValue) {\n const outputs = [];\n for (const name2 in options) {\n const value = options[name2];\n const treeValue = maybeTreeValue(value);\n if (treeValue !== void 0) {\n outputs.push([name2, ...column2(value), treeValue]);\n }\n }\n return outputs;\n}\n\n// ../../node_modules/@observablehq/plot/src/marks/tree.js\nfunction tree(data, {\n fill,\n stroke,\n strokeWidth,\n strokeOpacity,\n strokeLinejoin,\n strokeLinecap,\n strokeMiterlimit,\n strokeDasharray,\n strokeDashoffset,\n marker,\n markerStart = marker,\n markerEnd = marker,\n dot: dotDot = isNoneish(markerStart) && isNoneish(markerEnd),\n text: textText = \"node:name\",\n textStroke = \"var(--plot-background)\",\n title = \"node:path\",\n dx,\n dy,\n textAnchor,\n treeLayout = tree_default,\n textLayout = treeLayout === tree_default || treeLayout === cluster_default ? \"mirrored\" : \"normal\",\n tip: tip2,\n ...options\n} = {}) {\n if (dx === void 0) dx = maybeTreeAnchor(options.treeAnchor).dx;\n if (textAnchor !== void 0) throw new Error(\"textAnchor is not a configurable tree option\");\n textLayout = keyword(textLayout, \"textLayout\", [\"mirrored\", \"normal\"]);\n function treeText(textOptions2) {\n return text(\n data,\n treeNode({\n treeLayout,\n text: textText,\n fill: fill === void 0 ? \"currentColor\" : fill,\n stroke: textStroke,\n dx,\n dy,\n title,\n ...textOptions2,\n ...options\n })\n );\n }\n return marks(\n link2(\n data,\n treeLink({\n treeLayout,\n markerStart,\n markerEnd,\n stroke: stroke !== void 0 ? stroke : fill === void 0 ? \"node:internal\" : fill,\n strokeWidth,\n strokeOpacity,\n strokeLinejoin,\n strokeLinecap,\n strokeMiterlimit,\n strokeDasharray,\n strokeDashoffset,\n ...options\n })\n ),\n dotDot ? dot(data, treeNode({ treeLayout, fill: fill === void 0 ? \"node:internal\" : fill, title, tip: tip2, ...options })) : null,\n textText != null ? textLayout === \"mirrored\" ? [\n treeText({ textAnchor: \"start\", treeFilter: \"node:external\" }),\n treeText({ textAnchor: \"end\", treeFilter: \"node:internal\", dx: -dx })\n ] : treeText() : null\n );\n}\nfunction cluster(data, options) {\n return tree(data, { ...options, treeLayout: cluster_default });\n}\n\n// ../../node_modules/@observablehq/plot/src/marks/waffle.js\nvar waffleDefaults = {\n ariaLabel: \"waffle\"\n};\nvar WaffleX = class extends BarX {\n constructor(data, { unit: unit3 = 1, gap = 1, round: round2, render, multiple, ...options } = {}) {\n super(data, { ...options, render: composeRender(render, waffleRender(\"x\")) }, waffleDefaults);\n this.unit = Math.max(0, unit3);\n this.gap = +gap;\n this.round = maybeRound2(round2);\n this.multiple = maybeMultiple(multiple);\n }\n};\nvar WaffleY = class extends BarY {\n constructor(data, { unit: unit3 = 1, gap = 1, round: round2, render, multiple, ...options } = {}) {\n super(data, { ...options, render: composeRender(render, waffleRender(\"y\")) }, waffleDefaults);\n this.unit = Math.max(0, unit3);\n this.gap = +gap;\n this.round = maybeRound2(round2);\n this.multiple = maybeMultiple(multiple);\n }\n};\nfunction waffleRender(y3) {\n return function(index2, scales2, values2, dimensions, context) {\n const { unit: unit3, gap, rx, ry, round: round2 } = this;\n const { document: document2 } = context;\n const Y13 = values2.channels[`${y3}1`].value;\n const Y23 = values2.channels[`${y3}2`].value;\n const barwidth = this[y3 === \"y\" ? \"_width\" : \"_height\"](scales2, values2, dimensions);\n const barx = this[y3 === \"y\" ? \"_x\" : \"_y\"](scales2, values2, dimensions);\n const scale3 = unit3 * scaleof(scales2.scales[y3]);\n const { multiple = Math.max(1, Math.floor(Math.sqrt(barwidth / scale3))) } = this;\n const cx = Math.min(barwidth / multiple, scale3 * multiple);\n const cy = scale3 * multiple;\n const transform3 = y3 === \"y\" ? ([x3, y4]) => [x3 * cx, -y4 * cy] : ([x3, y4]) => [y4 * cy, x3 * cx];\n const tx = (barwidth - multiple * cx) / 2;\n const x06 = typeof barx === \"function\" ? (i) => barx(i) + tx : barx + tx;\n const y06 = scales2[y3](0);\n const patternId = getPatternId();\n const basePattern = document2.createElementNS(namespaces_default.svg, \"pattern\");\n basePattern.setAttribute(\"width\", y3 === \"y\" ? cx : cy);\n basePattern.setAttribute(\"height\", y3 === \"y\" ? cy : cx);\n basePattern.setAttribute(\"patternUnits\", \"userSpaceOnUse\");\n const basePatternRect = basePattern.appendChild(document2.createElementNS(namespaces_default.svg, \"rect\"));\n basePatternRect.setAttribute(\"x\", gap / 2);\n basePatternRect.setAttribute(\"y\", gap / 2);\n basePatternRect.setAttribute(\"width\", (y3 === \"y\" ? cx : cy) - gap);\n basePatternRect.setAttribute(\"height\", (y3 === \"y\" ? cy : cx) - gap);\n if (rx != null) basePatternRect.setAttribute(\"rx\", rx);\n if (ry != null) basePatternRect.setAttribute(\"ry\", ry);\n return create4(\"svg:g\", context).call(applyIndirectStyles, this, dimensions, context).call(this._transform, this, scales2).call(\n (g) => g.selectAll().data(index2).enter().append(() => basePattern.cloneNode(true)).attr(\"id\", (i) => `${patternId}-${i}`).select(\"rect\").call(applyDirectStyles, this).call(applyChannelStyles, this, values2)\n ).call(\n (g) => g.selectAll().data(index2).enter().append(\"path\").attr(\"transform\", y3 === \"y\" ? template`translate(${x06},${y06})` : template`translate(${y06},${x06})`).attr(\n \"d\",\n (i) => `M${wafflePoints(round2(Y13[i] / unit3), round2(Y23[i] / unit3), multiple).map(transform3).join(\"L\")}Z`\n ).attr(\"fill\", (i) => `url(#${patternId}-${i})`).attr(\"stroke\", this.stroke == null ? null : (i) => `url(#${patternId}-${i})`)\n ).node();\n };\n}\nfunction wafflePoints(i1, i2, columns) {\n if (i1 < 0 || i2 < 0) {\n const k2 = Math.ceil(-Math.min(i1, i2) / columns);\n return wafflePoints(i1 + k2 * columns, i2 + k2 * columns, columns).map(([x3, y3]) => [x3, y3 - k2]);\n }\n if (i2 < i1) {\n return wafflePoints(i2, i1, columns);\n }\n return [\n [0, Math.ceil(i1 / columns)],\n [Math.floor(i1 % columns), Math.ceil(i1 / columns)],\n [Math.floor(i1 % columns), Math.floor(i1 / columns) + i1 % 1],\n [Math.ceil(i1 % columns), Math.floor(i1 / columns) + i1 % 1],\n ...i1 % columns > columns - 1 ? [] : [\n [Math.ceil(i1 % columns), Math.floor(i1 / columns)],\n [columns, Math.floor(i1 / columns)]\n ],\n [columns, Math.floor(i2 / columns)],\n [Math.ceil(i2 % columns), Math.floor(i2 / columns)],\n [Math.ceil(i2 % columns), Math.floor(i2 / columns) + i2 % 1],\n [Math.floor(i2 % columns), Math.floor(i2 / columns) + i2 % 1],\n ...i2 % columns < 1 ? [] : [\n [Math.floor(i2 % columns), Math.ceil(i2 / columns)],\n [0, Math.ceil(i2 / columns)]\n ]\n ];\n}\nfunction maybeRound2(round2) {\n if (round2 === void 0 || round2 === false) return Number;\n if (round2 === true) return Math.round;\n if (typeof round2 !== \"function\") throw new Error(`invalid round: ${round2}`);\n return round2;\n}\nfunction maybeMultiple(multiple) {\n return multiple === void 0 ? void 0 : Math.max(1, Math.floor(multiple));\n}\nfunction scaleof({ domain, range: range3 }) {\n return spread(range3) / spread(domain);\n}\nfunction spread(domain) {\n const [min5, max4] = extent(domain);\n return max4 - min5;\n}\nfunction waffleX(data, options = {}) {\n if (!hasXY(options)) options = { ...options, y: indexOf, x2: identity7 };\n return new WaffleX(data, maybeStackX(maybeIntervalX(maybeIdentityX(options))));\n}\nfunction waffleY(data, options = {}) {\n if (!hasXY(options)) options = { ...options, x: indexOf, y2: identity7 };\n return new WaffleY(data, maybeStackY(maybeIntervalY(maybeIdentityY(options))));\n}\n\n// ../../node_modules/@observablehq/plot/src/transforms/dodge.js\nvar import_interval_tree_1d = __toESM(require_interval_tree(), 1);\nvar anchorXLeft = ({ marginLeft: marginLeft2 }) => [1, marginLeft2];\nvar anchorXRight = ({ width: width2, marginRight: marginRight2 }) => [-1, width2 - marginRight2];\nvar anchorXMiddle = ({ width: width2, marginLeft: marginLeft2, marginRight: marginRight2 }) => [0, (marginLeft2 + width2 - marginRight2) / 2];\nvar anchorYTop = ({ marginTop: marginTop2 }) => [1, marginTop2];\nvar anchorYBottom = ({ height: height2, marginBottom: marginBottom2 }) => [-1, height2 - marginBottom2];\nvar anchorYMiddle = ({ height: height2, marginTop: marginTop2, marginBottom: marginBottom2 }) => [0, (marginTop2 + height2 - marginBottom2) / 2];\nfunction maybeAnchor4(anchor) {\n return typeof anchor === \"string\" ? { anchor } : anchor;\n}\nfunction dodgeX(dodgeOptions = {}, options = {}) {\n if (arguments.length === 1) [dodgeOptions, options] = mergeOptions3(dodgeOptions);\n let { anchor = \"left\", padding: padding2 = 1, r = options.r } = maybeAnchor4(dodgeOptions);\n switch (`${anchor}`.toLowerCase()) {\n case \"left\":\n anchor = anchorXLeft;\n break;\n case \"right\":\n anchor = anchorXRight;\n break;\n case \"middle\":\n anchor = anchorXMiddle;\n break;\n default:\n throw new Error(`unknown dodge anchor: ${anchor}`);\n }\n return dodge(\"x\", \"y\", anchor, number5(padding2), r, options);\n}\nfunction dodgeY(dodgeOptions = {}, options = {}) {\n if (arguments.length === 1) [dodgeOptions, options] = mergeOptions3(dodgeOptions);\n let { anchor = \"bottom\", padding: padding2 = 1, r = options.r } = maybeAnchor4(dodgeOptions);\n switch (`${anchor}`.toLowerCase()) {\n case \"top\":\n anchor = anchorYTop;\n break;\n case \"bottom\":\n anchor = anchorYBottom;\n break;\n case \"middle\":\n anchor = anchorYMiddle;\n break;\n default:\n throw new Error(`unknown dodge anchor: ${anchor}`);\n }\n return dodge(\"y\", \"x\", anchor, number5(padding2), r, options);\n}\nfunction mergeOptions3(options) {\n const { anchor, padding: padding2, ...rest } = options;\n const { r } = rest;\n return [{ anchor, padding: padding2, r }, rest];\n}\nfunction dodge(y3, x3, anchor, padding2, r, options) {\n if (r != null && typeof r !== \"number\") {\n let { channels, sort: sort3, reverse: reverse3 } = options;\n channels = maybeNamed(channels);\n if (channels?.r === void 0) options = { ...options, channels: { ...channels, r: { value: r, scale: \"r\" } } };\n if (sort3 === void 0 && reverse3 === void 0) options.sort = { channel: \"-r\" };\n }\n return initializer(options, function(data, facets, channels, scales2, dimensions, context) {\n let { [x3]: X3, r: R } = channels;\n if (!channels[x3]) throw new Error(`missing channel: ${x3}`);\n ({ [x3]: X3 } = applyPosition(channels, scales2, context));\n const cr = R ? void 0 : r !== void 0 ? number5(r) : this.r !== void 0 ? this.r : 3;\n if (R) R = valueof(R.value, scales2[R.scale] || identity7, Float64Array);\n let [ky2, ty] = anchor(dimensions);\n const compare = ky2 ? compareAscending : compareSymmetric;\n const Y3 = new Float64Array(X3.length);\n const radius2 = R ? (i) => R[i] : () => cr;\n for (let I of facets) {\n const tree2 = (0, import_interval_tree_1d.default)();\n I = I.filter(R ? (i) => finite2(X3[i]) && positive(R[i]) : (i) => finite2(X3[i]));\n const intervals2 = new Float64Array(2 * I.length + 2);\n for (const i of I) {\n const ri = radius2(i);\n const y06 = ky2 ? ri + padding2 : 0;\n const l = X3[i] - ri;\n const h = X3[i] + ri;\n let k2 = 2;\n tree2.queryInterval(l - padding2, h + padding2, ([, , j]) => {\n const yj = Y3[j] - y06;\n const dx = X3[i] - X3[j];\n const dr = padding2 + (R ? R[i] + R[j] : 2 * cr);\n const dy = Math.sqrt(dr * dr - dx * dx);\n intervals2[k2++] = yj - dy;\n intervals2[k2++] = yj + dy;\n });\n let candidates = intervals2.slice(0, k2);\n if (ky2) candidates = candidates.filter((y4) => y4 >= 0);\n out: for (const y4 of candidates.sort(compare)) {\n for (let j = 0; j < k2; j += 2) {\n if (intervals2[j] + 1e-6 < y4 && y4 < intervals2[j + 1] - 1e-6) {\n continue out;\n }\n }\n Y3[i] = y4 + y06;\n break;\n }\n tree2.insert([l, h, i]);\n }\n }\n if (!ky2) ky2 = 1;\n for (const I of facets) {\n for (const i of I) {\n Y3[i] = Y3[i] * ky2 + ty;\n }\n }\n return {\n data,\n facets,\n channels: {\n [y3]: { value: Y3, source: null },\n // don’t show in tooltip\n [x3]: { value: X3, source: channels[x3] },\n ...R && { r: { value: R, source: channels.r } }\n }\n };\n });\n}\nfunction compareSymmetric(a2, b) {\n return Math.abs(a2) - Math.abs(b);\n}\nfunction compareAscending(a2, b) {\n return a2 - b;\n}\n\n// ../../node_modules/@observablehq/plot/src/transforms/normalize.js\nfunction normalizeX(basis2, options) {\n if (arguments.length === 1) ({ basis: basis2, ...options } = basis2);\n return mapX(normalize3(basis2), options);\n}\nfunction normalizeY(basis2, options) {\n if (arguments.length === 1) ({ basis: basis2, ...options } = basis2);\n return mapY(normalize3(basis2), options);\n}\nfunction normalize3(basis2) {\n if (basis2 === void 0) return normalizeFirst;\n if (typeof basis2 === \"function\") return normalizeBasis(taker(basis2));\n if (/^p\\d{2}$/i.test(basis2)) return normalizeAccessor(percentile(basis2));\n switch (`${basis2}`.toLowerCase()) {\n case \"deviation\":\n return normalizeDeviation;\n case \"first\":\n return normalizeFirst;\n case \"last\":\n return normalizeLast;\n case \"max\":\n return normalizeMax;\n case \"mean\":\n return normalizeMean;\n case \"median\":\n return normalizeMedian;\n case \"min\":\n return normalizeMin;\n case \"sum\":\n return normalizeSum;\n case \"extent\":\n return normalizeExtent;\n }\n throw new Error(`invalid basis: ${basis2}`);\n}\nfunction normalizeBasis(basis2) {\n return {\n mapIndex(I, S, T) {\n const b = +basis2(I, S);\n for (const i of I) {\n T[i] = S[i] === null ? NaN : S[i] / b;\n }\n }\n };\n}\nfunction normalizeAccessor(f) {\n return normalizeBasis((I, S) => f(I, (i) => S[i]));\n}\nvar normalizeExtent = {\n mapIndex(I, S, T) {\n const [s1, s2] = extent(I, (i) => S[i]);\n const d = s2 - s1;\n for (const i of I) {\n T[i] = S[i] === null ? NaN : (S[i] - s1) / d;\n }\n }\n};\nvar normalizeFirst = normalizeBasis((I, S) => {\n for (let i = 0; i < I.length; ++i) {\n const s2 = S[I[i]];\n if (defined(s2)) return s2;\n }\n});\nvar normalizeLast = normalizeBasis((I, S) => {\n for (let i = I.length - 1; i >= 0; --i) {\n const s2 = S[I[i]];\n if (defined(s2)) return s2;\n }\n});\nvar normalizeDeviation = {\n mapIndex(I, S, T) {\n const m = mean2(I, (i) => S[i]);\n const d = deviation(I, (i) => S[i]);\n for (const i of I) {\n T[i] = S[i] === null ? NaN : d ? (S[i] - m) / d : 0;\n }\n }\n};\nvar normalizeMax = normalizeAccessor(max2);\nvar normalizeMean = normalizeAccessor(mean2);\nvar normalizeMedian = normalizeAccessor(median2);\nvar normalizeMin = normalizeAccessor(min2);\nvar normalizeSum = normalizeAccessor(sum2);\n\n// ../../node_modules/@observablehq/plot/src/transforms/shift.js\nfunction shiftX(interval3, options) {\n return shiftK(\"x\", interval3, options);\n}\nfunction shiftY(interval3, options) {\n return shiftK(\"y\", interval3, options);\n}\nfunction shiftK(x3, interval3, options = {}) {\n let offset2;\n let k2 = 1;\n if (typeof interval3 === \"number\") {\n k2 = interval3;\n offset2 = (x4, k3) => +x4 + k3;\n } else {\n if (typeof interval3 === \"string\") {\n const sign3 = interval3.startsWith(\"-\") ? -1 : 1;\n [interval3, k2] = parseTimeInterval(interval3.replace(/^[+-]/, \"\"));\n k2 *= sign3;\n }\n interval3 = maybeInterval(interval3);\n offset2 = (x4, k3) => interval3.offset(x4, k3);\n }\n const x12 = `${x3}1`;\n const x22 = `${x3}2`;\n const mapped = map4(\n {\n [x12]: (D3) => D3.map((d) => offset2(d, k2)),\n [x22]: (D3) => D3\n },\n options\n );\n const t = mapped[x22].transform;\n mapped[x22].transform = () => {\n const V = t();\n const [x06, x13] = extent(V);\n V.domain = k2 < 0 ? [x06, offset2(x13, k2)] : [offset2(x06, k2), x13];\n return V;\n };\n return mapped;\n}\n\n// ../../node_modules/@observablehq/plot/src/transforms/select.js\nfunction select(selector, options = {}) {\n if (typeof selector === \"string\") {\n switch (selector.toLowerCase()) {\n case \"first\":\n return selectFirst(options);\n case \"last\":\n return selectLast(options);\n }\n }\n if (typeof selector === \"function\") {\n return selectChannel(null, selector, options);\n }\n let key, value;\n for (key in selector) {\n if (value !== void 0) throw new Error(\"ambiguous selector; multiple inputs\");\n value = maybeSelector(selector[key]);\n }\n if (value === void 0) throw new Error(`invalid selector: ${selector}`);\n return selectChannel(key, value, options);\n}\nfunction maybeSelector(selector) {\n if (typeof selector === \"function\") return selector;\n switch (`${selector}`.toLowerCase()) {\n case \"min\":\n return selectorMin;\n case \"max\":\n return selectorMax;\n }\n throw new Error(`unknown selector: ${selector}`);\n}\nfunction selectFirst(options) {\n return selectChannel(null, selectorFirst, options);\n}\nfunction selectLast(options) {\n return selectChannel(null, selectorLast, options);\n}\nfunction selectMinX(options) {\n return selectChannel(\"x\", selectorMin, options);\n}\nfunction selectMinY(options) {\n return selectChannel(\"y\", selectorMin, options);\n}\nfunction selectMaxX(options) {\n return selectChannel(\"x\", selectorMax, options);\n}\nfunction selectMaxY(options) {\n return selectChannel(\"y\", selectorMax, options);\n}\nfunction* selectorFirst(I) {\n yield I[0];\n}\nfunction* selectorLast(I) {\n yield I[I.length - 1];\n}\nfunction* selectorMin(I, X3) {\n yield least(I, (i) => X3[i]);\n}\nfunction* selectorMax(I, X3) {\n yield greatest(I, (i) => X3[i]);\n}\nfunction selectChannel(v2, selector, options) {\n if (v2 != null) {\n if (options[v2] == null) throw new Error(`missing channel: ${v2}`);\n v2 = options[v2];\n }\n const z = maybeZ(options);\n return basic(options, (data, facets) => {\n const Z = valueof(data, z);\n const V = valueof(data, v2);\n const selectFacets = [];\n for (const facet of facets) {\n const selectFacet = [];\n for (const I of Z ? group(facet, (i) => Z[i]).values() : [facet]) {\n for (const i of selector(I, V)) {\n selectFacet.push(i);\n }\n }\n selectFacets.push(selectFacet);\n }\n return { data, facets: selectFacets };\n });\n}\n\n// ../../node_modules/@observablehq/plot/src/index.js\nMark.prototype.plot = function({ marks: marks2 = [], ...options } = {}) {\n return plot({ ...options, marks: [...marks2, this] });\n};\n\n// ../plot/src/plot-attributes.js\nvar attributeMap = /* @__PURE__ */ new Map([\n [\"style\", \"style\"],\n [\"width\", \"width\"],\n [\"height\", \"height\"],\n [\"margin\", \"margin\"],\n [\"marginLeft\", \"marginLeft\"],\n [\"marginRight\", \"marginRight\"],\n [\"marginTop\", \"marginTop\"],\n [\"marginBottom\", \"marginBottom\"],\n [\"align\", \"align\"],\n [\"aspectRatio\", \"aspectRatio\"],\n [\"axis\", \"axis\"],\n [\"inset\", \"inset\"],\n [\"grid\", \"grid\"],\n [\"label\", \"label\"],\n [\"padding\", \"padding\"],\n [\"xScale\", \"x.type\"],\n [\"xDomain\", \"x.domain\"],\n [\"xRange\", \"x.range\"],\n [\"xNice\", \"x.nice\"],\n [\"xInset\", \"x.inset\"],\n [\"xInsetLeft\", \"x.insetLeft\"],\n [\"xInsetRight\", \"x.insetRight\"],\n [\"xClamp\", \"x.clamp\"],\n [\"xRound\", \"x.round\"],\n [\"xAlign\", \"x.align\"],\n [\"xPadding\", \"x.padding\"],\n [\"xPaddingInner\", \"x.paddingInner\"],\n [\"xPaddingOuter\", \"x.paddingOuter\"],\n [\"xAxis\", \"x.axis\"],\n [\"xTicks\", \"x.ticks\"],\n [\"xTickSize\", \"x.tickSize\"],\n [\"xTickSpacing\", \"x.tickSpacing\"],\n [\"xTickPadding\", \"x.tickPadding\"],\n [\"xTickFormat\", \"x.tickFormat\"],\n [\"xTickRotate\", \"x.tickRotate\"],\n [\"xGrid\", \"x.grid\"],\n [\"xLine\", \"x.line\"],\n [\"xLabel\", \"x.label\"],\n [\"xLabelAnchor\", \"x.labelAnchor\"],\n [\"xLabelArrow\", \"x.labelArrow\"],\n [\"xLabelOffset\", \"x.labelOffset\"],\n [\"xFontVariant\", \"x.fontVariant\"],\n [\"xAriaLabel\", \"x.ariaLabel\"],\n [\"xAriaDescription\", \"x.ariaDescription\"],\n [\"xPercent\", \"x.percent\"],\n [\"xReverse\", \"x.reverse\"],\n [\"xZero\", \"x.zero\"],\n [\"xBase\", \"x.base\"],\n [\"xExponent\", \"x.exponent\"],\n [\"xConstant\", \"x.constant\"],\n [\"yScale\", \"y.type\"],\n [\"yDomain\", \"y.domain\"],\n [\"yRange\", \"y.range\"],\n [\"yNice\", \"y.nice\"],\n [\"yInset\", \"y.inset\"],\n [\"yInsetTop\", \"y.insetTop\"],\n [\"yInsetBottom\", \"y.insetBottom\"],\n [\"yClamp\", \"y.clamp\"],\n [\"yRound\", \"y.round\"],\n [\"yAlign\", \"y.align\"],\n [\"yPadding\", \"y.padding\"],\n [\"yPaddingInner\", \"y.paddingInner\"],\n [\"yPaddingOuter\", \"y.paddingOuter\"],\n [\"yAxis\", \"y.axis\"],\n [\"yTicks\", \"y.ticks\"],\n [\"yTickSize\", \"y.tickSize\"],\n [\"yTickSpacing\", \"y.tickSpacing\"],\n [\"yTickPadding\", \"y.tickPadding\"],\n [\"yTickFormat\", \"y.tickFormat\"],\n [\"yTickRotate\", \"y.tickRotate\"],\n [\"yGrid\", \"y.grid\"],\n [\"yLine\", \"y.line\"],\n [\"yLabel\", \"y.label\"],\n [\"yLabelAnchor\", \"y.labelAnchor\"],\n [\"yLabelArrow\", \"y.labelArrow\"],\n [\"yLabelOffset\", \"y.labelOffset\"],\n [\"yFontVariant\", \"y.fontVariant\"],\n [\"yAriaLabel\", \"y.ariaLabel\"],\n [\"yAriaDescription\", \"y.ariaDescription\"],\n [\"yPercent\", \"y.percent\"],\n [\"yReverse\", \"y.reverse\"],\n [\"yZero\", \"y.zero\"],\n [\"yBase\", \"y.base\"],\n [\"yExponent\", \"y.exponent\"],\n [\"yConstant\", \"y.constant\"],\n [\"facetMargin\", \"facet.margin\"],\n [\"facetMarginTop\", \"facet.marginTop\"],\n [\"facetMarginBottom\", \"facet.marginBottom\"],\n [\"facetMarginLeft\", \"facet.marginLeft\"],\n [\"facetMarginRight\", \"facet.marginRight\"],\n [\"facetGrid\", \"facet.grid\"],\n [\"facetLabel\", \"facet.label\"],\n [\"fxDomain\", \"fx.domain\"],\n [\"fxRange\", \"fx.range\"],\n [\"fxInset\", \"fx.inset\"],\n [\"fxInsetLeft\", \"fx.insetLeft\"],\n [\"fxInsetRight\", \"fx.insetRight\"],\n [\"fxRound\", \"fx.round\"],\n [\"fxAlign\", \"fx.align\"],\n [\"fxPadding\", \"fx.padding\"],\n [\"fxPaddingInner\", \"fx.paddingInner\"],\n [\"fxPaddingOuter\", \"fx.paddingOuter\"],\n [\"fxAxis\", \"fx.axis\"],\n [\"fxTicks\", \"fx.ticks\"],\n [\"fxTickSize\", \"fx.tickSize\"],\n [\"fxTickSpacing\", \"fx.tickSpacing\"],\n [\"fxTickPadding\", \"fx.tickPadding\"],\n [\"fxTickFormat\", \"fx.tickFormat\"],\n [\"fxTickRotate\", \"fx.tickRotate\"],\n [\"fxGrid\", \"fx.grid\"],\n [\"fxLine\", \"fx.line\"],\n [\"fxLabel\", \"fx.label\"],\n [\"fxLabelAnchor\", \"fx.labelAnchor\"],\n [\"fxLabelOffset\", \"fx.labelOffset\"],\n [\"fxFontVariant\", \"fx.fontVariant\"],\n [\"fxAriaLabel\", \"fx.ariaLabel\"],\n [\"fxAriaDescription\", \"fx.ariaDescription\"],\n [\"fxReverse\", \"fx.reverse\"],\n [\"fyDomain\", \"fy.domain\"],\n [\"fyRange\", \"fy.range\"],\n [\"fyInset\", \"fy,inset\"],\n [\"fyInsetTop\", \"fy.insetTop\"],\n [\"fyInsetBottom\", \"fy.insetBottom\"],\n [\"fyRound\", \"fy.round\"],\n [\"fyAlign\", \"fy.align\"],\n [\"fyPadding\", \"fy.padding\"],\n [\"fyPaddingInner\", \"fy.paddingInner\"],\n [\"fyPaddingOuter\", \"fy.paddingOuter\"],\n [\"fyAxis\", \"fy.axis\"],\n [\"fyTicks\", \"fy.ticks\"],\n [\"fyTickSize\", \"fy.tickSize\"],\n [\"fyTickSpacing\", \"fy.tickSpacing\"],\n [\"fyTickPadding\", \"fy.tickPadding\"],\n [\"fyTickFormat\", \"fy.tickFormat\"],\n [\"fyTickRotate\", \"fy.tickRotate\"],\n [\"fyGrid\", \"fy.grid\"],\n [\"fyLine\", \"fy.line\"],\n [\"fyLabel\", \"fy.label\"],\n [\"fyLabelAnchor\", \"fy.labelAnchor\"],\n [\"fyLabelOffset\", \"fy.labelOffset\"],\n [\"fyFontVariant\", \"fy.fontVariant\"],\n [\"fyAriaLabel\", \"fy.ariaLabel\"],\n [\"fyAriaDescription\", \"fy.ariaDescription\"],\n [\"fyReverse\", \"fy.reverse\"],\n [\"colorScale\", \"color.type\"],\n [\"colorDomain\", \"color.domain\"],\n [\"colorRange\", \"color.range\"],\n [\"colorClamp\", \"color.clamp\"],\n [\"colorN\", \"color.n\"],\n [\"colorNice\", \"color.nice\"],\n [\"colorScheme\", \"color.scheme\"],\n [\"colorInterpolate\", \"color.interpolate\"],\n [\"colorPivot\", \"color.pivot\"],\n [\"colorSymmetric\", \"color.symmetric\"],\n [\"colorLabel\", \"color.label\"],\n [\"colorPercent\", \"color.percent\"],\n [\"colorReverse\", \"color.reverse\"],\n [\"colorZero\", \"color.zero\"],\n [\"colorTickFormat\", \"color.tickFormat\"],\n [\"colorBase\", \"color.base\"],\n [\"colorExponent\", \"color.exponent\"],\n [\"colorConstant\", \"color.constant\"],\n [\"opacityScale\", \"opacity.type\"],\n [\"opacityDomain\", \"opacity.domain\"],\n [\"opacityRange\", \"opacity.range\"],\n [\"opacityClamp\", \"opacity.clamp\"],\n [\"opacityNice\", \"opacity.nice\"],\n [\"opacityLabel\", \"opacity.label\"],\n [\"opacityPercent\", \"opacity.percent\"],\n [\"opacityReverse\", \"opacity.reverse\"],\n [\"opacityZero\", \"opacity.zero\"],\n [\"opacityTickFormat\", \"opacity.tickFormat\"],\n [\"opacityBase\", \"opacity.base\"],\n [\"opacityExponent\", \"opacity.exponent\"],\n [\"opacityConstant\", \"opacity.constant\"],\n [\"symbolScale\", \"symbol.type\"],\n [\"symbolDomain\", \"symbol.domain\"],\n [\"symbolRange\", \"symbol.range\"],\n [\"rScale\", \"r.type\"],\n [\"rDomain\", \"r.domain\"],\n [\"rRange\", \"r.range\"],\n [\"rClamp\", \"r.clamp\"],\n [\"rNice\", \"r.nice\"],\n [\"rLabel\", \"r.label\"],\n [\"rPercent\", \"r.percent\"],\n [\"rZero\", \"r.zero\"],\n [\"rBase\", \"r.base\"],\n [\"rExponent\", \"r.exponent\"],\n [\"rConstant\", \"r.constant\"],\n [\"lengthScale\", \"length.type\"],\n [\"lengthDomain\", \"length.domain\"],\n [\"lengthRange\", \"length.range\"],\n [\"lengthClamp\", \"length.clamp\"],\n [\"lengthNice\", \"length.nice\"],\n [\"lengthPercent\", \"length.percent\"],\n [\"lengthZero\", \"length.zero\"],\n [\"lengthBase\", \"length.base\"],\n [\"lengthExponent\", \"length.exponent\"],\n [\"lengthConstant\", \"length.constant\"],\n [\"projectionType\", \"projection.type\"],\n [\"projectionParallels\", \"projection.parallels\"],\n [\"projectionPrecision\", \"projection.precision\"],\n [\"projectionRotate\", \"projection.rotate\"],\n [\"projectionDomain\", \"projection.domain\"],\n [\"projectionInset\", \"projection.inset\"],\n [\"projectionInsetLeft\", \"projection.insetLeft\"],\n [\"projectionInsetRight\", \"projection.insetRight\"],\n [\"projectionInsetTop\", \"projection.insetTop\"],\n [\"projectionInsetBottom\", \"projection.insetBottom\"],\n [\"projectionClip\", \"projection.clip\"]\n]);\nfunction setProperty(object, path2, value) {\n for (let i = 0; i < path2.length; ++i) {\n const key = path2[i];\n if (i === path2.length - 1) {\n object[key] = value;\n } else {\n object = object[key] || (object[key] = {});\n }\n }\n}\nfunction setAttributes(attributes2, spec, symbols3) {\n for (const key in attributes2) {\n const specKey = attributeMap.get(key);\n if (specKey == null) {\n throw new Error(`Unrecognized plot attribute: ${key}`);\n }\n const value = attributes2[key];\n if (typeof value === \"symbol\") {\n symbols3.push(key);\n } else if (value !== void 0) {\n setProperty(spec, specKey.split(\".\"), value);\n }\n }\n}\n\n// ../plot/src/plot-renderer.js\nvar OPTIONS_ONLY_MARKS = /* @__PURE__ */ new Set([\n \"frame\",\n \"hexgrid\",\n \"sphere\",\n \"graticule\"\n]);\nvar SELECT_TRANSFORMS = /* @__PURE__ */ new Map([\n [\"first\", selectFirst],\n [\"last\", selectLast],\n [\"maxX\", selectMaxX],\n [\"maxY\", selectMaxY],\n [\"minX\", selectMinX],\n [\"minY\", selectMinY],\n [\"nearest\", pointer],\n [\"nearestX\", pointerX],\n [\"nearestXY\", pointerY]\n]);\nasync function plotRenderer(plot3) {\n const spec = { marks: [] };\n const symbols3 = [];\n const { attributes: attributes2, marks: marks2 } = plot3;\n setAttributes(attributes2, spec, symbols3);\n const indices2 = [];\n for (const mark2 of marks2) {\n for (const { type: type2, data, options } of mark2.plotSpecs()) {\n const { select: select2, ...rest } = options;\n const opt = SELECT_TRANSFORMS.get(select2)?.(rest) ?? rest;\n const arg = OPTIONS_ONLY_MARKS.has(type2) ? [opt] : [data, opt];\n spec.marks.push(src_exports[type2](...arg));\n indices2.push(mark2.index);\n }\n }\n inferLabels(spec, plot3);\n const svg = plot(spec);\n annotatePlot(svg, indices2);\n setSymbolAttributes(plot3, svg, attributes2, symbols3);\n for (const interactor2 of plot3.interactors) {\n await interactor2.init(svg);\n }\n return svg;\n}\nfunction setSymbolAttributes(plot3, svg, attributes2, symbols3) {\n symbols3.forEach((key) => {\n const value = attributes2[key];\n if (value === Fixed) {\n if (!key.endsWith(\"Domain\")) {\n throw new Error(`Unsupported fixed attribute: ${key}`);\n }\n const type2 = key.slice(0, -\"Domain\".length);\n const scale3 = svg.scale(type2);\n if (scale3?.domain) {\n plot3.setAttribute(key, attributes2[`${type2}Reverse`] ? scale3.domain.slice().reverse() : scale3.domain);\n }\n } else {\n throw new Error(`Unrecognized symbol: ${value}`);\n }\n });\n}\nfunction inferLabels(spec, plot3) {\n const { marks: marks2 } = plot3;\n inferLabel(\"x\", spec, marks2);\n inferLabel(\"y\", spec, marks2);\n inferLabel(\"fx\", spec, marks2);\n inferLabel(\"fy\", spec, marks2);\n}\nfunction inferLabel(key, spec, marks2) {\n const scale3 = spec[key] || {};\n if (scale3.axis === null || scale3.label !== void 0) return;\n const fields = marks2.map((mark2) => mark2.channelField(key)?.field);\n if (fields.every((x3) => x3 == null)) return;\n let candCol;\n let candLabel;\n let type2;\n for (let i = 0; i < fields.length; ++i) {\n const { column: column3, label: label2 } = fields[i] || {};\n if (column3 === void 0 && label2 === void 0) {\n continue;\n } else if (candCol === void 0 && candLabel === void 0) {\n candCol = column3;\n candLabel = label2;\n type2 = getType(marks2[i].data, key) || \"number\";\n } else if (candLabel !== label2) {\n candLabel = void 0;\n } else if (candCol !== column3) {\n candCol = void 0;\n }\n }\n let candidate = candLabel || candCol;\n if (candidate === void 0) return;\n if ((type2 === \"number\" || type2 === \"date\") && (key === \"x\" || key === \"y\")) {\n if (scale3.percent) candidate = `${candidate} (%)`;\n const order = (key === \"x\" ? 1 : -1) * (scale3.reverse ? -1 : 1);\n if (key === \"x\" || scale3.labelAnchor === \"center\") {\n candidate = key === \"x\" === order < 0 ? `\\u2190 ${candidate}` : `${candidate} \\u2192`;\n } else {\n candidate = `${order < 0 ? \"\\u2191 \" : \"\\u2193 \"}${candidate}`;\n }\n }\n spec[key] = { ...scale3, label: candidate };\n}\nfunction annotatePlot(svg, indices2) {\n const facets = svg.querySelectorAll('g[aria-label=\"facet\"]');\n if (facets.length) {\n for (const facet of facets) {\n annotateMarks(facet, indices2);\n }\n } else {\n annotateMarks(svg, indices2);\n }\n}\nfunction annotateMarks(svg, indices2) {\n let index2 = -1;\n for (const child of svg.children) {\n const aria = child.getAttribute(\"aria-label\") || \"\";\n const skip = child.nodeName === \"style\" || aria.includes(\"-axis\") || aria.includes(\"-grid\");\n if (!skip) {\n child.setAttribute(\"data-index\", indices2[++index2]);\n }\n }\n}\nfunction getType(data, channel) {\n if (!data) return;\n const { columns } = data;\n const col = columns[channel] ?? columns[channel + \"1\"] ?? columns[channel + \"2\"];\n if (col) {\n for (const v2 of col) {\n if (v2 != null) {\n return v2 instanceof Date ? \"date\" : typeof v2;\n }\n }\n }\n}\n\n// ../plot/src/plot.js\nvar DEFAULT_ATTRIBUTES = {\n width: 640,\n marginLeft: 40,\n marginRight: 20,\n marginTop: 20,\n marginBottom: 30\n};\nvar Plot = class {\n constructor(element) {\n this.attributes = { ...DEFAULT_ATTRIBUTES };\n this.listeners = null;\n this.interactors = [];\n this.legends = [];\n this.marks = [];\n this.markset = null;\n this.element = element || document.createElement(\"div\");\n this.element.setAttribute(\"class\", \"plot\");\n this.element.style.display = \"flex\";\n this.element.value = this;\n this.params = /* @__PURE__ */ new Map();\n this.synch = synchronizer();\n }\n margins() {\n return {\n left: this.getAttribute(\"marginLeft\"),\n top: this.getAttribute(\"marginTop\"),\n bottom: this.getAttribute(\"marginBottom\"),\n right: this.getAttribute(\"marginRight\")\n };\n }\n innerWidth() {\n const { left: left2, right: right2 } = this.margins();\n return this.getAttribute(\"width\") - left2 - right2;\n }\n innerHeight(defaultValue = 400) {\n const { top: top2, bottom: bottom2 } = this.margins();\n let h = this.getAttribute(\"height\");\n if (h == null) {\n h = maybeAspectRatio(this, top2, bottom2) || defaultValue;\n this.setAttribute(\"height\", h, { silent: true });\n }\n return h - top2 - bottom2;\n }\n pending(mark2) {\n this.synch.pending(mark2);\n }\n update(mark2) {\n if (this.synch.ready(mark2) && !this.pendingRender) {\n this.pendingRender = true;\n requestAnimationFrame(() => this.render());\n }\n return this.synch.promise;\n }\n async render() {\n this.pendingRender = false;\n const svg = await plotRenderer(this);\n const legends = this.legends.flatMap(({ legend: legend3, include }) => {\n const el = legend3.init(svg);\n return include ? el : [];\n });\n this.element.replaceChildren(svg, ...legends);\n this.synch.resolve();\n }\n /**\n * @param {string} name The attribute to return.\n * @returns {*} The value of the attribute.\n */\n getAttribute(name2) {\n return this.attributes[name2];\n }\n /**\n * @param {string} name The name of the attribute to set.\n * @param {*} value The value to set.\n * @param {{silent: boolean}} [options] Options for setting the attribute.\n * @returns {boolean} whether the value changed.\n */\n setAttribute(name2, value, options) {\n if (distinct(this.attributes[name2], value)) {\n if (value === void 0) {\n delete this.attributes[name2];\n } else {\n this.attributes[name2] = value;\n }\n if (!options?.silent) {\n this.listeners?.get(name2)?.forEach((cb) => cb(name2, value));\n }\n return true;\n }\n return false;\n }\n /**\n * @param {string} name The attribute name.\n * @param {*} callback The function to call when the attribute changes.\n * @returns {this}\n */\n addAttributeListener(name2, callback) {\n const map5 = this.listeners || (this.listeners = /* @__PURE__ */ new Map());\n if (!map5.has(name2)) map5.set(name2, /* @__PURE__ */ new Set());\n map5.get(name2).add(callback);\n return this;\n }\n /**\n * @param {string} name The attribute name.\n * @param {*} callback The function to call when the attribute changes.\n * @returns {void}\n */\n removeAttributeListener(name2, callback) {\n return this.listeners?.get(name2)?.delete(callback);\n }\n addParams(mark2, paramSet) {\n const { params } = this;\n for (const param of paramSet) {\n if (params.has(param)) {\n params.get(param).push(mark2);\n } else {\n params.set(param, [mark2]);\n param.addEventListener(\"value\", () => {\n return Promise.allSettled(\n params.get(param).map((mark3) => mark3.initialize())\n );\n });\n }\n }\n }\n addMark(mark2) {\n mark2.setPlot(this, this.marks.length);\n this.marks.push(mark2);\n this.markset = null;\n return this;\n }\n get markSet() {\n return this.markset || (this.markset = new Set(this.marks));\n }\n addInteractor(sel) {\n this.interactors.push(sel);\n return this;\n }\n addLegend(legend3, include = true) {\n legend3.setPlot(this);\n this.legends.push({ legend: legend3, include });\n }\n};\nfunction maybeAspectRatio(plot3, top2, bottom2) {\n const ar = plot3.getAttribute(\"aspectRatio\");\n if (ar == null) return;\n const x3 = plot3.getAttribute(\"xDomain\");\n const y3 = plot3.getAttribute(\"yDomain\");\n if (!x3 || !y3) return;\n const dx = Math.abs(x3[1] - x3[0]);\n const dy = Math.abs(y3[1] - y3[0]);\n return dy * plot3.innerWidth() / (ar * dx) + top2 + bottom2;\n}\n\n// ../plot/src/marks/util/is-color.js\nfunction isColor2(value) {\n if (typeof value !== \"string\") return false;\n value = value.toLowerCase().trim();\n return value === \"none\" || value === \"currentcolor\" || value.startsWith(\"url(\") && value.endsWith(\")\") || // , e.g. pattern or gradient\n value.startsWith(\"var(\") && value.endsWith(\")\") || // CSS variable\n color(value) !== null;\n}\n\n// ../plot/src/marks/util/is-constant-option.js\nvar constantOptions = /* @__PURE__ */ new Set([\n \"order\",\n \"sort\",\n \"label\",\n \"anchor\",\n \"curve\",\n \"tension\",\n \"marker\",\n \"markerStart\",\n \"markerMid\",\n \"markerEnd\",\n \"textAnchor\",\n \"lineAnchor\",\n \"lineHeight\",\n \"textOverflow\",\n \"monospace\",\n \"fontFamily\",\n \"fontSize\",\n \"fontStyle\",\n \"fontVariant\",\n \"fontWeight\",\n \"frameAnchor\",\n \"strokeLinejoin\",\n \"strokeLinecap\",\n \"strokeMiterlimit\",\n \"strokeDasharray\",\n \"strokeDashoffset\",\n \"mixBlendMode\",\n \"shapeRendering\",\n \"imageRendering\",\n \"preserveAspectRatio\",\n \"interpolate\",\n \"crossOrigin\",\n \"paintOrder\",\n \"pointerEvents\",\n \"target\",\n \"select\"\n]);\nfunction isConstantOption(value) {\n return constantOptions.has(value);\n}\n\n// ../plot/src/marks/util/is-symbol.js\nvar symbols2 = /* @__PURE__ */ new Set([\n \"asterisk\",\n \"circle\",\n \"cross\",\n \"diamond\",\n \"diamond2\",\n \"hexagon\",\n \"plus\",\n \"square\",\n \"square2\",\n \"star\",\n \"times\",\n \"triangle\",\n \"triangle2\",\n \"wye\"\n]);\nfunction isSymbol2(value) {\n return symbols2.has(`${value}`.toLowerCase());\n}\n\n// ../plot/src/marks/Mark.js\nvar isColorChannel = (channel) => channel === \"stroke\" || channel === \"fill\";\nvar isOpacityChannel = (channel) => /opacity$/i.test(channel);\nvar isSymbolChannel = (channel) => channel === \"symbol\";\nvar isFieldObject = (channel, field3) => {\n return channel !== \"sort\" && channel !== \"tip\" && field3 != null && !Array.isArray(field3);\n};\nvar fieldEntry = (channel, field3) => ({\n channel,\n field: field3,\n as: field3 instanceof Ref ? field3.column : channel\n});\nvar valueEntry = (channel, value) => ({ channel, value });\nvar isDataArray = (source) => Array.isArray(source);\nvar Mark2 = class extends MosaicClient {\n constructor(type2, source, encodings, reqs = {}) {\n super(source?.options?.filterBy);\n this.type = type2;\n this.reqs = reqs;\n this.source = source;\n if (isDataArray(this.source)) {\n this.data = toDataColumns(this.source);\n }\n const channels = this.channels = [];\n const detail = this.detail = /* @__PURE__ */ new Set();\n const params = this.params = /* @__PURE__ */ new Set();\n const process = (channel, entry) => {\n const type3 = typeof entry;\n if (channel === \"channels\") {\n for (const name2 in entry) {\n detail.add(name2);\n process(name2, entry[name2]);\n }\n } else if (type3 === \"function\" && entry[Transform]) {\n const enc = entry(this, channel);\n for (const key in enc) {\n process(key, enc[key]);\n }\n } else if (type3 === \"string\") {\n if (isConstantOption(channel) || isColorChannel(channel) && isColor2(entry) || isSymbolChannel(channel) && isSymbol2(entry)) {\n channels.push(valueEntry(channel, entry));\n } else {\n channels.push(fieldEntry(channel, column(entry)));\n }\n } else if (isParamLike(entry)) {\n if (Array.isArray(entry.columns)) {\n channels.push(fieldEntry(channel, entry));\n params.add(entry);\n } else {\n const c4 = valueEntry(channel, entry.value);\n channels.push(c4);\n entry.addEventListener(\"value\", (value) => {\n c4.value = value;\n return this.update();\n });\n }\n } else if (type3 === \"object\" && isFieldObject(channel, entry)) {\n channels.push(fieldEntry(channel, entry));\n } else if (entry !== void 0) {\n channels.push(valueEntry(channel, entry));\n }\n };\n for (const channel in encodings) {\n process(channel, encodings[channel]);\n }\n }\n /**\n * @param {import('../plot.js').Plot} plot The plot.\n * @param {number} index\n */\n setPlot(plot3, index2) {\n this.plot = plot3;\n this.index = index2;\n plot3.addParams(this, this.params);\n if (this.source?.table) this.queryPending();\n }\n hasOwnData() {\n return this.source == null || isDataArray(this.source);\n }\n hasFieldInfo() {\n return !!this._fieldInfo;\n }\n channel(channel) {\n return this.channels.find((c4) => c4.channel === channel);\n }\n channelField(channel, { exact = false } = {}) {\n const c4 = exact ? this.channel(channel) : this.channels.find((c5) => c5.channel.startsWith(channel));\n return c4?.field ? c4 : null;\n }\n fields() {\n if (this.hasOwnData()) return null;\n const { source: { table: table3 }, channels, reqs } = this;\n const fields = /* @__PURE__ */ new Map();\n for (const { channel, field: field3 } of channels) {\n if (!field3) continue;\n const stats = field3.stats?.stats || [];\n const key = field3.stats?.column ?? field3;\n const entry = fields.get(key) ?? fields.set(key, /* @__PURE__ */ new Set()).get(key);\n stats.forEach((s2) => entry.add(s2));\n reqs[channel]?.forEach((s2) => entry.add(s2));\n }\n return Array.from(fields, ([c4, s2]) => ({ table: table3, column: c4, stats: s2 }));\n }\n fieldInfo(info) {\n const lookup = Object.fromEntries(info.map((x3) => [x3.column, x3]));\n for (const entry of this.channels) {\n const { field: field3 } = entry;\n if (field3) {\n Object.assign(entry, lookup[field3.stats?.column ?? field3]);\n }\n }\n this._fieldInfo = true;\n return this;\n }\n /**\n * Return a query specifying the data needed by this Mark client.\n * @param {*} [filter] The filtering criteria to apply in the query.\n * @returns {*} The client query\n */\n query(filter3 = []) {\n if (this.hasOwnData()) return null;\n const { channels, source: { table: table3 } } = this;\n return markQuery(channels, table3).where(filter3);\n }\n queryPending() {\n this.plot.pending(this);\n return this;\n }\n /**\n * Provide query result data to the mark.\n */\n queryResult(data) {\n this.data = toDataColumns(data);\n return this;\n }\n update() {\n return this.plot.update(this);\n }\n /**\n * Generate an array of Plot mark specifications.\n * @returns {object[]}\n */\n plotSpecs() {\n const { type: type2, data, detail, channels } = this;\n return markPlotSpec(type2, detail, channels, data);\n }\n};\nfunction channelOption(c4, columns) {\n const value = columns?.[c4.as] ?? c4.as;\n return Object.hasOwn(c4, \"value\") ? c4.value : isColorChannel(c4.channel) ? { value, scale: \"color\" } : isOpacityChannel(c4.channel) ? { value, scale: \"opacity\" } : value;\n}\nfunction markQuery(channels, table3, skip = []) {\n const q = Query.from({ source: table3 });\n const dims = /* @__PURE__ */ new Set();\n let aggr = false;\n for (const c4 of channels) {\n const { channel, field: field3, as } = c4;\n if (skip.includes(channel)) continue;\n if (channel === \"orderby\") {\n q.orderby(c4.value);\n } else if (field3) {\n if (field3.aggregate) {\n aggr = true;\n } else {\n if (dims.has(as)) continue;\n dims.add(as);\n }\n q.select({ [as]: field3 });\n }\n }\n if (aggr) {\n q.groupby(Array.from(dims));\n }\n return q;\n}\nfunction markPlotSpec(type2, detail, channels, data, options = {}) {\n const { numRows: length4, values: values2, columns } = data ?? {};\n const side = {};\n for (const c4 of channels) {\n const obj = detail.has(c4.channel) ? side : options;\n obj[c4.channel] = channelOption(c4, columns);\n }\n if (detail.size) options.channels = side;\n const specData = values2 ?? (data ? { length: length4 } : null);\n const spec = [{ type: type2, data: specData, options }];\n return spec;\n}\n\n// ../plot/src/marks/util/channel-scale.js\nfunction channelScale(mark2, channel) {\n const { plot: plot3 } = mark2;\n let scaleType = plot3.getAttribute(`${channel}Scale`);\n if (!scaleType) {\n const { type: type2 } = mark2.channelField(channel);\n scaleType = type2 === \"date\" ? \"time\" : \"linear\";\n }\n const options = { type: scaleType };\n switch (scaleType) {\n case \"log\":\n options.base = plot3.getAttribute(`${channel}Base`) ?? 10;\n break;\n case \"pow\":\n options.exponent = plot3.getAttribute(`${channel}Exponent`) ?? 1;\n break;\n case \"symlog\":\n options.constant = plot3.getAttribute(`${channel}Constant`) ?? 1;\n break;\n }\n return scaleTransform(options);\n}\n\n// ../plot/src/marks/util/bin-expr.js\nfunction binExpr(mark2, channel, n, extent4, pad3 = 1, expr) {\n const { field: field3 } = mark2.channelField(channel);\n expr = expr ?? field3;\n const { type: type2, apply: apply2, sqlApply } = channelScale(mark2, channel);\n const reverse3 = !!mark2.plot.getAttribute(`${channel}Reverse`);\n const [lo, hi] = extent4.map((v3) => apply2(v3));\n const v2 = sqlApply(expr);\n const f = type2 === \"time\" || type2 === \"utc\" ? v2 : expr;\n const d = hi === lo ? 0 : (n - pad3) / (hi - lo);\n const s2 = d !== 1 ? ` * ${d}::DOUBLE` : \"\";\n const bin3 = reverse3 ? sql`(${hi} - ${v2}::DOUBLE)${s2}` : sql`(${v2}::DOUBLE - ${lo})${s2}`;\n return [bin3, f];\n}\n\n// ../plot/src/marks/util/extent.js\nvar xext = { x: [\"min\", \"max\"] };\nvar yext = { y: [\"min\", \"max\"] };\nvar xyext = { ...xext, ...yext };\nfunction plotExtent(mark2, filter3, channel, domainAttr, niceAttr) {\n const { plot: plot3 } = mark2;\n const domain = plot3.getAttribute(domainAttr);\n const nice3 = plot3.getAttribute(niceAttr);\n if (Array.isArray(domain) && !domain[Transient]) {\n return domain;\n } else {\n const { column: column3, min: min5, max: max4 } = mark2.channelField(channel);\n const dom = filteredExtent(filter3, column3) || (nice3 ? linear2().domain([min5, max4]).nice().domain() : [min5, max4]);\n if (domain !== Fixed) dom[Transient] = true;\n plot3.setAttribute(domainAttr, dom, { silent: true });\n return dom;\n }\n}\nfunction extentX(mark2, filter3) {\n return plotExtent(mark2, filter3, \"x\", \"xDomain\", \"xNice\");\n}\nfunction extentY(mark2, filter3) {\n return plotExtent(mark2, filter3, \"y\", \"yDomain\", \"yNice\");\n}\nfunction filteredExtent(filter3, column3) {\n if (!filter3) return;\n let lo;\n let hi;\n const visitor = (type2, clause) => {\n if (type2 === \"BETWEEN\" && `${clause.field}` === column3) {\n const { range: range3 } = clause;\n if (range3 && (lo == null || range3[0] < lo)) lo = range3[0];\n if (range3 && (hi == null || range3[1] > hi)) hi = range3[1];\n }\n };\n if (Array.isArray(filter3)) {\n filter3.forEach((p) => p.visit?.(visitor));\n } else if (filter3.visit) {\n filter3.visit(visitor);\n }\n return lo != null && hi != null && lo !== hi ? [lo, hi] : void 0;\n}\n\n// ../plot/src/marks/ConnectedMark.js\nvar ConnectedMark = class extends Mark2 {\n constructor(type2, source, encodings) {\n const dim = type2.endsWith(\"X\") ? \"y\" : type2.endsWith(\"Y\") ? \"x\" : null;\n const req = dim ? { [dim]: [\"min\", \"max\"] } : void 0;\n super(type2, source, encodings, req);\n this.dim = dim;\n }\n /**\n * Return a query specifying the data needed by this Mark client.\n * @param {*} [filter] The filtering criteria to apply in the query.\n * @returns {*} The client query\n */\n query(filter3 = []) {\n const { plot: plot3, dim, source } = this;\n const { optimize = true } = source.options || {};\n const q = super.query(filter3);\n if (!dim) return q;\n const ortho = dim === \"x\" ? \"y\" : \"x\";\n const value = this.channelField(ortho, { exact: true })?.as;\n const { field: field3, as, type: type2, min: min5, max: max4 } = this.channelField(dim);\n const isContinuous = type2 === \"date\" || type2 === \"number\";\n if (optimize && isContinuous && value) {\n const size = dim === \"x\" ? plot3.innerWidth() : plot3.innerHeight();\n const [lo, hi] = filteredExtent(filter3, field3) || [min5, max4];\n const [expr] = binExpr(this, dim, size, [lo, hi], 1, as);\n const cols = q.select().map((c4) => c4.as).filter((c4) => c4 !== as && c4 !== value);\n return m4(q, expr, as, value, cols);\n } else {\n return q.orderby(field3);\n }\n }\n};\nfunction m4(input3, bin3, x3, y3, cols = []) {\n const pixel = sql`FLOOR(${bin3})::INTEGER`;\n const q = (sel) => Query.from(input3).select(sel).groupby(pixel, cols);\n return Query.union(\n q([{ [x3]: min(x3), [y3]: argmin(y3, x3) }, ...cols]),\n q([{ [x3]: max(x3), [y3]: argmax(y3, x3) }, ...cols]),\n q([{ [x3]: argmin(x3, y3), [y3]: min(y3) }, ...cols]),\n q([{ [x3]: argmax(x3, y3), [y3]: max(y3) }, ...cols])\n ).orderby(cols, x3);\n}\n\n// ../plot/src/marks/util/grid.js\nfunction array3(size, proto = []) {\n return new proto.constructor(size);\n}\nfunction grid1d(size, index2, value) {\n const G = array3(size, value);\n const n = value.length;\n for (let i = 0; i < n; ++i) {\n G[index2[i]] = value[i];\n }\n return G;\n}\nfunction grid2d(w, h, index2, columns, aggregates, groupby, interpolate) {\n const numRows = index2.length;\n const size = w * h;\n const values2 = aggregates.map((name2) => columns[name2]);\n const result = {};\n const cells = [];\n const group3 = new Int32Array(numRows);\n if (groupby?.length) {\n const gvalues = groupby.map((name2) => columns[name2]);\n const cellMap = {};\n for (let row = 0; row < numRows; ++row) {\n const key = gvalues.map((group4) => group4[row]);\n group3[row] = cellMap[key] ??= cells.push(key) - 1;\n }\n for (let i = 0; i < groupby.length; ++i) {\n result[groupby[i]] = cells.map((cell3) => cell3[i]);\n }\n } else {\n cells.push([]);\n }\n if (interpolate) {\n const X3 = index2.map((k2) => k2 % w);\n const Y3 = index2.map((k2) => Math.floor(k2 / w));\n const I = cells.map(() => []);\n for (let row = 0; row < numRows; ++row) {\n I[group3[row]].push(row);\n }\n aggregates.forEach((name2, i) => {\n const V = values2[i];\n result[name2] = cells.map((_, j) => interpolate(I[j], w, h, X3, Y3, V));\n });\n } else {\n aggregates.forEach((name2, i) => {\n const V = values2[i];\n const G = result[name2] = cells.map(() => array3(size, V));\n for (let row = 0; row < numRows; ++row) {\n G[group3[row]][index2[row]] = V[row];\n }\n });\n }\n return { numRows: cells.length, columns: result };\n}\nfunction gridDomainContinuous(grids) {\n let lo = Infinity, hi = -Infinity;\n grids.forEach((G) => {\n const n = G.length;\n for (let i = 0; i < n; ++i) {\n const v2 = G[i];\n if (v2 < lo) lo = v2;\n if (v2 > hi) hi = v2;\n }\n });\n return Number.isFinite(lo) && Number.isFinite(hi) ? [lo, hi] : [0, 1];\n}\nfunction gridDomainDiscrete(grids) {\n const values2 = new InternSet();\n grids.forEach((G) => {\n const n = G.length;\n for (let i = 0; i < n; ++i) {\n values2.add(G[i]);\n }\n });\n return Array.from(values2).sort(ascending);\n}\n\n// ../plot/src/marks/util/handle-param.js\nfunction handleParam(value, update2) {\n return isParam(value) ? (value.addEventListener(\"value\", update2), value.value) : value;\n}\n\n// ../plot/src/marks/util/density.js\nfunction dericheConfig(sigma, negative2 = false) {\n const a2 = new Float64Array(5);\n const bc4 = new Float64Array(4);\n dericheCausalCoeff(a2, bc4, sigma);\n const ba = Float64Array.of(\n 0,\n bc4[1] - a2[1] * bc4[0],\n bc4[2] - a2[2] * bc4[0],\n bc4[3] - a2[3] * bc4[0],\n -a2[4] * bc4[0]\n );\n const accum_denom = 1 + a2[1] + a2[2] + a2[3] + a2[4];\n const sum_causal = (bc4[0] + bc4[1] + bc4[2] + bc4[3]) / accum_denom;\n const sum_anticausal = (ba[1] + ba[2] + ba[3] + ba[4]) / accum_denom;\n return {\n sigma,\n negative: negative2,\n a: a2,\n b_causal: bc4,\n b_anticausal: ba,\n sum_causal,\n sum_anticausal\n };\n}\nfunction dericheCausalCoeff(a_out, b_out, sigma) {\n const K2 = 4;\n const alpha = Float64Array.of(\n 0.84,\n 1.8675,\n 0.84,\n -1.8675,\n -0.34015,\n -0.1299,\n -0.34015,\n 0.1299\n );\n const x12 = Math.exp(-1.783 / sigma);\n const x22 = Math.exp(-1.723 / sigma);\n const y12 = 0.6318 / sigma;\n const y22 = 1.997 / sigma;\n const beta = Float64Array.of(\n -x12 * Math.cos(y12),\n x12 * Math.sin(y12),\n -x12 * Math.cos(-y12),\n x12 * Math.sin(-y12),\n -x22 * Math.cos(y22),\n x22 * Math.sin(y22),\n -x22 * Math.cos(-y22),\n x22 * Math.sin(-y22)\n );\n const denom = sigma * 2.5066282746310007;\n const b = Float64Array.of(alpha[0], alpha[1], 0, 0, 0, 0, 0, 0);\n const a2 = Float64Array.of(1, 0, beta[0], beta[1], 0, 0, 0, 0, 0, 0);\n let j, k2;\n for (k2 = 2; k2 < 8; k2 += 2) {\n b[k2] = beta[k2] * b[k2 - 2] - beta[k2 + 1] * b[k2 - 1];\n b[k2 + 1] = beta[k2] * b[k2 - 1] + beta[k2 + 1] * b[k2 - 2];\n for (j = k2 - 2; j > 0; j -= 2) {\n b[j] += beta[k2] * b[j - 2] - beta[k2 + 1] * b[j - 1];\n b[j + 1] += beta[k2] * b[j - 1] + beta[k2 + 1] * b[j - 2];\n }\n for (j = 0; j <= k2; j += 2) {\n b[j] += alpha[k2] * a2[j] - alpha[k2 + 1] * a2[j + 1];\n b[j + 1] += alpha[k2] * a2[j + 1] + alpha[k2 + 1] * a2[j];\n }\n a2[k2 + 2] = beta[k2] * a2[k2] - beta[k2 + 1] * a2[k2 + 1];\n a2[k2 + 3] = beta[k2] * a2[k2 + 1] + beta[k2 + 1] * a2[k2];\n for (j = k2; j > 0; j -= 2) {\n a2[j] += beta[k2] * a2[j - 2] - beta[k2 + 1] * a2[j - 1];\n a2[j + 1] += beta[k2] * a2[j - 1] + beta[k2 + 1] * a2[j - 2];\n }\n }\n for (k2 = 0; k2 < K2; ++k2) {\n j = k2 << 1;\n b_out[k2] = b[j] / denom;\n a_out[k2 + 1] = a2[j + 2];\n }\n}\nfunction dericheConv2d(cx, cy, grid2, [nx, ny]) {\n const yc = new Float64Array(Math.max(nx, ny));\n const ya = new Float64Array(Math.max(nx, ny));\n const h = new Float64Array(5);\n const d = new Float64Array(grid2.length);\n for (let row = 0, r0 = 0; row < ny; ++row, r0 += nx) {\n const dx = d.subarray(r0);\n dericheConv1d(cx, grid2.subarray(r0), nx, 1, yc, ya, h, dx);\n }\n for (let c0 = 0; c0 < nx; ++c0) {\n const dy = d.subarray(c0);\n dericheConv1d(cy, dy, ny, nx, yc, ya, h, dy);\n }\n return d;\n}\nfunction dericheConv1d(c4, src, N, stride = 1, y_causal = new Float64Array(N), y_anticausal = new Float64Array(N), h = new Float64Array(5), d = y_causal, init2 = dericheInitZeroPad) {\n const stride_2 = stride * 2;\n const stride_3 = stride * 3;\n const stride_4 = stride * 4;\n const stride_N = stride * N;\n let i, n;\n init2(\n y_causal,\n src,\n N,\n stride,\n c4.b_causal,\n 3,\n c4.a,\n 4,\n c4.sum_causal,\n h,\n c4.sigma\n );\n for (n = 4, i = stride_4; n < N; ++n, i += stride) {\n y_causal[n] = c4.b_causal[0] * src[i] + c4.b_causal[1] * src[i - stride] + c4.b_causal[2] * src[i - stride_2] + c4.b_causal[3] * src[i - stride_3] - c4.a[1] * y_causal[n - 1] - c4.a[2] * y_causal[n - 2] - c4.a[3] * y_causal[n - 3] - c4.a[4] * y_causal[n - 4];\n }\n init2(\n y_anticausal,\n src,\n N,\n -stride,\n c4.b_anticausal,\n 4,\n c4.a,\n 4,\n c4.sum_anticausal,\n h,\n c4.sigma\n );\n for (n = 4, i = stride_N - stride * 5; n < N; ++n, i -= stride) {\n y_anticausal[n] = c4.b_anticausal[1] * src[i + stride] + c4.b_anticausal[2] * src[i + stride_2] + c4.b_anticausal[3] * src[i + stride_3] + c4.b_anticausal[4] * src[i + stride_4] - c4.a[1] * y_anticausal[n - 1] - c4.a[2] * y_anticausal[n - 2] - c4.a[3] * y_anticausal[n - 3] - c4.a[4] * y_anticausal[n - 4];\n }\n if (c4.negative) {\n for (n = 0, i = 0; n < N; ++n, i += stride) {\n d[i] = y_causal[n] + y_anticausal[N - n - 1];\n }\n } else {\n for (n = 0, i = 0; n < N; ++n, i += stride) {\n d[i] = Math.max(0, y_causal[n] + y_anticausal[N - n - 1]);\n }\n }\n return d;\n}\nfunction dericheInitZeroPad(dest, src, N, stride, b, p, a2, q, sum4, h, sigma, tol = 0.5) {\n const stride_N = Math.abs(stride) * N;\n const off = stride < 0 ? stride_N + stride : 0;\n let i, n, m;\n for (n = 0; n <= q; ++n) {\n h[n] = n <= p ? b[n] : 0;\n for (m = 1; m <= q && m <= n; ++m) {\n h[n] -= a2[m] * h[n - m];\n }\n }\n for (m = 0; m < q; ++m) {\n for (dest[m] = 0, n = 1; n <= m; ++n) {\n i = off + stride * n;\n if (i >= 0 && i < stride_N) {\n dest[m] += h[m - n] * src[i];\n }\n }\n }\n const cur = src[off];\n const max_iter = Math.ceil(sigma * 10);\n for (n = 0; n < max_iter; ++n) {\n for (m = 0; m < q; ++m) {\n dest[m] += h[m] * cur;\n }\n sum4 -= Math.abs(h[0]);\n if (sum4 <= tol) break;\n h[q] = n + q <= p ? b[n + q] : 0;\n for (m = 1; m <= q; ++m) {\n h[q] -= a2[m] * h[q - m];\n }\n for (m = 0; m < q; ++m) {\n h[m] = h[m + 1];\n }\n }\n return;\n}\n\n// ../plot/src/marks/Grid2DMark.js\nvar DENSITY = \"density\";\nvar Grid2DMark = class extends Mark2 {\n constructor(type2, source, options) {\n const {\n bandwidth = 0,\n interpolate = \"none\",\n pixelSize = 1,\n pad: pad3 = 1,\n width: width2,\n height: height2,\n ...channels\n } = options;\n const densityMap = createDensityMap(channels);\n super(type2, source, channels, xyext);\n this.densityMap = densityMap;\n this.bandwidth = handleParam(bandwidth, (value) => {\n this.bandwidth = value;\n return this.grids ? this.convolve().update() : null;\n });\n this.interpolate = handleParam(interpolate, (value) => {\n return this.interpolate = value, this.requestUpdate();\n });\n this.pixelSize = handleParam(pixelSize, (value) => {\n return this.pixelSize = value, this.requestUpdate();\n });\n this.pad = handleParam(pad3, (value) => {\n return this.pad = value, this.requestUpdate();\n });\n this.width = handleParam(width2, (value) => {\n return this.width = value, this.requestUpdate();\n });\n this.height = handleParam(height2, (value) => {\n return this.height = value, this.requestUpdate();\n });\n }\n /**\n * @param {import('../plot.js').Plot} plot The plot.\n * @param {number} index\n */\n setPlot(plot3, index2) {\n const update2 = () => {\n if (this.hasFieldInfo()) this.requestUpdate();\n };\n plot3.addAttributeListener(\"xDomain\", update2);\n plot3.addAttributeListener(\"yDomain\", update2);\n super.setPlot(plot3, index2);\n }\n get filterIndexable() {\n const xdom = this.plot.getAttribute(\"xDomain\");\n const ydom = this.plot.getAttribute(\"yDomain\");\n return xdom && ydom && !xdom[Transient] && !ydom[Transient];\n }\n query(filter3 = []) {\n const { interpolate, pad: pad3, channels, densityMap, source } = this;\n const [x06, x12] = this.extentX = extentX(this, filter3);\n const [y06, y12] = this.extentY = extentY(this, filter3);\n const [nx, ny] = this.bins = this.binDimensions();\n const [x3, bx] = binExpr(this, \"x\", nx, [x06, x12], pad3);\n const [y3, by] = binExpr(this, \"y\", ny, [y06, y12], pad3);\n const bounds = pad3 ? [isBetween(bx, [+x06, +x12]), isBetween(by, [+y06, +y12])] : [lte(+x06, bx), lt(bx, +x12), lte(+y06, by), lt(by, +y12)];\n const q = Query.from(source.table).where(filter3.concat(bounds));\n const groupby = this.groupby = [];\n const aggrMap = {};\n for (const c4 of channels) {\n if (Object.hasOwn(c4, \"field\")) {\n const { as, channel, field: field3 } = c4;\n if (field3.aggregate) {\n aggrMap[channel] = field3;\n densityMap[channel] = true;\n } else if (channel === \"weight\") {\n aggrMap[DENSITY] = sum(field3);\n } else if (channel !== \"x\" && channel !== \"y\") {\n q.select({ [as]: field3 });\n groupby.push(as);\n }\n }\n }\n const aggr = this.aggr = Object.keys(aggrMap);\n if (aggrMap.density && aggr.length > 1) {\n throw new Error(\"Weight option can not be used with custom aggregates.\");\n }\n if (!aggr.length) {\n aggr.push(DENSITY);\n aggrMap.density = count();\n }\n if (interpolate === \"linear\") {\n if (aggr.length > 1) {\n throw new Error(\"Linear binning not applicable to multiple aggregates.\");\n }\n if (!aggrMap.density) {\n throw new Error(\"Linear binning not applicable to custom aggregates.\");\n }\n return binLinear2d(q, x3, y3, aggrMap[DENSITY], nx, groupby);\n } else {\n return bin2d(q, x3, y3, aggrMap, nx, groupby);\n }\n }\n /**\n * @returns {[number, number]} The bin dimensions.\n */\n binDimensions() {\n const { plot: plot3, pixelSize, width: width2, height: height2 } = this;\n return [\n width2 ?? Math.round(plot3.innerWidth() / pixelSize),\n height2 ?? Math.round(plot3.innerHeight() / pixelSize)\n ];\n }\n queryResult(data) {\n const [w, h] = this.bins;\n const interp = maybeInterpolate2(this.interpolate);\n const { columns } = toDataColumns(data);\n this.grids0 = grid2d(w, h, columns.index, columns, this.aggr, this.groupby, interp);\n return this.convolve();\n }\n convolve() {\n const { aggr, bandwidth, bins: bins2, grids0, plot: plot3 } = this;\n this.grids = grids0;\n if (bandwidth > 0) {\n const prop = aggr.length === 1 ? aggr[0] : aggr.includes(DENSITY) ? DENSITY : null;\n if (!prop) {\n console.warn(\"No compatible grid found for smoothing.\");\n return this;\n }\n const g = grids0.columns[prop];\n const w = plot3.innerWidth();\n const h = plot3.innerHeight();\n const [nx, ny] = bins2;\n const neg = g.some((grid2) => grid2.some((v2) => v2 < 0));\n const configX = dericheConfig(bandwidth * (nx - 1) / w, neg);\n const configY = dericheConfig(bandwidth * (ny - 1) / h, neg);\n this.grids = {\n numRows: grids0.numRows,\n columns: {\n ...grids0.columns,\n // @ts-ignore\n [prop]: g.map((grid2) => dericheConv2d(configX, configY, grid2, bins2))\n }\n };\n }\n return this;\n }\n};\nfunction createDensityMap(channels) {\n const densityMap = {};\n for (const key in channels) {\n if (channels[key] === \"density\") {\n delete channels[key];\n densityMap[key] = true;\n }\n }\n return densityMap;\n}\nfunction maybeInterpolate2(interpolate = \"none\") {\n if (typeof interpolate === \"function\") return interpolate;\n switch (interpolate.toLowerCase()) {\n case \"none\":\n case \"linear\":\n return void 0;\n // no special interpolation need\n case \"nearest\":\n return interpolateNearest;\n case \"barycentric\":\n return interpolatorBarycentric();\n case \"random-walk\":\n return interpolatorRandomWalk();\n }\n throw new Error(`invalid interpolate: ${interpolate}`);\n}\nfunction bin2d(q, xp, yp, aggs, xn, groupby) {\n return q.select({\n index: sql`FLOOR(${xp})::INTEGER + FLOOR(${yp})::INTEGER * ${xn}`,\n ...aggs\n }).groupby(\"index\", groupby);\n}\nfunction binLinear2d(q, xp, yp, density3, xn, groupby) {\n const w = density3?.column ? `* ${density3.column}` : \"\";\n const subq = (i, w2) => q.clone().select({ xp, yp, i, w: w2 });\n const a2 = subq(\n sql`FLOOR(xp)::INTEGER + FLOOR(yp)::INTEGER * ${xn}`,\n sql`(FLOOR(xp)::INTEGER + 1 - xp) * (FLOOR(yp)::INTEGER + 1 - yp)${w}`\n );\n const b = subq(\n sql`FLOOR(xp)::INTEGER + (FLOOR(yp)::INTEGER + 1) * ${xn}`,\n sql`(FLOOR(xp)::INTEGER + 1 - xp) * (yp - FLOOR(yp)::INTEGER)${w}`\n );\n const c4 = subq(\n sql`FLOOR(xp)::INTEGER + 1 + FLOOR(yp)::INTEGER * ${xn}`,\n sql`(xp - FLOOR(xp)::INTEGER) * (FLOOR(yp)::INTEGER + 1 - yp)${w}`\n );\n const d = subq(\n sql`FLOOR(xp)::INTEGER + 1 + (FLOOR(yp)::INTEGER + 1) * ${xn}`,\n sql`(xp - FLOOR(xp)::INTEGER) * (yp - FLOOR(yp)::INTEGER)${w}`\n );\n return Query.from(Query.unionAll(a2, b, c4, d)).select({ index: \"i\", density: sum(\"w\") }, groupby).groupby(\"index\", groupby).having(neq(\"density\", 0));\n}\n\n// ../plot/src/marks/ContourMark.js\nvar ContourMark = class extends Grid2DMark {\n constructor(source, options) {\n const { thresholds = 10, ...channels } = options;\n super(\"geo\", source, {\n bandwidth: 20,\n interpolate: \"linear\",\n pixelSize: 2,\n ...channels\n });\n this.thresholds = handleParam(thresholds, (value) => {\n this.thresholds = value;\n return this.grids ? this.contours().update() : null;\n });\n }\n convolve() {\n return super.convolve().contours();\n }\n contours() {\n const { bins: bins2, densityMap, grids, thresholds, plot: plot3 } = this;\n const { numRows, columns } = grids;\n let t = thresholds;\n let tz;\n if (Array.isArray(t)) {\n tz = t;\n } else {\n const [, hi] = gridDomainContinuous(columns.density);\n tz = Array.from({ length: t - 1 }, (_, i) => hi * (i + 1) / t);\n }\n if (densityMap.fill || densityMap.stroke) {\n if (this.plot.getAttribute(\"colorScale\") !== \"log\") {\n this.plot.setAttribute(\"colorZero\", true);\n }\n }\n const [nx, ny] = bins2;\n const [x06, x12] = plot3.getAttribute(\"xDomain\");\n const [y06, y12] = plot3.getAttribute(\"yDomain\");\n const sx = (x12 - x06) / nx;\n const sy = (y12 - y06) / ny;\n const xo = +x06;\n const yo = +y06;\n const x3 = (v2) => xo + v2 * sx;\n const y3 = (v2) => yo + v2 * sy;\n const contour3 = contours_default().size(bins2);\n const data = this.contourData = Array(numRows * tz.length);\n const { density: density3, ...groupby } = columns;\n const groups2 = Object.entries(groupby);\n for (let i = 0, k2 = 0; i < numRows; ++i) {\n const grid2 = density3[i];\n const rest = groups2.reduce((o, [name2, col]) => (o[name2] = col[i], o), {});\n for (let j = 0; j < tz.length; ++j, ++k2) {\n data[k2] = Object.assign(\n transform2(contour3.contour(grid2, tz[j]), x3, y3),\n rest\n );\n }\n }\n return this;\n }\n plotSpecs() {\n const { type: type2, channels, densityMap, contourData: data } = this;\n const options = {};\n for (const c4 of channels) {\n const { channel } = c4;\n if (channel !== \"x\" && channel !== \"y\") {\n options[channel] = channelOption(c4);\n }\n }\n for (const channel in densityMap) {\n if (!densityMap[channel]) continue;\n options[channel] = channelOption({ channel, as: \"value\" });\n }\n return [{ type: type2, data, options }];\n }\n};\nfunction transform2(geometry, x3, y3) {\n function transformPolygon(coordinates) {\n coordinates.forEach(transformRing);\n }\n function transformRing(coordinates) {\n coordinates.forEach(transformPoint);\n }\n function transformPoint(coordinates) {\n coordinates[0] = x3(coordinates[0]);\n coordinates[1] = y3(coordinates[1]);\n }\n geometry.coordinates.forEach(transformPolygon);\n return geometry;\n}\n\n// ../plot/src/marks/util/permute.js\nfunction indices(length4) {\n return Array.from({ length: length4 }, (_, i) => i);\n}\nfunction permute2(data, order) {\n const ord = order.reduce((acc, val, i) => (acc[val] = i, acc), {});\n const idx = indices(data.length);\n idx.sort((a2, b) => ord[data[a2]] - ord[data[b]]);\n return idx;\n}\n\n// ../plot/src/marks/util/raster.js\nfunction createCanvas(w, h) {\n if (typeof document !== \"undefined\") {\n const c4 = document.createElement(\"canvas\");\n c4.setAttribute(\"width\", w);\n c4.setAttribute(\"height\", h);\n return c4;\n }\n throw new Error(\"Can not create a canvas instance.\");\n}\nfunction alphaConstant(v2 = 1) {\n const a2 = 255 * v2 | 0;\n return (data, w, h) => {\n for (let j = 0, k2 = 0; j < h; ++j) {\n for (let i = 0; i < w; ++i, k2 += 4) {\n data[k2 + 3] = a2;\n }\n }\n };\n}\nfunction alphaScheme(scale3) {\n const { apply: apply2 } = scale3;\n return (data, w, h, grid2) => {\n for (let j = 0, k2 = 0; j < h; ++j) {\n for (let i = 0, row = (h - j - 1) * w; i < w; ++i, k2 += 4) {\n data[k2 + 3] = 255 * apply2(grid2[i + row]) | 0;\n }\n }\n };\n}\nfunction colorConstant(v2 = {}) {\n const { r = 0, g = 0, b = 0, opacity: opacity2 = 1 } = typeof v2 === \"string\" ? rgb(v2) : v2;\n const c4 = new Uint8ClampedArray([r, g, b, 255 * opacity2 | 0]);\n return (data, w, h) => {\n for (let j = 0, k2 = 0; j < h; ++j) {\n for (let i = 0; i < w; ++i, k2 += 4) {\n data[k2 + 0] = c4[0];\n data[k2 + 1] = c4[1];\n data[k2 + 2] = c4[2];\n data[k2 + 3] = c4[3];\n }\n }\n };\n}\nfunction colorCategory(scale3) {\n const { domain, range: range3 } = scale3;\n const idx = /* @__PURE__ */ Object.create(null);\n const p = new Uint8ClampedArray(4 * domain.length);\n const n = domain.length - 1;\n const m = range3.length;\n for (let i = 0; i <= n; ++i) {\n const v2 = range3[i % m];\n const { r, g, b, opacity: opacity2 = 1 } = typeof v2 === \"string\" ? rgb(v2) : v2;\n const k2 = i << 2;\n p[k2 + 0] = r;\n p[k2 + 1] = g;\n p[k2 + 2] = b;\n p[k2 + 3] = 255 * opacity2 | 0;\n idx[domain[i]] = k2;\n }\n return (data, w, h, grid2) => {\n if (grid2.map) {\n for (let j = 0, k2 = 0; j < h; ++j) {\n for (let i = 0, row = (h - j - 1) * w; i < w; ++i, k2 += 4) {\n const c4 = idx[grid2[i + row]];\n data[k2 + 0] = p[c4 + 0];\n data[k2 + 1] = p[c4 + 1];\n data[k2 + 2] = p[c4 + 2];\n data[k2 + 3] = p[c4 + 3];\n }\n }\n } else {\n const c4 = idx[grid2];\n for (let j = 0, k2 = 0; j < h; ++j) {\n for (let i = 0; i < w; ++i, k2 += 4) {\n data[k2 + 0] = p[c4 + 0];\n data[k2 + 1] = p[c4 + 1];\n data[k2 + 2] = p[c4 + 2];\n data[k2 + 3] = p[c4 + 3];\n }\n }\n }\n };\n}\nfunction colorScheme(size, scale3, frac) {\n const { interpolate } = scale3;\n const p = new Uint8ClampedArray(4 * size);\n const n = size - 1;\n for (let i = 0; i <= n; ++i) {\n const v2 = interpolate(i / n);\n const { r, g, b, opacity: opacity2 = 1 } = typeof v2 === \"string\" ? rgb(v2) : v2;\n const k2 = i << 2;\n p[k2 + 0] = r;\n p[k2 + 1] = g;\n p[k2 + 2] = b;\n p[k2 + 3] = 255 * opacity2 | 0;\n }\n return (data, w, h, grid2) => {\n for (let j = 0, k2 = 0; j < h; ++j) {\n for (let i = 0, row = (h - j - 1) * w; i < w; ++i, k2 += 4) {\n const c4 = n * frac(grid2[i + row]) << 2;\n data[k2 + 0] = p[c4 + 0];\n data[k2 + 1] = p[c4 + 1];\n data[k2 + 2] = p[c4 + 2];\n data[k2 + 3] = p[c4 + 3];\n }\n }\n };\n}\n\n// ../plot/src/marks/RasterMark.js\nvar RasterMark = class extends Grid2DMark {\n constructor(source, options) {\n super(\"image\", source, options);\n this.image = null;\n }\n setPlot(plot3, index2) {\n const update2 = () => {\n if (this.hasFieldInfo()) this.rasterize();\n };\n plot3.addAttributeListener(\"schemeColor\", update2);\n super.setPlot(plot3, index2);\n }\n convolve() {\n return super.convolve().rasterize();\n }\n rasterize() {\n const { bins: bins2, grids } = this;\n const [w, h] = bins2;\n const { numRows, columns } = grids;\n const { canvas, ctx, img } = imageData(this, w, h);\n const { alpha, alphaProp, color: color3, colorProp } = rasterEncoding(this);\n const alphaData = columns[alphaProp] ?? [];\n const colorData = columns[colorProp] ?? [];\n const idx = numRows > 1 && colorProp && this.groupby?.includes(colorProp) ? permute2(colorData, this.plot.getAttribute(\"colorDomain\")) : indices(numRows);\n this.data = {\n numRows,\n columns: {\n src: Array.from({ length: numRows }, (_, i) => {\n color3?.(img.data, w, h, colorData[idx[i]]);\n alpha?.(img.data, w, h, alphaData[idx[i]]);\n ctx.putImageData(img, 0, 0);\n return canvas.toDataURL();\n })\n }\n };\n return this;\n }\n plotSpecs() {\n const { type: type2, plot: plot3, data: { numRows: length4, columns } } = this;\n const options = {\n src: columns.src,\n width: plot3.innerWidth(),\n height: plot3.innerHeight(),\n preserveAspectRatio: \"none\",\n imageRendering: this.channel(\"imageRendering\")?.value,\n frameAnchor: \"middle\"\n };\n return [{ type: type2, data: { length: length4 }, options }];\n }\n};\nvar HeatmapMark = class extends RasterMark {\n constructor(source, options) {\n super(source, {\n bandwidth: 20,\n interpolate: \"linear\",\n pixelSize: 2,\n ...options\n });\n }\n};\nfunction rasterEncoding(mark2) {\n const { aggr, densityMap, groupby, plot: plot3 } = mark2;\n const hasDensity = aggr.includes(DENSITY);\n const hasFillOpacity = aggr.includes(\"fillOpacity\");\n const fillEntry = mark2.channel(\"fill\");\n const opacEntry = mark2.channel(\"fillOpacity\");\n if (aggr.length > 2 || hasDensity && hasFillOpacity) {\n throw new Error(\"Invalid raster encodings. Try dropping an aggregate?\");\n }\n if (groupby.includes(opacEntry?.as)) {\n throw new Error(\"Raster fillOpacity must be an aggregate or constant.\");\n }\n const fill = densityMap.fill || aggr.includes(\"fill\") ? \"grid\" : groupby.includes(fillEntry?.as) ? \"group\" : isColor2(fillEntry?.value) ? fillEntry.value : hasDensity && plot3.getAttribute(\"colorScheme\") ? \"grid\" : void 0;\n const opac = densityMap.fillOpacity || aggr.includes(\"fillOpacity\") ? \"grid\" : typeof opacEntry?.value === \"number\" ? opacEntry.value : hasDensity && fill !== \"grid\" ? \"grid\" : void 0;\n if (fill !== \"grid\" && opac !== \"grid\") {\n throw new Error(\"Raster mark missing density values.\");\n }\n const colorProp = fillEntry?.as ?? (fill === \"grid\" ? DENSITY : null);\n const alphaProp = opacEntry?.as ?? (opac === \"grid\" ? DENSITY : null);\n const color3 = fill !== \"grid\" && fill !== \"group\" ? colorConstant(fill) : colorScale(mark2, colorProp);\n const alpha = opac !== \"grid\" ? alphaConstant(opac) : alphaScale(mark2, alphaProp);\n return { alphaProp, colorProp, alpha, color: color3 };\n}\nfunction alphaScale(mark2, prop) {\n const { plot: plot3, grids } = mark2;\n const domainAttr = plot3.getAttribute(\"opacityDomain\");\n const domainFixed = domainAttr === Fixed;\n const domainTransient = domainAttr?.[Transient];\n const domain = !domainFixed && !domainTransient && domainAttr || gridDomainContinuous(grids.columns[prop]);\n if (domainFixed || domainTransient || !domainAttr) {\n if (!domainFixed) domain[Transient] = true;\n plot3.setAttribute(\"opacityDomain\", domain);\n }\n const s2 = scale2({\n opacity: {\n type: plot3.getAttribute(\"opacityScale\"),\n domain,\n clamp: plot3.getAttribute(\"opacityClamp\"),\n nice: plot3.getAttribute(\"opacityNice\"),\n reverse: plot3.getAttribute(\"opacityReverse\"),\n zero: plot3.getAttribute(\"opacityZero\"),\n base: plot3.getAttribute(\"opacityBase\"),\n exponent: plot3.getAttribute(\"opacityExponent\"),\n constant: plot3.getAttribute(\"opacityConstant\")\n }\n });\n return alphaScheme(s2);\n}\nfunction colorScale(mark2, prop) {\n const { plot: plot3, grids } = mark2;\n const data = grids.columns[prop];\n const flat = !data[0]?.map;\n const discrete = flat || Array.isArray(data[0]);\n const domainAttr = plot3.getAttribute(\"colorDomain\");\n const domainFixed = domainAttr === Fixed;\n const domainTransient = domainAttr?.[Transient];\n const domain = !domainFixed && !domainTransient && domainAttr || (flat ? data.slice().sort(ascending) : discrete ? gridDomainDiscrete(data) : gridDomainContinuous(data));\n if (domainFixed || domainTransient || !domainAttr) {\n if (!domainFixed) domain[Transient] = true;\n plot3.setAttribute(\"colorDomain\", domain);\n }\n const s2 = scale2({\n color: {\n type: plot3.getAttribute(\"colorScale\"),\n domain,\n range: plot3.getAttribute(\"colorRange\"),\n clamp: plot3.getAttribute(\"colorClamp\"),\n n: plot3.getAttribute(\"colorN\"),\n nice: plot3.getAttribute(\"colorNice\"),\n reverse: plot3.getAttribute(\"colorReverse\"),\n scheme: plot3.getAttribute(\"colorScheme\"),\n interpolate: plot3.getAttribute(\"colorInterpolate\"),\n pivot: plot3.getAttribute(\"colorPivot\"),\n symmetric: plot3.getAttribute(\"colorSymmetric\"),\n zero: plot3.getAttribute(\"colorZero\"),\n base: plot3.getAttribute(\"colorBase\"),\n exponent: plot3.getAttribute(\"colorExponent\"),\n constant: plot3.getAttribute(\"colorConstant\")\n }\n });\n if (discrete) {\n return colorCategory(s2);\n } else {\n const frac = scale2({\n x: {\n type: inferScaleType2(s2.type),\n domain: s2.domain,\n reverse: s2.reverse,\n range: [0, 1],\n clamp: s2.clamp,\n base: s2.base,\n exponent: s2.exponent,\n constant: s2.constant\n }\n });\n return colorScheme(1024, s2, frac.apply);\n }\n}\nfunction inferScaleType2(type2) {\n if (type2.endsWith(\"symlog\")) return \"symlog\";\n if (type2.endsWith(\"log\")) return \"log\";\n if (type2.endsWith(\"pow\")) return \"pow\";\n if (type2.endsWith(\"sqrt\")) return \"sqrt\";\n if (type2 === \"diverging\") return \"linear\";\n return type2;\n}\nfunction imageData(mark2, w, h) {\n if (!mark2.image || mark2.image.w !== w || mark2.image.h !== h) {\n const canvas = createCanvas(w, h);\n const ctx = canvas.getContext(\"2d\", { willReadFrequently: true });\n const img = ctx.getImageData(0, 0, w, h);\n mark2.image = { canvas, ctx, img, w, h };\n }\n return mark2.image;\n}\n\n// ../plot/src/marks/DenseLineMark.js\nvar DenseLineMark = class extends RasterMark {\n constructor(source, options) {\n const { normalize: normalize4 = true, ...rest } = options;\n super(source, rest);\n this.normalize = handleParam(normalize4, (value) => {\n return this.normalize = value, this.requestUpdate();\n });\n }\n query(filter3 = []) {\n const { channels, normalize: normalize4, source, pad: pad3 } = this;\n const [nx, ny] = this.bins = this.binDimensions();\n const [x3] = binExpr(this, \"x\", nx, extentX(this, filter3), pad3);\n const [y3] = binExpr(this, \"y\", ny, extentY(this, filter3), pad3);\n const q = Query.from(source.table).where(stripXY(this, filter3));\n this.aggr = [\"density\"];\n const groupby = this.groupby = [];\n const z = [];\n for (const c4 of channels) {\n if (Object.hasOwn(c4, \"field\")) {\n const { channel, field: field3 } = c4;\n if (channel === \"z\") {\n q.select({ [channel]: field3 });\n z.push(\"z\");\n } else if (channel !== \"x\" && channel !== \"y\") {\n q.select({ [channel]: field3 });\n groupby.push(channel);\n }\n }\n }\n return lineDensity(q, x3, y3, z, nx, ny, groupby, normalize4);\n }\n};\nfunction stripXY(mark2, filter3) {\n if (Array.isArray(filter3) && !filter3.length) return filter3;\n const { column: xc } = mark2.channelField(\"x\");\n const { column: yc } = mark2.channelField(\"y\");\n const test = (p) => {\n const col = `${p.field}`;\n return p.op !== \"BETWEEN\" || col !== xc && col !== yc;\n };\n const filterAnd = (p) => p.op === \"AND\" ? and(p.children.filter((c4) => test(c4))) : p;\n return Array.isArray(filter3) ? filter3.filter((p) => test(p)).map((p) => filterAnd(p)) : filterAnd(filter3);\n}\nfunction lineDensity(q, x3, y3, z, xn, yn, groupby = [], normalize4 = true) {\n q.select({\n x: sql`FLOOR(${x3})::INTEGER`,\n y: sql`FLOOR(${y3})::INTEGER`\n });\n const groups2 = groupby.concat(z);\n const pairPart = groups2.length ? `PARTITION BY ${groups2.join(\", \")} ` : \"\";\n const pairs3 = Query.from(q).select(groups2, {\n x0: \"x\",\n y0: \"y\",\n dx: sql`(lead(x) OVER sw - x)`,\n dy: sql`(lead(y) OVER sw - y)`\n }).window({ sw: sql`${pairPart}ORDER BY x ASC` }).qualify(and(\n sql`(x0 < ${xn} OR x0 + dx < ${xn})`,\n sql`(y0 < ${yn} OR y0 + dy < ${yn})`,\n sql`(x0 > 0 OR x0 + dx > 0)`,\n sql`(y0 > 0 OR y0 + dy > 0)`\n ));\n const num = Query.select({ x: sql`GREATEST(MAX(ABS(dx)), MAX(ABS(dy)))` }).from(\"pairs\");\n const indices2 = Query.select({ i: sql`UNNEST(range((${num})))::INTEGER` });\n const raster3 = Query.unionAll(\n Query.select(groups2, {\n x: sql`x0 + i`,\n y: sql`y0 + ROUND(i * dy / dx::FLOAT)::INTEGER`\n }).from(\"pairs\", \"indices\").where(sql`ABS(dy) <= ABS(dx) AND i < ABS(dx)`),\n Query.select(groups2, {\n x: sql`x0 + ROUND(SIGN(dy) * i * dx / dy::FLOAT)::INTEGER`,\n y: sql`y0 + SIGN(dy) * i`\n }).from(\"pairs\", \"indices\").where(sql`ABS(dy) > ABS(dx) AND i < ABS(dy)`),\n Query.select(groups2, { x: \"x0\", y: \"y0\" }).from(\"pairs\").where(isNull(\"dx\"))\n );\n const pointPart = [\"x\"].concat(groups2).join(\", \");\n const points2 = Query.from(\"raster\").select(\n groups2,\n \"x\",\n \"y\",\n normalize4 ? { w: sql`1.0 / COUNT(*) OVER (PARTITION BY ${pointPart})` } : null\n ).where(and(isBetween(\"x\", [0, xn], true), isBetween(\"y\", [0, yn], true)));\n return Query.with({ pairs: pairs3, indices: indices2, raster: raster3, points: points2 }).from(\"points\").select(groupby, {\n index: sql`x + y * ${xn}::INTEGER`,\n density: normalize4 ? sum(\"w\") : count()\n }).groupby(\"index\", groupby);\n}\n\n// ../plot/src/marks/Density1DMark.js\nvar Density1DMark = class extends Mark2 {\n constructor(type2, source, options) {\n const { bins: bins2 = 1024, bandwidth = 20, ...channels } = options;\n const dim = type2.endsWith(\"X\") ? \"y\" : \"x\";\n super(type2, source, channels, dim === \"x\" ? xext : yext);\n this.dim = dim;\n this.bins = handleParam(bins2, (value) => {\n return this.bins = value, this.requestUpdate();\n });\n this.bandwidth = handleParam(bandwidth, (value) => {\n this.bandwidth = value;\n return this.grid ? this.convolve().update() : null;\n });\n }\n get filterIndexable() {\n const name2 = this.dim === \"x\" ? \"xDomain\" : \"yDomain\";\n const dom = this.plot.getAttribute(name2);\n return dom && !dom[Transient];\n }\n query(filter3 = []) {\n if (this.hasOwnData()) throw new Error(\"Density1DMark requires a data source\");\n const { bins: bins2, channels, dim, source: { table: table3 } } = this;\n const extent4 = this.extent = (dim === \"x\" ? extentX : extentY)(this, filter3);\n const [x3, bx] = binExpr(this, dim, bins2, extent4);\n const q = markQuery(channels, table3, [dim]).where(filter3.concat(isBetween(bx, extent4)));\n const v2 = this.channelField(\"weight\") ? \"weight\" : null;\n return binLinear1d(q, x3, v2);\n }\n queryResult(data) {\n const { columns: { index: index2, density: density3 } } = toDataColumns(data);\n this.grid = grid1d(this.bins, index2, density3);\n return this.convolve();\n }\n convolve() {\n const { bins: bins2, bandwidth, dim, grid: grid2, plot: plot3, extent: [lo, hi] } = this;\n const neg = grid2.some((v3) => v3 < 0);\n const size = dim === \"x\" ? plot3.innerWidth() : plot3.innerHeight();\n const config = dericheConfig(bandwidth * (bins2 - 1) / size, neg);\n const result = dericheConv1d(config, grid2, bins2);\n const v2 = dim === \"x\" ? \"y\" : \"x\";\n const b = this.channelField(dim).as;\n const b0 = +lo;\n const delta = (hi - b0) / (bins2 - 1);\n const scale3 = 1 / delta;\n const _b = new Float64Array(bins2);\n const _v = new Float64Array(bins2);\n for (let i = 0; i < bins2; ++i) {\n _b[i] = b0 + i * delta;\n _v[i] = result[i] * scale3;\n }\n this.data = { numRows: bins2, columns: { [b]: _b, [v2]: _v } };\n return this;\n }\n plotSpecs() {\n const { type: type2, data: { numRows: length4, columns }, channels, dim } = this;\n const options = dim === \"x\" ? { y: columns.y } : { x: columns.x };\n for (const c4 of channels) {\n options[c4.channel] = channelOption(c4, columns);\n }\n return [{ type: type2, data: { length: length4 }, options }];\n }\n};\nfunction binLinear1d(q, p, density3) {\n const w = density3 ? `* ${density3}` : \"\";\n const u4 = q.clone().select({\n p,\n i: sql`FLOOR(p)::INTEGER`,\n w: sql`(FLOOR(p) + 1 - p)${w}`\n });\n const v2 = q.clone().select({\n p,\n i: sql`FLOOR(p)::INTEGER + 1`,\n w: sql`(p - FLOOR(p))${w}`\n });\n return Query.from(Query.unionAll(u4, v2)).select({ index: \"i\", density: sum(\"w\") }).groupby(\"index\").having(gt(\"density\", 0));\n}\n\n// ../plot/src/marks/Density2DMark.js\nvar Density2DMark = class extends Grid2DMark {\n constructor(source, options) {\n const { type: type2 = \"dot\", ...channels } = options;\n super(type2, source, {\n bandwidth: 20,\n interpolate: \"linear\",\n pad: 0,\n pixelSize: 2,\n ...channels\n });\n }\n convolve() {\n super.convolve();\n const { bins: bins2, pad: pad3, extentX: extentX2, extentY: extentY2 } = this;\n const [nx, ny] = bins2;\n const scaleX = channelScale(this, \"x\");\n const scaleY = channelScale(this, \"y\");\n const [x06, x12] = extentX2.map((v2) => scaleX.apply(v2));\n const [y06, y12] = extentY2.map((v2) => scaleY.apply(v2));\n const deltaX = (x12 - x06) / (nx - pad3);\n const deltaY = (y12 - y06) / (ny - pad3);\n const offset2 = pad3 ? 0 : 0.5;\n this.data = points(\n this.grids,\n bins2,\n x06,\n y06,\n deltaX,\n deltaY,\n scaleX.invert,\n scaleY.invert,\n offset2\n );\n return this;\n }\n plotSpecs() {\n const { type: type2, channels, densityMap, data: { numRows: length4, columns } } = this;\n const options = {};\n for (const c4 of channels) {\n const { channel } = c4;\n options[channel] = channel === \"x\" || channel === \"y\" ? columns[channel] : channelOption(c4, columns);\n }\n for (const channel in densityMap) {\n if (densityMap[channel]) {\n options[channel] = columns.density;\n }\n }\n return [{ type: type2, data: { length: length4 }, options }];\n }\n};\nfunction points(data, bins2, x06, y06, deltaX, deltaY, invertX, invertY, offset2) {\n const scale3 = 1 / (deltaX * deltaY);\n const [nx, ny] = bins2;\n const batch = nx * ny;\n const numRows = batch * data.numRows;\n const x3 = new Float64Array(numRows);\n const y3 = new Float64Array(numRows);\n const density3 = new Float64Array(numRows);\n const columns = { x: x3, y: y3, density: density3 };\n const { density: grids, ...rest } = data.columns;\n for (const name2 in rest) {\n columns[name2] = new rest[name2].constructor(numRows);\n }\n let r = 0;\n for (let row = 0; row < data.numRows; ++row) {\n for (const name2 in rest) {\n columns[name2].fill(rest[name2][row], r, r + batch);\n }\n const grid2 = grids[row];\n for (let k2 = 0, j = 0; j < ny; ++j) {\n for (let i = 0; i < nx; ++i, ++r, ++k2) {\n x3[r] = invertX(x06 + (i + offset2) * deltaX);\n y3[r] = invertY(y06 + (j + offset2) * deltaY);\n density3[r] = grid2[k2] * scale3;\n }\n }\n }\n return { numRows, columns };\n}\n\n// ../plot/src/marks/util/stats.js\nfunction ibetainv2(p, a2, b) {\n var EPS2 = 1e-8;\n var a1 = a2 - 1;\n var b1 = b - 1;\n var j = 0;\n var lna, lnb, pp, t, u4, err, x3, al, h, w, afac;\n if (p <= 0) return 0;\n if (p >= 1) return 1;\n if (a2 >= 1 && b >= 1) {\n pp = p < 0.5 ? p : 1 - p;\n t = Math.sqrt(-2 * Math.log(pp));\n x3 = (2.30753 + t * 0.27061) / (1 + t * (0.99229 + t * 0.04481)) - t;\n if (p < 0.5) x3 = -x3;\n al = (x3 * x3 - 3) / 6;\n h = 2 / (1 / (2 * a2 - 1) + 1 / (2 * b - 1));\n w = x3 * Math.sqrt(al + h) / h - (1 / (2 * b - 1) - 1 / (2 * a2 - 1)) * (al + 5 / 6 - 2 / (3 * h));\n x3 = a2 / (a2 + b * Math.exp(2 * w));\n } else {\n lna = Math.log(a2 / (a2 + b));\n lnb = Math.log(b / (a2 + b));\n t = Math.exp(a2 * lna) / a2;\n u4 = Math.exp(b * lnb) / b;\n w = t + u4;\n if (p < t / w) x3 = Math.pow(a2 * w * p, 1 / a2);\n else x3 = 1 - Math.pow(b * w * (1 - p), 1 / b);\n }\n afac = -gammaln2(a2) - gammaln2(b) + gammaln2(a2 + b);\n for (; j < 10; j++) {\n if (x3 === 0 || x3 === 1) return x3;\n err = ibeta2(x3, a2, b) - p;\n t = Math.exp(a1 * Math.log(x3) + b1 * Math.log(1 - x3) + afac);\n u4 = err / t;\n x3 -= t = u4 / (1 - 0.5 * Math.min(1, u4 * (a1 / x3 - b1 / (1 - x3))));\n if (x3 <= 0) x3 = 0.5 * (x3 + t);\n if (x3 >= 1) x3 = 0.5 * (x3 + t + 1);\n if (Math.abs(t) < EPS2 * x3 && j > 0) break;\n }\n return x3;\n}\nfunction ibeta2(x3, a2, b) {\n var bt = x3 === 0 || x3 === 1 ? 0 : Math.exp(gammaln2(a2 + b) - gammaln2(a2) - gammaln2(b) + a2 * Math.log(x3) + b * Math.log(1 - x3));\n if (x3 < 0 || x3 > 1) return 0;\n if (x3 < (a2 + 1) / (a2 + b + 2))\n return bt * betacf2(x3, a2, b) / a2;\n return 1 - bt * betacf2(1 - x3, b, a2) / b;\n}\nfunction betacf2(x3, a2, b) {\n var fpmin = 1e-30;\n var m = 1;\n var qab = a2 + b;\n var qap = a2 + 1;\n var qam = a2 - 1;\n var c4 = 1;\n var d = 1 - qab * x3 / qap;\n var m2, aa2, del, h;\n if (Math.abs(d) < fpmin) d = fpmin;\n d = 1 / d;\n h = d;\n for (; m <= 100; m++) {\n m2 = 2 * m;\n aa2 = m * (b - m) * x3 / ((qam + m2) * (a2 + m2));\n d = 1 + aa2 * d;\n if (Math.abs(d) < fpmin) d = fpmin;\n c4 = 1 + aa2 / c4;\n if (Math.abs(c4) < fpmin) c4 = fpmin;\n d = 1 / d;\n h *= d * c4;\n aa2 = -(a2 + m) * (qab + m) * x3 / ((a2 + m2) * (qap + m2));\n d = 1 + aa2 * d;\n if (Math.abs(d) < fpmin) d = fpmin;\n c4 = 1 + aa2 / c4;\n if (Math.abs(c4) < fpmin) c4 = fpmin;\n d = 1 / d;\n del = d * c4;\n h *= del;\n if (Math.abs(del - 1) < 3e-7) break;\n }\n return h;\n}\nfunction gammaln2(x3) {\n var j = 0;\n var cof = [\n 76.18009172947146,\n -86.5053203294167,\n 24.01409824083091,\n -1.231739572450155,\n 0.001208650973866179,\n -5395239384953e-18\n ];\n var ser = 1.000000000190015;\n var xx, y3, tmp;\n tmp = (y3 = xx = x3) + 5.5;\n tmp -= (xx + 0.5) * Math.log(tmp);\n for (; j < 6; j++) ser += cof[j] / ++y3;\n return Math.log(2.506628274631 * ser / xx) - tmp;\n}\nfunction qt2(p, dof) {\n var x3 = ibetainv2(2 * Math.min(p, 1 - p), 0.5 * dof, 0.5);\n x3 = Math.sqrt(dof * (1 - x3) / x3);\n return p > 0.5 ? x3 : -x3;\n}\nfunction erfinv(x3) {\n let w = -Math.log((1 - x3) * (1 + x3));\n let p;\n if (w < 6.25) {\n w -= 3.125;\n p = -364441206401782e-35;\n p = -16850591381820166e-35 + p * w;\n p = 128584807152564e-32 + p * w;\n p = 11157877678025181e-33 + p * w;\n p = -1333171662854621e-31 + p * w;\n p = 20972767875968562e-33 + p * w;\n p = 6637638134358324e-30 + p * w;\n p = -4054566272975207e-29 + p * w;\n p = -8151934197605472e-29 + p * w;\n p = 26335093153082323e-28 + p * w;\n p = -12975133253453532e-27 + p * w;\n p = -5415412054294628e-26 + p * w;\n p = 10512122733215323e-25 + p * w;\n p = -4112633980346984e-24 + p * w;\n p = -29070369957882005e-24 + p * w;\n p = 42347877827932404e-23 + p * w;\n p = -13654692000834679e-22 + p * w;\n p = -13882523362786469e-21 + p * w;\n p = 18673420803405714e-20 + p * w;\n p = -740702534166267e-18 + p * w;\n p = -0.006033670871430149 + p * w;\n p = 0.24015818242558962 + p * w;\n p = 1.6536545626831027 + p * w;\n } else if (w < 16) {\n w = Math.sqrt(w) - 3.25;\n p = 22137376921775787e-25;\n p = 9075656193888539e-23 + p * w;\n p = -27517406297064545e-23 + p * w;\n p = 18239629214389228e-24 + p * w;\n p = 15027403968909828e-22 + p * w;\n p = -4013867526981546e-21 + p * w;\n p = 29234449089955446e-22 + p * w;\n p = 12475304481671779e-21 + p * w;\n p = -47318229009055734e-21 + p * w;\n p = 6828485145957318e-20 + p * w;\n p = 24031110387097894e-21 + p * w;\n p = -3550375203628475e-19 + p * w;\n p = 9532893797373805e-19 + p * w;\n p = -0.0016882755560235047 + p * w;\n p = 0.002491442096107851 + p * w;\n p = -0.003751208507569241 + p * w;\n p = 0.005370914553590064 + p * w;\n p = 1.0052589676941592 + p * w;\n p = 3.0838856104922208 + p * w;\n } else if (Number.isFinite(w)) {\n w = Math.sqrt(w) - 5;\n p = -27109920616438573e-27;\n p = -2555641816996525e-25 + p * w;\n p = 15076572693500548e-25 + p * w;\n p = -3789465440126737e-24 + p * w;\n p = 761570120807834e-23 + p * w;\n p = -1496002662714924e-23 + p * w;\n p = 2914795345090108e-23 + p * w;\n p = -6771199775845234e-23 + p * w;\n p = 22900482228026655e-23 + p * w;\n p = -99298272942317e-20 + p * w;\n p = 4526062597223154e-21 + p * w;\n p = -1968177810553167e-20 + p * w;\n p = 7599527703001776e-20 + p * w;\n p = -21503011930044477e-20 + p * w;\n p = -13871931833623122e-20 + p * w;\n p = 1.0103004648645344 + p * w;\n p = 4.849906401408584 + p * w;\n } else {\n p = Infinity;\n }\n return p * x3;\n}\n\n// ../plot/src/marks/ErrorBarMark.js\nvar ErrorBarMark = class extends Mark2 {\n constructor(type2, source, options) {\n const dim = type2.endsWith(\"X\") ? \"y\" : \"x\";\n const { ci = 0.95, ...channels } = options;\n super(type2, source, channels);\n this.dim = dim;\n this.field = this.channelField(dim).field;\n this.channels = this.channels.filter((c4) => c4.channel !== dim);\n this.ci = handleParam(ci, (value) => {\n return this.ci = value, this.update();\n });\n }\n query(filter3 = []) {\n const { channels, field: field3, source: { table: table3 } } = this;\n const fields = channels.concat([\n { field: avg(field3), as: \"__avg__\" },\n { field: count(field3), as: \"__n__\" },\n { field: stddev(field3), as: \"__sd__\" }\n ]);\n return markQuery(fields, table3).where(filter3);\n }\n queryResult(data) {\n this.data = toDataColumns(data);\n return this;\n }\n plotSpecs() {\n const { type: type2, dim, detail, data, ci, channels } = this;\n const p = Math.SQRT2 * erfinv(ci);\n const { columns: { __avg__: u4, __sd__: s2, __n__: n } } = data;\n const options = {\n [`${dim}1`]: u4.map((u5, i) => u5 - p * s2[i] / Math.sqrt(n[i])),\n [`${dim}2`]: u4.map((u5, i) => u5 + p * s2[i] / Math.sqrt(n[i]))\n };\n return markPlotSpec(type2, detail, channels, data, options);\n }\n};\n\n// ../plot/src/marks/GeoMark.js\nvar DEFAULT_GEOMETRY_COLUMN = \"geom\";\nvar GeoMark = class extends Mark2 {\n constructor(source, encodings = {}, reqs) {\n if (!isDataArray(source) && !encodings?.geometry) {\n encodings.geometry = geojson(DEFAULT_GEOMETRY_COLUMN);\n }\n super(\"geo\", source, encodings, reqs);\n }\n queryResult(data) {\n super.queryResult(data);\n const geom = this.channelField(\"geometry\")?.as;\n if (geom) {\n const { columns } = this.data;\n if (typeof columns[geom][0] === \"string\") {\n columns[geom] = columns[geom].map((s2) => JSON.parse(s2));\n }\n }\n return this;\n }\n};\n\n// ../plot/src/marks/HexbinMark.js\nvar HexbinMark = class extends Mark2 {\n constructor(source, options) {\n const { type: type2 = \"hexagon\", binWidth = 20, ...channels } = options;\n super(type2, source, { r: binWidth / 2, clip: true, ...channels }, xyext);\n this.binWidth = handleParam(binWidth, (value) => {\n return this.binWidth = value, this.requestUpdate();\n });\n }\n get filterIndexable() {\n const xdom = this.plot.getAttribute(\"xDomain\");\n const ydom = this.plot.getAttribute(\"yDomain\");\n return xdom && ydom && !xdom[Transient] && !ydom[Transient];\n }\n query(filter3 = []) {\n if (this.hasOwnData()) return null;\n const { plot: plot3, binWidth, channels, source } = this;\n let x3, y3;\n const dims = /* @__PURE__ */ new Set();\n const cols = {};\n for (const c4 of channels) {\n if (c4.channel === \"orderby\") {\n } else if (c4.channel === \"x\") {\n x3 = c4;\n } else if (c4.channel === \"y\") {\n y3 = c4;\n } else if (Object.hasOwn(c4, \"field\")) {\n const { as, field: field3 } = c4;\n cols[as] = field3;\n if (!field3.aggregate) {\n dims.add(as);\n }\n }\n }\n const [x12, x22] = extentX(this, filter3);\n const [y12, y22] = extentY(this, filter3);\n const ox2 = 0.5 - plot3.getAttribute(\"marginLeft\");\n const oy2 = 0 - plot3.getAttribute(\"marginTop\");\n const dx = `${binWidth}::DOUBLE`;\n const dy = `${binWidth * (1.5 / Math.sqrt(3))}::DOUBLE`;\n const xr = `${plot3.innerWidth() / (x22 - x12)}::DOUBLE`;\n const yr = `${plot3.innerHeight() / (y22 - y12)}::DOUBLE`;\n return Query.select({\n [x3.as]: sql`${x12}::DOUBLE + ((_x + 0.5 * (_y & 1)) * ${dx} + ${ox2})::DOUBLE / ${xr}`,\n [y3.as]: sql`${y22}::DOUBLE - (_y * ${dy} + ${oy2})::DOUBLE / ${yr}`,\n ...cols\n }).groupby(\"_x\", \"_y\", ...dims).from(\n // Subquery performs hex binning in screen space and also passes\n // original columns through (the DB should optimize this).\n Query.select({\n _py: sql`(${yr} * (${y22}::DOUBLE - ${y3.field}) - ${oy2}) / ${dy}`,\n _pj: sql`ROUND(_py)::INTEGER`,\n _px: sql`(${xr} * (${x3.field} - ${x12}::DOUBLE) - ${ox2}) / ${dx} - 0.5 * (_pj & 1)`,\n _pi: sql`ROUND(_px)::INTEGER`,\n _tt: sql`ABS(_py-_pj) * 3 > 1 AND (_px-_pi)**2 + (_py-_pj)**2 > (_px - _pi - 0.5 * CASE WHEN _px < _pi THEN -1 ELSE 1 END)**2 + (_py - _pj - CASE WHEN _py < _pj THEN -1 ELSE 1 END)**2`,\n _x: sql`CASE WHEN _tt THEN (_pi + (CASE WHEN _px < _pi THEN -0.5 ELSE 0.5 END) + (CASE WHEN _pj & 1 <> 0 THEN 0.5 ELSE -0.5 END))::INTEGER ELSE _pi END`,\n _y: sql`CASE WHEN _tt THEN (_pj + CASE WHEN _py < _pj THEN -1 ELSE 1 END)::INTEGER ELSE _pj END`\n }, \"*\").from(source.table).where(isNotNull(x3.field), isNotNull(y3.field), filter3)\n );\n }\n};\n\n// ../plot/src/marks/RasterTileMark.js\nvar RasterTileMark = class extends Grid2DMark {\n constructor(source, options) {\n const { origin = [0, 0], dim = \"xy\", ...markOptions2 } = options;\n super(\"image\", source, markOptions2);\n this.image = null;\n this.origin = origin;\n this.tileX = dim.toLowerCase().includes(\"x\");\n this.tileY = dim.toLowerCase().includes(\"y\");\n }\n setPlot(plot3, index2) {\n const update2 = () => {\n if (this.hasFieldInfo()) this.rasterize();\n };\n plot3.addAttributeListener(\"schemeColor\", update2);\n super.setPlot(plot3, index2);\n }\n requestQuery() {\n return this.requestTiles();\n }\n query(filter3 = []) {\n this._filter = filter3;\n return null;\n }\n tileQuery(extent4) {\n const { interpolate, pad: pad3, channels, densityMap, source } = this;\n const [[x06, x12], [y06, y12]] = extent4;\n const [nx, ny] = this.bins;\n const [x3, bx] = binExpr(this, \"x\", nx, [x06, x12], pad3);\n const [y3, by] = binExpr(this, \"y\", ny, [y06, y12], pad3);\n const bounds = pad3 ? [isBetween(bx, [+x06, +x12]), isBetween(by, [+y06, +y12])] : [lte(+x06, bx), lt(bx, +x12), lte(+y06, by), lt(by, +y12)];\n const q = Query.from(source.table).where(bounds);\n const groupby = this.groupby = [];\n const aggrMap = {};\n for (const c4 of channels) {\n if (Object.hasOwn(c4, \"field\")) {\n const { as, channel, field: field3 } = c4;\n if (field3.aggregate) {\n aggrMap[channel] = field3;\n densityMap[channel] = true;\n } else if (channel === \"weight\") {\n aggrMap.density = sum(field3);\n } else if (channel !== \"x\" && channel !== \"y\") {\n q.select({ [as]: field3 });\n groupby.push(as);\n }\n }\n }\n const aggr = this.aggr = Object.keys(aggrMap);\n if (aggrMap.density && aggr.length > 1) {\n throw new Error(\"Weight option can not be used with custom aggregates.\");\n }\n if (!aggr.length) {\n aggr.push(\"density\");\n aggrMap.density = count();\n }\n if (interpolate === \"linear\") {\n if (aggr.length > 1) {\n throw new Error(\"Linear binning not applicable to multiple aggregates.\");\n }\n if (!aggrMap.density) {\n throw new Error(\"Linear binning not applicable to custom aggregates.\");\n }\n return binLinear2d2(q, x3, y3, aggrMap.density, nx, groupby);\n } else {\n return bin2d2(q, x3, y3, aggrMap, nx, groupby);\n }\n }\n async requestTiles() {\n const mc = coordinator();\n if (this.prefetch) mc.cancel(this.prefetch);\n const { pad: pad3, tileX, tileY, origin: [tx, ty] } = this;\n const [m, n] = this.bins = this.binDimensions();\n const [x06, x12] = extentX(this, this._filter);\n const [y06, y12] = extentY(this, this._filter);\n const xspan = x12 - x06;\n const yspan = y12 - y06;\n const xx = Math.floor((x06 - tx) * (m - pad3) / xspan);\n const yy = Math.floor((y06 - ty) * (n - pad3) / yspan);\n const tileExtent = (i, j) => [\n [tx + i * xspan, tx + (i + 1) * xspan],\n [ty + j * yspan, ty + (j + 1) * yspan]\n ];\n const i0 = Math.floor((x06 - tx) / xspan);\n const i1 = tileX ? tileFloor((x12 - tx) / xspan) : i0;\n const j0 = Math.floor((y06 - ty) / yspan);\n const j1 = tileY ? tileFloor((y12 - ty) / yspan) : j0;\n const coords = [];\n for (let i = i0; i <= i1; ++i) {\n for (let j = j0; j <= j1; ++j) {\n coords.push([i, j]);\n }\n }\n const queries = coords.map(\n ([i, j]) => mc.query(this.tileQuery(tileExtent(i, j)))\n );\n const prefetchCoords = [];\n if (tileX) {\n for (let j = j0; j <= j1; ++j) {\n prefetchCoords.push([i1 + 1, j]);\n prefetchCoords.push([i0 - 1, j]);\n }\n }\n if (tileY) {\n const x07 = tileX ? i0 - 1 : i0;\n const x13 = tileX ? i1 + 1 : i1;\n for (let i = x07; i <= x13; ++i) {\n prefetchCoords.push([i, j1 + 1]);\n prefetchCoords.push([i, j0 - 1]);\n }\n }\n this.prefetch = prefetchCoords.map(\n ([i, j]) => mc.prefetch(this.tileQuery(tileExtent(i, j)))\n );\n const tiles = await Promise.all(queries);\n const density3 = processTiles(m, n, xx, yy, coords, tiles);\n this.grids0 = {\n numRows: density3.length,\n columns: { density: [density3] }\n };\n this.convolve().update();\n }\n convolve() {\n return super.convolve().rasterize();\n }\n rasterize() {\n const { bins: bins2, grids } = this;\n const [w, h] = bins2;\n const { numRows, columns } = grids;\n const { canvas, ctx, img } = imageData2(this, w, h);\n const { alpha, alphaProp, color: color3, colorProp } = rasterEncoding(this);\n const alphaData = columns[alphaProp] ?? [];\n const colorData = columns[colorProp] ?? [];\n const idx = numRows > 1 && colorProp && this.groupby?.includes(colorProp) ? permute2(colorData, this.plot.getAttribute(\"colorDomain\")) : indices(numRows);\n this.data = {\n numRows,\n columns: {\n src: Array.from({ length: numRows }, (_, i) => {\n color3?.(img.data, w, h, colorData[idx[i]]);\n alpha?.(img.data, w, h, alphaData[idx[i]]);\n ctx.putImageData(img, 0, 0);\n return canvas.toDataURL();\n })\n }\n };\n return this;\n }\n plotSpecs() {\n const { type: type2, plot: plot3, data: { numRows: length4, columns } } = this;\n const options = {\n src: columns.src,\n width: plot3.innerWidth(),\n height: plot3.innerHeight(),\n preserveAspectRatio: \"none\",\n imageRendering: this.channel(\"imageRendering\")?.value,\n frameAnchor: \"middle\"\n };\n return [{ type: type2, data: { length: length4 }, options }];\n }\n};\nfunction processTiles(m, n, x3, y3, coords, tiles) {\n const grid2 = new Float64Array(m * n);\n tiles.forEach((data, index2) => {\n const [i, j] = coords[index2];\n const tx = i * m - x3;\n const ty = j * n - y3;\n copy3(m, n, grid2, data, tx, ty);\n });\n return grid2;\n}\nfunction copy3(m, n, grid2, values2, tx, ty) {\n const num = values2.numRows;\n if (num === 0) return;\n const index2 = values2.getChild(\"index\").toArray();\n const value = values2.getChild(\"density\").toArray();\n for (let row = 0; row < num; ++row) {\n const idx = index2[row];\n const i = tx + idx % m;\n const j = ty + Math.floor(idx / m);\n if (0 <= i && i < m && 0 <= j && j < n) {\n grid2[i + j * m] = value[row];\n }\n }\n}\nfunction imageData2(mark2, w, h) {\n if (!mark2.image || mark2.image.w !== w || mark2.image.h !== h) {\n const canvas = createCanvas(w, h);\n const ctx = canvas.getContext(\"2d\", { willReadFrequently: true });\n const img = ctx.getImageData(0, 0, w, h);\n mark2.image = { canvas, ctx, img, w, h };\n }\n return mark2.image;\n}\nfunction bin2d2(q, xp, yp, aggs, xn, groupby) {\n return q.select({\n index: sql`FLOOR(${xp})::INTEGER + FLOOR(${yp})::INTEGER * ${xn}`,\n ...aggs\n }).groupby(\"index\", groupby);\n}\nfunction binLinear2d2(q, xp, yp, value, xn, groupby) {\n const w = value.column ? `* ${value.column}` : \"\";\n const subq = (i, w2) => q.clone().select({ xp, yp, i, w: w2 });\n const a2 = subq(\n sql`FLOOR(xp)::INTEGER + FLOOR(yp)::INTEGER * ${xn}`,\n sql`(FLOOR(xp)::INTEGER + 1 - xp) * (FLOOR(yp)::INTEGER + 1 - yp)${w}`\n );\n const b = subq(\n sql`FLOOR(xp)::INTEGER + (FLOOR(yp)::INTEGER + 1) * ${xn}`,\n sql`(FLOOR(xp)::INTEGER + 1 - xp) * (yp - FLOOR(yp)::INTEGER)${w}`\n );\n const c4 = subq(\n sql`FLOOR(xp)::INTEGER + 1 + FLOOR(yp)::INTEGER * ${xn}`,\n sql`(xp - FLOOR(xp)::INTEGER) * (FLOOR(yp)::INTEGER + 1 - yp)${w}`\n );\n const d = subq(\n sql`FLOOR(xp)::INTEGER + 1 + (FLOOR(yp)::INTEGER + 1) * ${xn}`,\n sql`(xp - FLOOR(xp)::INTEGER) * (yp - FLOOR(yp)::INTEGER)${w}`\n );\n return Query.from(Query.unionAll(a2, b, c4, d)).select({ index: \"i\", density: sum(\"w\") }, groupby).groupby(\"index\", groupby).having(neq(\"density\", 0));\n}\nfunction tileFloor(value) {\n const floored = Math.floor(value);\n return floored === value ? floored - 1 : floored;\n}\n\n// ../plot/src/marks/RegressionMark.js\nvar RegressionMark = class extends Mark2 {\n constructor(source, options) {\n const { ci = 0.95, precision = 4, ...channels } = options;\n super(\"line\", source, channels);\n const update2 = () => this.modelFit ? this.confidenceBand().update() : null;\n this.ci = handleParam(ci, (value) => {\n return this.ci = value, update2();\n });\n this.precision = handleParam(precision, (value) => {\n return this.precision = value, update2();\n });\n }\n query(filter3 = []) {\n const x3 = this.channelField(\"x\").as;\n const y3 = this.channelField(\"y\").as;\n const groupby = Array.from(new Set(\n [\"stroke\", \"z\", \"fx\", \"fy\"].flatMap((c4) => this.channelField(c4)?.as || [])\n ));\n return Query.from(super.query(filter3)).select({\n intercept: regrIntercept(y3, x3),\n slope: regrSlope(y3, x3),\n n: regrCount(y3, x3),\n ssy: regrSYY(y3, x3),\n ssx: regrSXX(y3, x3),\n xm: regrAvgX(y3, x3),\n x0: castDouble(min(x3).where(isNotNull(y3))),\n x1: castDouble(max(x3).where(isNotNull(y3)))\n }).select(groupby).groupby(groupby);\n }\n queryResult(data) {\n this.modelFit = toDataColumns(data);\n this.lineData = linePoints(this.modelFit);\n return this.confidenceBand();\n }\n confidenceBand() {\n const { ci, modelFit, precision, plot: plot3 } = this;\n const width2 = plot3.innerWidth();\n this.areaData = ci ? areaPoints(modelFit, ci, precision, width2) : null;\n return this;\n }\n plotSpecs() {\n const { lineData, areaData, channels, ci } = this;\n const lcols = lineData.columns;\n const acols = ci ? areaData.columns : {};\n const lopt = { x: lcols.x, y: lcols.y };\n const aopt = { x: acols.x, y1: acols.y1, y2: acols.y2, fillOpacity: 0.1 };\n for (const c4 of channels) {\n switch (c4.channel) {\n case \"x\":\n case \"y\":\n case \"fill\":\n break;\n case \"tip\":\n aopt.tip = channelOption(c4, acols);\n break;\n case \"stroke\":\n lopt.stroke = channelOption(c4, lcols);\n aopt.fill = channelOption(c4, acols);\n break;\n case \"strokeOpacity\":\n lopt.strokeOpacity = channelOption(c4, lcols);\n break;\n case \"fillOpacity\":\n aopt.fillOpacity = channelOption(c4, acols);\n break;\n default:\n lopt[c4.channel] = channelOption(c4, lcols);\n aopt[c4.channel] = channelOption(c4, acols);\n break;\n }\n }\n return [\n ...ci ? [{ type: \"areaY\", data: { length: areaData.numRows }, options: aopt }] : [],\n { type: \"line\", data: { length: lineData.numRows }, options: lopt }\n ];\n }\n};\nfunction concat(a2, b) {\n if (a2.concat) return a2.concat(b);\n const array4 = new a2.constructor(a2.length + b.length);\n array4.set(a2, 0);\n array4.set(b, a2.length);\n return array4;\n}\nfunction linePoints(fit2) {\n const { x0: x06 = [], x1: x12 = [], xm, intercept, slope, n, ssx, ssy, ...rest } = fit2.columns;\n const predict = (x4, i) => intercept[i] + x4 * slope[i];\n const x3 = concat(x06, x12);\n const y3 = concat(x06.map(predict), x12.map(predict));\n for (const name2 in rest) {\n rest[name2] = concat(rest[name2], rest[name2]);\n }\n return { numRows: x3.length, columns: { x: x3, y: y3, ...rest } };\n}\nfunction areaPoints(fit2, ci, precision, width2) {\n const len = fit2.numRows;\n const { x0: x06, x1: x12, xm, intercept, slope, n, ssx, ssy, ...rest } = fit2.columns;\n const other = Object.keys(rest);\n const columns = { x: [], y1: [], y2: [] };\n other.forEach((name2) => columns[name2] = []);\n for (let i = 0; i < len; ++i) {\n const pp = precision * (x12[i] - x06[i]) / width2;\n const t_sy = qt2((1 - ci) / 2, n[i] - 2) * Math.sqrt(ssy[i] / (n[i] - 2));\n range(x06[i], x12[i] - pp / 2, pp).concat(x12[i]).forEach((x3) => {\n const y3 = intercept[i] + x3 * slope[i];\n const ye = t_sy * Math.sqrt(1 / n[i] + (x3 - xm[i]) ** 2 / ssx[i]);\n columns.x.push(x3);\n columns.y1.push(y3 - ye);\n columns.y2.push(y3 + ye);\n other.forEach((name2) => columns[name2].push(rest[name2][i]));\n });\n }\n return { numRows: columns.x.length, columns };\n}\n\n// ../plot/src/interactors/util/to-kebab-case.js\nfunction toKebabCase(cc2) {\n const lc = cc2.toLowerCase();\n const n = cc2.length;\n let kc = \"\";\n for (let i = 0; i < n; ++i) {\n kc += (cc2[i] !== lc[i] ? \"-\" : \"\") + lc[i];\n }\n return kc;\n}\n\n// ../plot/src/interactors/util/sanitize-styles.js\nfunction sanitizeStyles(styles2) {\n const s2 = {};\n for (const name2 in styles2) {\n s2[toKebabCase(name2)] = styles2[name2];\n }\n return s2;\n}\n\n// ../plot/src/interactors/Highlight.js\nfunction configureMark(mark2) {\n const { channels } = mark2;\n const dims = /* @__PURE__ */ new Set();\n let ordered = false;\n let aggregate = false;\n for (const c4 of channels) {\n const { channel, field: field3, as } = c4;\n if (channel === \"orderby\") {\n ordered = true;\n } else if (field3) {\n if (field3.aggregate) {\n aggregate = true;\n } else {\n if (dims.has(as)) continue;\n dims.add(as);\n }\n }\n }\n if (!ordered && aggregate && dims.size) {\n mark2.channels.push({ channel: \"orderby\", value: Array.from(dims) });\n }\n return mark2;\n}\nvar Highlight = class {\n constructor(mark2, {\n selection: selection2,\n channels = {}\n }) {\n this.mark = configureMark(mark2);\n this.selection = selection2;\n const c4 = Object.entries(sanitizeStyles(channels));\n this.channels = c4.length ? c4 : [[\"opacity\", 0.2]];\n this.selection.addEventListener(\"value\", throttle(() => this.update()));\n }\n init(svg) {\n this.svg = svg;\n const values2 = this.values = [];\n const index2 = this.mark.index;\n const nodes = this.nodes = svg.querySelectorAll(`[data-index=\"${index2}\"] > *`);\n const { channels } = this;\n for (let i = 0; i < nodes.length; ++i) {\n const node = nodes[i];\n values2.push(channels.map((c4) => node.getAttribute(c4[0])));\n }\n return this.update();\n }\n async update() {\n const { svg, nodes, channels, values: values2, mark: mark2, selection: selection2 } = this;\n if (!svg) return;\n const test = await predicateFunction(mark2, selection2);\n for (let i = 0; i < nodes.length; ++i) {\n const node = nodes[i];\n const base = values2[i];\n const data = node.__data__;\n const t = test(Array.isArray(data) ? data[0] : data);\n for (let j = 0; j < channels.length; ++j) {\n const [attr, value] = channels[j];\n node.setAttribute(attr, t ? base[j] : value);\n }\n }\n }\n};\nasync function predicateFunction(mark2, selection2) {\n const pred = selection2?.predicate(mark2);\n if (!pred || pred.length === 0) {\n return () => true;\n }\n const filter3 = mark2.filterBy?.predicate(mark2, true);\n const s2 = { __: and(pred) };\n const q = mark2.query(filter3);\n (q.queries || [q]).forEach((q2) => {\n q2.groupby().length ? q2.select(s2) : q2.$select(s2);\n });\n const data = await mark2.coordinator.query(q);\n const v2 = data.getChild?.(\"__\");\n return !(data.numRows || data.length) ? () => false : v2 ? (i) => v2.at(i) : (i) => data[i].__;\n}\n\n// ../plot/src/interactors/util/brush.js\nfunction wrap2(brush3) {\n const brushOn = brush3.on;\n let enabled = true;\n function silence(callback) {\n enabled = false;\n callback();\n enabled = true;\n }\n brush3.reset = (...args) => {\n silence(() => brush3.clear(...args));\n };\n brush3.moveSilent = (...args) => {\n silence(() => brush3.move(...args));\n };\n brush3.on = (...args) => {\n if (args.length > 1 && args[1]) {\n const callback = args[1];\n args[1] = (...event) => enabled && callback(...event);\n }\n return brushOn(...args);\n };\n return brush3;\n}\nfunction brush2() {\n return wrap2(brush_default());\n}\nfunction brushX2() {\n return wrap2(brushX());\n}\nfunction brushY2() {\n return wrap2(brushY());\n}\n\n// ../plot/src/interactors/util/close-to.js\nvar EPS = 1e-12;\nfunction closeTo(a2, b) {\n return a2 === b || a2 && b && Math.abs(a2[0] - b[0]) < EPS && Math.abs(a2[1] - b[1]) < EPS || false;\n}\n\n// ../plot/src/interactors/util/get-field.js\nfunction getField(mark2, channel) {\n const field3 = mark2.channelField(channel)?.field;\n return field3?.basis || field3;\n}\n\n// ../plot/src/interactors/util/invert.js\nfunction invert(value, scale3, pixelSize = 1) {\n return scale3.invert(pixelSize * Math.floor(value / pixelSize));\n}\n\n// ../plot/src/interactors/util/patchScreenCTM.js\nfunction patchScreenCTM() {\n const node = this;\n const getScreenCTM = node.getScreenCTM;\n let memo2;\n node.getScreenCTM = () => {\n return node.isConnected ? memo2 = getScreenCTM.call(node) : memo2;\n };\n}\n\n// ../plot/src/interactors/Interval1D.js\nvar Interval1D = class {\n constructor(mark2, {\n channel,\n selection: selection2,\n field: field3 = void 0,\n pixelSize = 1,\n peers = true,\n brush: style2\n }) {\n this.mark = mark2;\n this.channel = channel;\n this.pixelSize = pixelSize || 1;\n this.selection = selection2;\n this.peers = peers;\n this.field = field3 || getField(mark2, channel);\n this.style = style2 && sanitizeStyles(style2);\n this.brush = channel === \"y\" ? brushY2() : brushX2();\n this.brush.on(\"brush end\", ({ selection: selection3 }) => this.publish(selection3));\n }\n reset() {\n this.value = void 0;\n if (this.g) this.brush.reset(this.g);\n }\n activate() {\n this.selection.activate(this.clause(this.value || [0, 1]));\n }\n publish(extent4) {\n let range3 = void 0;\n if (extent4) {\n range3 = extent4.map((v2) => invert(v2, this.scale, this.pixelSize)).sort((a2, b) => a2 - b);\n }\n if (!closeTo(range3, this.value)) {\n this.value = range3;\n this.g.call(this.brush.moveSilent, extent4);\n this.selection.update(this.clause(range3));\n }\n }\n clause(value) {\n const { mark: mark2, pixelSize, field: field3, scale: scale3 } = this;\n return clauseInterval(field3, value, {\n source: this,\n clients: this.peers ? mark2.plot.markSet : (/* @__PURE__ */ new Set()).add(mark2),\n scale: scale3,\n pixelSize\n });\n }\n init(svg, root2) {\n const { brush: brush3, channel, style: style2 } = this;\n this.scale = svg.scale(channel);\n const rx = svg.scale(\"x\").range;\n const ry = svg.scale(\"y\").range;\n brush3.extent([[min2(rx), min2(ry)], [max2(rx), max2(ry)]]);\n const range3 = this.value?.map(this.scale.apply).sort(ascending);\n const facets = select_default2(svg).selectAll('g[aria-label=\"facet\"]');\n root2 = facets.size() ? facets : select_default2(root2 ?? svg);\n this.g = root2.append(\"g\").attr(\"class\", `interval-${channel}`).each(patchScreenCTM).call(brush3).call(brush3.moveSilent, range3);\n if (style2) {\n const brushes = this.g.selectAll(\"rect.selection\");\n for (const name2 in style2) {\n brushes.attr(name2, style2[name2]);\n }\n }\n svg.addEventListener(\"pointerenter\", (evt) => {\n if (!evt.buttons) this.activate();\n });\n }\n};\n\n// ../plot/src/interactors/Interval2D.js\nvar Interval2D = class {\n constructor(mark2, {\n selection: selection2,\n xfield,\n yfield,\n pixelSize = 1,\n peers = true,\n brush: style2\n }) {\n this.mark = mark2;\n this.pixelSize = pixelSize || 1;\n this.selection = selection2;\n this.peers = peers;\n this.xfield = xfield || getField(mark2, \"x\");\n this.yfield = yfield || getField(mark2, \"y\");\n this.style = style2 && sanitizeStyles(style2);\n this.brush = brush2();\n this.brush.on(\"brush end\", ({ selection: selection3 }) => this.publish(selection3));\n }\n reset() {\n this.value = void 0;\n if (this.g) this.brush.reset(this.g);\n }\n activate() {\n this.selection.activate(this.clause(this.value || [[0, 1], [0, 1]]));\n }\n publish(extent4) {\n const { value, pixelSize, xscale, yscale } = this;\n let xr = void 0;\n let yr = void 0;\n if (extent4) {\n const [a2, b] = extent4;\n xr = [a2[0], b[0]].map((v2) => invert(v2, xscale, pixelSize)).sort(ascending);\n yr = [a2[1], b[1]].map((v2) => invert(v2, yscale, pixelSize)).sort(ascending);\n }\n if (!closeTo(xr, value?.[0]) || !closeTo(yr, value?.[1])) {\n this.value = extent4 ? [xr, yr] : void 0;\n this.g.call(this.brush.moveSilent, extent4);\n this.selection.update(this.clause(this.value));\n }\n }\n clause(value) {\n const { mark: mark2, pixelSize, xfield, yfield, xscale, yscale } = this;\n return clauseIntervals([xfield, yfield], value, {\n source: this,\n clients: this.peers ? mark2.plot.markSet : (/* @__PURE__ */ new Set()).add(mark2),\n scales: [xscale, yscale],\n pixelSize\n });\n }\n init(svg) {\n const { brush: brush3, style: style2 } = this;\n const xscale = this.xscale = svg.scale(\"x\");\n const yscale = this.yscale = svg.scale(\"y\");\n const rx = xscale.range;\n const ry = yscale.range;\n brush3.extent([[min2(rx), min2(ry)], [max2(rx), max2(ry)]]);\n const facets = select_default2(svg).selectAll('g[aria-label=\"facet\"]');\n const root2 = facets.size() ? facets : select_default2(svg);\n this.g = root2.append(\"g\").attr(\"class\", `interval-xy`).each(patchScreenCTM).call(brush3);\n if (style2) {\n const brushes = this.g.selectAll(\"rect.selection\");\n for (const name2 in style2) {\n brushes.attr(name2, style2[name2]);\n }\n }\n if (this.value) {\n const [x12, x22] = this.value[0].map(xscale.apply).sort(ascending);\n const [y12, y22] = this.value[1].map(yscale.apply).sort(ascending);\n this.g.call(brush3.moveSilent, [[x12, y12], [x22, y22]]);\n }\n svg.addEventListener(\"pointerenter\", (evt) => {\n if (!evt.buttons) this.activate();\n });\n }\n};\n\n// ../plot/src/interactors/Nearest.js\nvar Nearest = class {\n constructor(mark2, {\n selection: selection2,\n pointer: pointer2,\n channels,\n fields,\n maxRadius = 40\n }) {\n this.mark = mark2;\n this.selection = selection2;\n this.clients = (/* @__PURE__ */ new Set()).add(mark2);\n this.pointer = pointer2;\n this.channels = channels || (pointer2 === \"x\" ? [\"x\"] : pointer2 === \"y\" ? [\"y\"] : [\"x\", \"y\"]);\n this.fields = fields || this.channels.map((c4) => getField(mark2, [c4]));\n this.maxRadius = maxRadius;\n this.valueIndex = -1;\n }\n clause(value) {\n const { clients, fields } = this;\n const opt = { source: this, clients };\n return fields.length > 1 ? clausePoints(fields, value ? [value] : value, opt) : clausePoint(fields[0], value?.[0], opt);\n }\n init(svg) {\n const that = this;\n const { mark: mark2, channels, selection: selection2, maxRadius } = this;\n const { data: { columns } } = mark2;\n const keys = channels.map((c4) => mark2.channelField(c4).as);\n const param = !isSelection(selection2);\n const facets = select_default2(svg).selectAll('g[aria-label=\"facet\"]');\n const root2 = facets.size() ? facets : select_default2(svg);\n const xscale = svg.scale(\"x\").apply;\n const yscale = svg.scale(\"y\").apply;\n const X3 = Array.from(columns[mark2.channelField(\"x\").as], xscale);\n const Y3 = Array.from(columns[mark2.channelField(\"y\").as], yscale);\n const sx = this.pointer === \"y\" ? 0.01 : 1;\n const sy = this.pointer === \"x\" ? 0.01 : 1;\n root2.on(\"pointerenter pointerdown pointermove\", function(evt) {\n const [px, py] = pointer_default(evt, this);\n const i = findNearest(X3, Y3, px, py, sx, sy, maxRadius);\n if (i !== this.valueIndex) {\n this.valueIndex = i;\n const v2 = i < 0 ? void 0 : keys.map((k2) => columns[k2][i]);\n selection2.update(\n // provide value for param, clause for selection\n param ? !v2 || v2.length > 1 ? v2 : v2[0] : that.clause(v2)\n );\n }\n });\n if (param) return;\n root2.on(\"pointerleave\", () => {\n selection2.update(that.clause(void 0));\n });\n svg.addEventListener(\"pointerenter\", (evt) => {\n if (!evt.buttons) {\n const v2 = this.channels.map(() => 0);\n selection2.activate(this.clause(v2));\n }\n });\n }\n};\nfunction findNearest(x3, y3, px, py, sx, sy, maxRadius) {\n let dist2 = maxRadius * maxRadius;\n let nearest2 = -1;\n for (let i = 0; i < x3.length; ++i) {\n const dx = sx * (x3[i] - px);\n const dy = sy * (y3[i] - py);\n const dd = dx * dx + dy * dy;\n if (dd <= dist2) {\n dist2 = dd;\n nearest2 = i;\n }\n }\n return nearest2;\n}\n\n// ../plot/src/interactors/PanZoom.js\nvar asc = (a2, b) => a2 - b;\nvar PanZoom = class {\n constructor(mark2, {\n x: x3 = new Selection(),\n y: y3 = new Selection(),\n xfield,\n yfield,\n zoom: zoom2 = true,\n panx = true,\n pany = true\n }) {\n this.mark = mark2;\n this.xsel = x3;\n this.ysel = y3;\n this.xfield = xfield || getField(mark2, \"x\");\n this.yfield = yfield || getField(mark2, \"y\");\n this.zoom = extent3(zoom2, [0, Infinity], [1, 1]);\n this.panx = this.xsel && panx;\n this.pany = this.ysel && pany;\n const { plot: plot3 } = mark2;\n if (panx) {\n this.xsel.addEventListener(\"value\", (value) => {\n if (plot3.setAttribute(\"xDomain\", value)) plot3.update();\n });\n }\n if (pany) {\n this.ysel.addEventListener(\"value\", (value) => {\n if (plot3.setAttribute(\"yDomain\", value)) plot3.update();\n });\n }\n }\n publish(transform3) {\n if (this.panx) {\n const xdom = rescaleX(transform3, this.xscale);\n this.xsel.update(this.clause(xdom, this.xfield, this.xscale));\n }\n if (this.pany) {\n const ydom = rescaleY(transform3, this.yscale);\n this.ysel.update(this.clause(ydom, this.yfield, this.yscale));\n }\n }\n clause(value, field3, scale3) {\n return clauseInterval(field3, value, {\n source: this,\n clients: this.mark.plot.markSet,\n scale: scale3\n });\n }\n init(svg) {\n this.svg = svg;\n if (this.initialized) return;\n else this.initialized = true;\n const { panx, pany, mark: { plot: { element } }, xsel, ysel } = this;\n this.xscale = svg.scale(\"x\");\n this.yscale = svg.scale(\"y\");\n const rx = this.xscale.range.slice().sort(asc);\n const ry = this.yscale.range.slice().sort(asc);\n const tx = extent3(panx, [-Infinity, Infinity], rx);\n const ty = extent3(pany, [-Infinity, Infinity], ry);\n const z = zoom_default2().extent([[rx[0], ry[0]], [rx[1], ry[1]]]).scaleExtent(this.zoom).translateExtent([[tx[0], ty[0]], [tx[1], ty[1]]]).on(\"start\", () => {\n this.xscale = this.svg.scale(\"x\");\n this.yscale = this.svg.scale(\"y\");\n }).on(\"end\", () => element.__zoom = new Transform2(1, 0, 0)).on(\"zoom\", ({ transform: transform3 }) => this.publish(transform3));\n select_default2(element).call(z);\n if (panx || pany) {\n let enter = false;\n element.addEventListener(\"pointerenter\", (evt) => {\n if (enter) return;\n else enter = true;\n if (evt.buttons) return;\n if (panx) {\n const { xscale, xfield } = this;\n xsel.activate(this.clause(xscale.domain, xfield, xscale));\n }\n if (pany) {\n const { yscale, yfield } = this;\n ysel.activate(this.clause(yscale.domain, yfield, yscale));\n }\n });\n element.addEventListener(\"pointerleave\", () => enter = false);\n }\n }\n};\nfunction extent3(ext, defaultTrue, defaultFalse) {\n return ext ? Array.isArray(ext) ? ext : defaultTrue : defaultFalse;\n}\nfunction rescaleX(transform3, scale3) {\n return scale3.range.map(transform3.invertX, transform3).map(scale3.invert, scale3);\n}\nfunction rescaleY(transform3, scale3) {\n return scale3.range.map(transform3.invertY, transform3).map(scale3.invert, scale3);\n}\n\n// ../plot/src/interactors/Toggle.js\nvar Toggle = class {\n /**\n * @param {*} mark The mark to interact with.\n * @param {*} options The interactor options.\n */\n constructor(mark2, {\n selection: selection2,\n channels,\n peers = true\n }) {\n this.value = null;\n this.mark = mark2;\n this.selection = selection2;\n this.peers = peers;\n const fields = this.fields = [];\n const as = this.as = [];\n channels.forEach((c4) => {\n const q = c4 === \"color\" ? [\"color\", \"fill\", \"stroke\"] : c4 === \"x\" ? [\"x\", \"x1\", \"x2\"] : c4 === \"y\" ? [\"y\", \"y1\", \"y2\"] : [c4];\n for (let i = 0; i < q.length; ++i) {\n const f = mark2.channelField(q[i], { exact: true });\n if (f) {\n fields.push(f.field?.basis || f.field);\n as.push(f.as);\n return;\n }\n }\n throw new Error(`Missing channel: ${c4}`);\n });\n }\n clause(value) {\n const { fields, mark: mark2 } = this;\n return clausePoints(fields, value, {\n source: this,\n clients: this.peers ? mark2.plot.markSet : (/* @__PURE__ */ new Set()).add(mark2)\n });\n }\n init(svg, selector, accessor) {\n const { mark: mark2, as, selection: selection2 } = this;\n const { data: { columns = {} } = {} } = mark2;\n accessor ??= (target) => as.map((name2) => {\n const data = target.__data__;\n return columns[name2][Array.isArray(data) ? data[0] : data];\n });\n selector ??= `[data-index=\"${mark2.index}\"]`;\n const groups2 = new Set(svg.querySelectorAll(selector));\n svg.addEventListener(\"pointerdown\", (evt) => {\n const state = selection2.single ? selection2.value : this.value;\n const target = evt.target;\n let value = null;\n if (isTargetElement(groups2, target)) {\n const point6 = accessor(target);\n if ((evt.shiftKey || evt.metaKey) && state?.length) {\n value = state.filter((s2) => neq2(s2, point6));\n if (value.length === state.length) value.push(point6);\n } else if (state?.length === 1 && !neq2(state[0], point6)) {\n value = null;\n } else {\n value = [point6];\n }\n }\n this.value = value;\n if (neqSome(state, value)) {\n selection2.update(this.clause(value));\n }\n });\n svg.addEventListener(\"pointerenter\", (evt) => {\n if (evt.buttons) return;\n this.selection.activate(this.clause([this.fields.map(() => 0)]));\n });\n }\n};\nfunction isTargetElement(groups2, node) {\n return groups2.has(node) || groups2.has(node.parentNode) || groups2.has(node.parentNode?.parentNode);\n}\nfunction neqSome(a2, b) {\n return a2 == null || b == null ? a2 != null || b != null : a2.length !== b.length || a2.some((x3, i) => neq2(x3, b[i]));\n}\nfunction neq2(a2, b) {\n const n = a2.length;\n if (b.length !== n) return true;\n for (let i = 0; i < n; ++i) {\n if (a2[i] !== b[i]) return true;\n }\n return false;\n}\n\n// ../plot/src/legend.js\nvar TOGGLE_SELECTOR = \":scope > div, :scope > span\";\nvar SWATCH = \"swatch\";\nvar RAMP = \"ramp\";\nvar Legend = class {\n constructor(channel, options) {\n const { as, field: field3, ...rest } = options;\n this.channel = channel;\n this.options = rest;\n this.type = null;\n this.handler = null;\n this.selection = as;\n this.field = field3;\n this.legend = null;\n this.element = document.createElement(\"div\");\n this.element.setAttribute(\"class\", \"legend\");\n Object.defineProperty(this.element, \"value\", { value: this });\n }\n setPlot(plot3) {\n this.plot = plot3;\n }\n init(svg) {\n const el = createLegend(this, svg);\n this.element.replaceChildren(el);\n return this.element;\n }\n update() {\n if (!this.legend) return;\n const { selection: selection2, handler } = this;\n const { single, value } = selection2;\n const vals = single ? value : selection2.valueFor(handler);\n const curr = vals && vals.length ? new Set(vals.map((v2) => v2[0])) : null;\n const nodes = this.legend.querySelectorAll(TOGGLE_SELECTOR);\n for (const node of nodes) {\n const selected = curr ? curr.has(node.__data__) : true;\n node.style.opacity = selected ? 1 : 0.2;\n }\n }\n};\nfunction createLegend(legend3, svg) {\n const { channel, plot: plot3, selection: selection2 } = legend3;\n const scale3 = svg.scale(channel);\n const type2 = scale3.type === \"ordinal\" ? SWATCH : RAMP;\n const options = {\n label: plot3.getAttribute(`${channel}Label`) ?? null,\n ...legend3.options\n };\n const opt = type2 === SWATCH ? options : options.label ? { tickSize: 2, ...options } : { tickSize: 2, marginTop: 1, height: 29, ...options };\n const el = svg.legend(channel, opt);\n legend3.legend = el;\n let interactive = !!selection2;\n if (interactive && type2 === RAMP) {\n const width2 = opt.width ?? 240;\n const spatial = spatialScale(scale3, width2);\n if (spatial) {\n el.scale = function(type3) {\n return type3 === \"x\" ? { range: [0, width2] } : type3 === \"y\" ? { range: [-10, 0] } : type3 === channel ? spatial : void 0;\n };\n } else {\n interactive = false;\n }\n }\n if (interactive) {\n const handler = getInteractor(legend3, type2);\n if (type2 === SWATCH) {\n handler.init(el, TOGGLE_SELECTOR, (el2) => [el2.__data__]);\n legend3.update();\n } else {\n handler.init(el, el.querySelector(\"g:last-of-type\"));\n }\n }\n return el;\n}\nfunction getInteractor(legend3, type2) {\n const { channel, handler, selection: selection2 } = legend3;\n if (handler) return handler;\n const mark2 = interactorMark(legend3);\n if (type2 === SWATCH) {\n legend3.handler = new Toggle(mark2, {\n selection: selection2,\n channels: [channel],\n peers: false\n });\n selection2.addEventListener(\"value\", () => legend3.update());\n } else {\n legend3.handler = new Interval1D(mark2, {\n selection: selection2,\n channel,\n brush: { fill: \"none\", stroke: \"currentColor\" },\n peers: false\n });\n }\n return legend3.handler;\n}\nfunction interactorMark(legend3) {\n const { channel, plot: plot3 } = legend3;\n const field3 = legend3.field ?? findField(plot3.marks, channel) ?? \"value\";\n if (field3) {\n const f = { field: field3 };\n return { plot: plot3, channelField: (c4) => channel === c4 ? f : void 0 };\n }\n}\nfunction findField(marks2, channel) {\n const channels = channel === \"color\" ? [\"fill\", \"stroke\"] : channel === \"opacity\" ? [\"opacity\", \"fillOpacity\", \"strokeOpacity\"] : null;\n if (channels == null) return null;\n for (let i = marks2.length - 1; i > -1; --i) {\n for (const c4 of channels) {\n const field3 = marks2[i].channelField(c4, { exact: true });\n if (field3) return field3.field;\n }\n }\n return null;\n}\nfunction spatialScale(sourceScale, width2) {\n const { apply: apply2, invert: invert2, interpolate, ...rest } = sourceScale;\n let src = sourceScale.type;\n if (src.startsWith(\"diverging-\")) src = src.slice(11);\n let type2;\n switch (src) {\n case \"log\":\n case \"pow\":\n case \"sqrt\":\n case \"symlog\":\n type2 = src;\n break;\n case \"threshold\":\n case \"quantize\":\n case \"quantile\":\n console.warn(`Legends do not yet support ${src} scales.`);\n return null;\n default:\n type2 = \"linear\";\n }\n return scale2({ x: { ...rest, type: type2, range: [0, width2] } });\n}\n\n// ../plot/src/transforms/bin-step.js\nfunction binStep(span, steps, minstep = 0, logb = Math.LN10) {\n let v2;\n const level = Math.ceil(Math.log(steps) / logb);\n let step = Math.max(\n minstep,\n Math.pow(10, Math.round(Math.log(span) / logb) - level)\n );\n while (Math.ceil(span / step) > steps) {\n step *= 10;\n }\n const div = [5, 2];\n for (let i = 0, n = div.length; i < n; ++i) {\n v2 = step / div[i];\n if (v2 >= minstep && span / v2 <= steps) step = v2;\n }\n return step;\n}\nfunction bins(min5, max4, options) {\n let { step, steps, minstep = 0, nice: nice3 = true } = options;\n if (nice3 !== false) {\n const span = max4 - min5;\n const logb = Math.LN10;\n step = step || binStep(span, steps || 25, minstep, logb);\n let v2 = Math.log(step);\n const precision = v2 >= 0 ? 0 : ~~(-v2 / logb) + 1;\n const eps2 = Math.pow(10, -precision - 1);\n v2 = Math.floor(min5 / step + eps2) * step;\n min5 = min5 < v2 ? v2 - step : v2;\n max4 = Math.ceil(max4 / step) * step;\n steps = Math.round((max4 - min5) / step);\n }\n return { min: min5, max: max4, steps };\n}\n\n// ../plot/src/transforms/time-interval.js\nvar YEAR = \"year\";\nvar MONTH = \"month\";\nvar DAY = \"day\";\nvar HOUR = \"hour\";\nvar MINUTE = \"minute\";\nvar SECOND = \"second\";\nvar MILLISECOND = \"millisecond\";\nvar durationSecond3 = 1e3;\nvar durationMinute3 = durationSecond3 * 60;\nvar durationHour3 = durationMinute3 * 60;\nvar durationDay3 = durationHour3 * 24;\nvar durationWeek3 = durationDay3 * 7;\nvar durationMonth3 = durationDay3 * 30;\nvar durationYear3 = durationDay3 * 365;\nvar intervals = [\n [SECOND, 1, durationSecond3],\n [SECOND, 5, 5 * durationSecond3],\n [SECOND, 15, 15 * durationSecond3],\n [SECOND, 30, 30 * durationSecond3],\n [MINUTE, 1, durationMinute3],\n [MINUTE, 5, 5 * durationMinute3],\n [MINUTE, 15, 15 * durationMinute3],\n [MINUTE, 30, 30 * durationMinute3],\n [HOUR, 1, durationHour3],\n [HOUR, 3, 3 * durationHour3],\n [HOUR, 6, 6 * durationHour3],\n [HOUR, 12, 12 * durationHour3],\n [DAY, 1, durationDay3],\n [DAY, 7, durationWeek3],\n [MONTH, 1, durationMonth3],\n [MONTH, 3, 3 * durationMonth3],\n [YEAR, 1, durationYear3]\n];\nfunction timeInterval3(min5, max4, steps) {\n const span = max4 - min5;\n const target = span / steps;\n let i = bisector((i2) => i2[2]).right(intervals, target);\n if (i === intervals.length) {\n return { interval: YEAR, step: binStep(span / durationYear3, steps) };\n } else if (i) {\n i = intervals[target / intervals[i - 1][2] < intervals[i][2] / target ? i - 1 : i];\n return { interval: i[0], step: i[1] };\n } else {\n return { interval: MILLISECOND, step: binStep(span, steps, 1) };\n }\n}\n\n// ../plot/src/transforms/bin.js\nvar EXTENT = /* @__PURE__ */ new Set([\n \"rectY-x\",\n \"rectX-y\",\n \"rect-x\",\n \"rect-y\",\n \"ruleY-x\",\n \"ruleX-y\"\n]);\nfunction hasExtent(mark2, channel) {\n return EXTENT.has(`${mark2.type}-${channel}`);\n}\nfunction bin2(field3, options = {}) {\n const fn = (mark2, channel) => {\n if (hasExtent(mark2, channel)) {\n return {\n [`${channel}1`]: binField(mark2, channel, field3, options),\n [`${channel}2`]: binField(mark2, channel, field3, { ...options, offset: 1 })\n };\n } else {\n return {\n [channel]: binField(mark2, channel, field3, options)\n };\n }\n };\n fn[Transform] = true;\n return fn;\n}\nfunction binField(mark2, channel, column3, options) {\n return {\n column: column3,\n label: column3,\n get columns() {\n return [column3];\n },\n get basis() {\n return column3;\n },\n get stats() {\n return { column: column3, stats: [\"min\", \"max\"] };\n },\n toString() {\n const { type: type2, min: min5, max: max4 } = mark2.channelField(channel);\n const { interval: i, steps, offset: offset2 = 0 } = options;\n const interval3 = i ?? (type2 === \"date\" || hasTimeScale(mark2, channel) ? \"date\" : \"number\");\n if (interval3 === \"number\") {\n const { apply: apply2, sqlApply, sqlInvert } = channelScale(mark2, channel);\n const b = bins(apply2(min5), apply2(max4), options);\n const col = sqlApply(column3);\n const base = b.min === 0 ? col : `(${col} - ${b.min})`;\n const alpha = `${(b.max - b.min) / b.steps}::DOUBLE`;\n const off = offset2 ? `${offset2} + ` : \"\";\n const expr = `${b.min} + ${alpha} * (${off}FLOOR(${base} / ${alpha}))`;\n return `${sqlInvert(expr)}`;\n } else {\n const { interval: unit3, step = 1 } = interval3 === \"date\" ? timeInterval3(min5, max4, steps || 40) : options;\n const off = offset2 ? ` + INTERVAL ${offset2 * step} ${unit3}` : \"\";\n return `(${dateBin(column3, unit3, step)}${off})`;\n }\n }\n };\n}\nfunction hasTimeScale(mark2, channel) {\n const scale3 = mark2.plot.getAttribute(`${channel}Scale`);\n return scale3 === \"utc\" || scale3 === \"time\";\n}\n\n// ../inputs/src/Menu.js\nvar isObject2 = (v2) => {\n return v2 && typeof v2 === \"object\" && !Array.isArray(v2);\n};\nvar Menu = class extends MosaicClient {\n /**\n * Create a new menu input.\n * @param {object} [options] Options object\n * @param {HTMLElement} [options.element] The parent DOM element in which to\n * place the menu elements. If undefined, a new `div` element is created.\n * @param {Selection} [options.filterBy] A selection to filter the database\n * table indicated by the *from* option.\n * @param {Param} [options.as] The output param or selection. A selection\n * clause is added for the currently selected menu option.\n * @param {string} [options.field] The database column name to use within\n * generated selection clause predicates. Defaults to the *column* option.\n * @param {(any | { value: any, label?: string })[]} [options.options] An\n * array of menu options, as literal values or option objects. Option\n * objects have a `value` property and an optional `label` property. If no\n * label or *format* function is provided, the string-coerced value is used.\n * @param {(value: any) => string} [options.format] A format function that\n * takes an option value as input and generates a string label. The format\n * function is not applied when an explicit label is provided in an option\n * object.\n * @param {*} [options.value] The initial selected menu value.\n * @param {string} [options.from] The name of a database table to use as a data\n * source for this widget. Used in conjunction with the *column* option.\n * @param {string} [options.column] The name of a database column from which\n * to pull menu options. The unique column values are used as menu options.\n * Used in conjunction with the *from* option.\n * @param {string} [options.label] A text label for this input.\n */\n constructor({\n element,\n filterBy,\n from: from2,\n column: column3,\n label: label2 = column3,\n format: format3 = (x3) => x3,\n // TODO\n options,\n value,\n field: field3 = column3,\n as\n } = {}) {\n super(filterBy);\n this.from = from2;\n this.column = column3;\n this.format = format3;\n this.field = field3;\n const selection2 = this.selection = as;\n this.element = element ?? document.createElement(\"div\");\n this.element.setAttribute(\"class\", \"input\");\n Object.defineProperty(this.element, \"value\", { value: this });\n const lab3 = document.createElement(\"label\");\n lab3.innerText = label2 || column3;\n this.element.appendChild(lab3);\n this.select = document.createElement(\"select\");\n this.element.appendChild(this.select);\n if (options) {\n this.data = options.map((value2) => isObject2(value2) ? value2 : { value: value2 });\n this.selectedValue(value ?? \"\");\n this.update();\n }\n if (selection2) {\n const isParam2 = !isSelection(selection2);\n if (value != null && (!isParam2 || selection2.value === void 0)) {\n this.publish(value);\n }\n this.select.addEventListener(\"input\", () => {\n this.publish(this.selectedValue() ?? null);\n });\n if (isParam2) {\n this.selection.addEventListener(\"value\", (value2) => {\n if (value2 !== this.select.value) {\n this.selectedValue(value2);\n }\n });\n }\n }\n }\n selectedValue(value) {\n if (arguments.length === 0) {\n const index2 = this.select.selectedIndex;\n return this.data[index2].value;\n } else {\n const index2 = this.data?.findIndex((opt) => opt.value === value);\n if (index2 >= 0) {\n this.select.selectedIndex = index2;\n } else {\n this.select.value = String(value);\n }\n }\n }\n reset() {\n this.select.selectedIndex = this.from ? 0 : -1;\n }\n publish(value) {\n const { selection: selection2, field: field3 } = this;\n if (isSelection(selection2)) {\n if (value === \"\") value = void 0;\n const clause = clausePoint(field3, value, { source: this });\n selection2.update(clause);\n } else if (isParam(selection2)) {\n selection2.update(value);\n }\n }\n query(filter3 = []) {\n const { from: from2, column: column3 } = this;\n if (!from2) return null;\n return Query.from(from2).select({ value: column3 }).distinct().where(filter3).orderby(column3);\n }\n queryResult(data) {\n this.data = [{ value: \"\", label: \"All\" }, ...data];\n return this;\n }\n update() {\n const { data, format: format3, select: select2, selection: selection2 } = this;\n select2.replaceChildren();\n for (const { value, label: label2 } of data) {\n const opt = document.createElement(\"option\");\n opt.setAttribute(\"value\", value);\n opt.innerText = label2 ?? format3(value);\n this.select.appendChild(opt);\n }\n if (selection2) {\n const value = isSelection(selection2) ? selection2.valueFor(this) : selection2.value;\n this.selectedValue(value ?? \"\");\n }\n return this;\n }\n};\n\n// ../inputs/src/Search.js\nvar _id = 0;\nvar Search = class extends MosaicClient {\n /**\n * Create a new text search input.\n * @param {object} [options] Options object\n * @param {HTMLElement} [options.element] The parent DOM element in which to\n * place the search elements. If undefined, a new `div` element is created.\n * @param {Selection} [options.filterBy] A selection to filter the database\n * table indicated by the *from* option.\n * @param {Param} [options.as] The output param or selection. A selection\n * clause is added based on the current text search query.\n * @param {string} [options.field] The database column name to use within\n * generated selection clause predicates. Defaults to the *column* option.\n * @param {'contains' | 'prefix' | 'suffix' | 'regexp'} [options.type] The\n * type of text search query to perform. One of:\n * - `\"contains\"` (default): the query string may appear anywhere in the text\n * - `\"prefix\"`: the query string must appear at the start of the text\n * - `\"suffix\"`: the query string must appear at the end of the text\n * - `\"regexp\"`: the query string is a regular expression the text must match\n * @param {string} [options.from] The name of a database table to use as an\n * autocomplete data source for this widget. Used in conjunction with the\n * *column* option.\n * @param {string} [options.column] The name of a database column from which\n * to pull valid search results. The unique column values are used as search\n * autocomplete values. Used in conjunction with the *from* option.\n * @param {string} [options.label] A text label for this input.\n */\n constructor({\n element,\n filterBy,\n from: from2,\n column: column3,\n label: label2,\n type: type2 = \"contains\",\n field: field3 = column3,\n as\n } = {}) {\n super(filterBy);\n this.id = \"search_\" + ++_id;\n this.type = type2;\n this.from = from2;\n this.column = column3;\n this.selection = as;\n this.field = field3;\n this.element = element ?? document.createElement(\"div\");\n this.element.setAttribute(\"class\", \"input\");\n Object.defineProperty(this.element, \"value\", { value: this });\n if (label2) {\n const lab3 = document.createElement(\"label\");\n lab3.setAttribute(\"for\", this.id);\n lab3.innerText = label2;\n this.element.appendChild(lab3);\n }\n this.searchbox = document.createElement(\"input\");\n this.searchbox.setAttribute(\"id\", this.id);\n this.searchbox.setAttribute(\"type\", \"text\");\n this.searchbox.setAttribute(\"placeholder\", \"Query\");\n this.element.appendChild(this.searchbox);\n if (this.selection) {\n this.searchbox.addEventListener(\"input\", () => {\n this.publish(this.searchbox.value || null);\n });\n if (!isSelection(this.selection)) {\n this.selection.addEventListener(\"value\", (value) => {\n if (value !== this.searchbox.value) {\n this.searchbox.value = value;\n }\n });\n }\n }\n }\n reset() {\n this.searchbox.value = \"\";\n }\n publish(value) {\n const { selection: selection2, field: field3, type: type2 } = this;\n if (isSelection(selection2)) {\n const clause = clauseMatch(field3, value, { source: this, method: type2 });\n selection2.update(clause);\n } else if (isParam(selection2)) {\n selection2.update(value);\n }\n }\n query(filter3 = []) {\n const { from: from2, column: column3 } = this;\n if (!from2) return null;\n return Query.from(from2).select({ list: column3 }).distinct().where(filter3);\n }\n queryResult(data) {\n this.data = data;\n return this;\n }\n update() {\n const list2 = document.createElement(\"datalist\");\n const id2 = `${this.id}_list`;\n list2.setAttribute(\"id\", id2);\n for (const d of this.data) {\n const opt = document.createElement(\"option\");\n opt.setAttribute(\"value\", d.list);\n list2.append(opt);\n }\n if (this.datalist) this.datalist.remove();\n this.element.appendChild(this.datalist = list2);\n this.searchbox.setAttribute(\"list\", id2);\n return this;\n }\n};\n\n// ../inputs/src/Slider.js\nvar _id2 = 0;\nvar Slider = class extends MosaicClient {\n /**\n * Create a new slider input.\n * @param {object} [options] Options object\n * @param {HTMLElement} [options.element] The parent DOM element in which to\n * place the slider elements. If undefined, a new `div` element is created.\n * @param {Selection} [options.filterBy] A selection to filter the database\n * table indicated by the *from* option.\n * @param {Param} [options.as] The output param or selection. A selection\n * clause is added based on the currently selected slider option.\n * @param {string} [options.field] The database column name to use within\n * generated selection clause predicates. Defaults to the *column* option.\n * @param {'point' | 'interval'} [options.select] The type of selection clause\n * predicate to generate if the **as** option is a Selection. If `'point'`\n * (the default), the selection predicate is an equality check for the slider\n * value. If `'interval'`, the predicate checks an interval from the minimum\n * to the current slider value.\n * @param {number} [options.min] The minimum slider value.\n * @param {number} [options.max] The maximum slider value.\n * @param {number} [options.step] The slider step, the amount to increment\n * between consecutive values.\n * @param {number} [options.value] The initial slider value.\n * @param {string} [options.from] The name of a database table to use as a data\n * source for this widget. Used in conjunction with the *column* option.\n * The minimum and maximum values of the column determine the slider range.\n * @param {string} [options.column] The name of a database column whose values\n * determine the slider range. Used in conjunction with the *from* option.\n * The minimum and maximum values of the column determine the slider range.\n * @param {string} [options.label] A text label for this input.\n * @param {number} [options.width] The width of the slider in screen pixels.\n */\n constructor({\n element,\n filterBy,\n as,\n min: min5,\n max: max4,\n step,\n from: from2,\n column: column3,\n label: label2 = column3,\n value = as?.value,\n select: select2 = \"point\",\n field: field3 = column3,\n width: width2\n } = {}) {\n super(filterBy);\n this.id = \"slider_\" + ++_id2;\n this.from = from2;\n this.column = column3 || \"value\";\n this.selection = as;\n this.selectionType = select2;\n this.field = field3;\n this.min = min5;\n this.max = max4;\n this.step = step;\n this.element = element || document.createElement(\"div\");\n this.element.setAttribute(\"class\", \"input\");\n Object.defineProperty(this.element, \"value\", { value: this });\n if (label2) {\n const desc2 = document.createElement(\"label\");\n desc2.setAttribute(\"for\", this.id);\n desc2.innerText = label2;\n this.element.appendChild(desc2);\n }\n this.slider = document.createElement(\"input\");\n this.slider.setAttribute(\"id\", this.id);\n this.slider.setAttribute(\"type\", \"range\");\n if (width2 != null) this.slider.style.width = `${+width2}px`;\n if (min5 != null) this.slider.setAttribute(\"min\", `${min5}`);\n if (max4 != null) this.slider.setAttribute(\"max\", `${max4}`);\n if (step != null) this.slider.setAttribute(\"step\", `${step}`);\n this.element.appendChild(this.slider);\n this.curval = document.createElement(\"label\");\n this.curval.setAttribute(\"for\", this.id);\n this.curval.setAttribute(\"class\", \"value\");\n this.element.appendChild(this.curval);\n if (value != null) {\n this.slider.setAttribute(\"value\", `${value}`);\n if (this.selection?.value === void 0) this.publish(value);\n }\n this.curval.innerText = this.slider.value;\n this.slider.addEventListener(\"input\", () => {\n const { value: value2 } = this.slider;\n this.curval.innerText = value2;\n if (this.selection) this.publish(+value2);\n });\n if (this.selection && !isSelection(this.selection)) {\n this.selection.addEventListener(\"value\", (value2) => {\n if (value2 !== +this.slider.value) {\n this.slider.value = value2;\n this.curval.innerText = value2;\n }\n });\n }\n }\n query(filter3 = []) {\n const { from: from2, column: column3 } = this;\n if (!from2 || this.min != null && this.max != null) return null;\n return Query.select({ min: min(column3), max: max(column3) }).from(from2).where(filter3);\n }\n queryResult(data) {\n const { min: min5, max: max4 } = Array.from(data)[0];\n if (this.min == null) {\n this.min = min5;\n this.slider.setAttribute(\"min\", `${min5}`);\n }\n if (this.max == null) {\n this.max = max4;\n this.slider.setAttribute(\"max\", `${max4}`);\n }\n if (this.step == null) {\n this.step = (max4 - min5) / 500;\n this.slider.setAttribute(\"step\", `${this.step}`);\n }\n return this;\n }\n publish(value) {\n const { field: field3, selectionType, selection: selection2 } = this;\n if (isSelection(selection2)) {\n if (selectionType === \"interval\") {\n const domain = [this.min ?? 0, value];\n selection2.update(clauseInterval(field3, domain, {\n source: this,\n bin: \"ceil\",\n scale: { type: \"identity\", domain },\n pixelSize: this.step\n }));\n } else {\n selection2.update(clausePoint(field3, value, { source: this }));\n }\n } else if (isParam(this.selection)) {\n selection2.update(value);\n }\n }\n};\n\n// ../inputs/src/util/format.js\nvar formatLocaleAuto = localize((locale3) => {\n const formatNumber3 = formatLocaleNumber(locale3);\n return (value) => value == null ? \"\" : typeof value === \"number\" ? formatNumber3(value) : value instanceof Date ? formatDate(value) : `${value}`;\n});\nvar formatLocaleNumber = localize((locale3) => {\n return (value) => value === 0 ? \"0\" : value.toLocaleString(locale3);\n});\nvar formatAuto2 = formatLocaleAuto();\nvar formatNumber2 = formatLocaleNumber();\nfunction formatDate(date3) {\n return format2(date3, \"Invalid Date\");\n}\nfunction localize(f) {\n let key = null;\n let value;\n return (locale3 = \"en\") => locale3 === key ? value : value = f(key = locale3);\n}\n\n// ../inputs/src/Table.js\nvar _id3 = -1;\nvar Table2 = class extends MosaicClient {\n /**\n * Create a new Table instance.\n * @param {object} options Options object\n */\n constructor({\n element,\n filterBy,\n from: from2,\n columns = [\"*\"],\n align: align3 = {},\n format: format3,\n width: width2,\n maxWidth,\n height: height2 = 500,\n rowBatch = 100,\n as\n } = {}) {\n super(filterBy);\n this.id = `table-${++_id3}`;\n this.from = from2;\n this.columns = columns;\n this.format = format3;\n this.align = align3;\n this.widths = typeof width2 === \"object\" ? width2 : {};\n this.offset = 0;\n this.limit = +rowBatch;\n this.pending = false;\n this.selection = as;\n this.currentRow = -1;\n this.sortHeader = null;\n this.sortColumn = null;\n this.sortDesc = false;\n this.element = element || document.createElement(\"div\");\n this.element.setAttribute(\"id\", this.id);\n Object.defineProperty(this.element, \"value\", { value: this });\n if (typeof width2 === \"number\") this.element.style.width = `${width2}px`;\n if (maxWidth) this.element.style.maxWidth = `${maxWidth}px`;\n this.element.style.maxHeight = `${height2}px`;\n this.element.style.overflow = \"auto\";\n let prevScrollTop = -1;\n this.element.addEventListener(\"scroll\", (evt) => {\n const { pending, loaded } = this;\n const { scrollHeight, scrollTop, clientHeight } = evt.target;\n const back = scrollTop < prevScrollTop;\n prevScrollTop = scrollTop;\n if (back || pending || loaded) return;\n if (scrollHeight - scrollTop < 2 * clientHeight) {\n this.pending = true;\n this.requestData(this.offset + this.limit);\n }\n });\n this.tbl = document.createElement(\"table\");\n this.element.appendChild(this.tbl);\n this.head = document.createElement(\"thead\");\n this.tbl.appendChild(this.head);\n this.body = document.createElement(\"tbody\");\n this.tbl.appendChild(this.body);\n if (this.selection) {\n this.body.addEventListener(\"pointerover\", (evt) => {\n const row = resolveRow(evt.target);\n if (row > -1 && row !== this.currentRow) {\n this.currentRow = row;\n this.selection.update(this.clause([row]));\n }\n });\n this.body.addEventListener(\"pointerleave\", () => {\n this.currentRow = -1;\n this.selection.update(this.clause());\n });\n }\n this.style = document.createElement(\"style\");\n this.element.appendChild(this.style);\n }\n clause(rows = []) {\n const { data, limit, schema } = this;\n const fields = schema.map((s2) => s2.column);\n const values2 = rows.map((row) => {\n const { columns } = data[~~(row / limit)];\n return fields.map((f) => columns[f][row % limit]);\n });\n return clausePoints(fields, values2, { source: this });\n }\n requestData(offset2 = 0) {\n this.offset = offset2;\n const query = this.query(this.filterBy?.predicate(this));\n this.requestQuery(query);\n coordinator().prefetch(query.clone().offset(offset2 + this.limit));\n }\n fields() {\n return this.columns.map((name2) => column(this.from, name2));\n }\n fieldInfo(info) {\n this.schema = info;\n const thead = this.head;\n thead.innerHTML = \"\";\n const tr = document.createElement(\"tr\");\n for (const { column: column3 } of info) {\n const th = document.createElement(\"th\");\n th.addEventListener(\"click\", (evt) => this.sort(evt, column3));\n th.appendChild(document.createElement(\"span\"));\n th.appendChild(document.createTextNode(column3));\n tr.appendChild(th);\n }\n thead.appendChild(tr);\n this.formats = formatof(this.format, info);\n this.style.innerText = tableCSS(\n this.id,\n alignof(this.align, info),\n widthof(this.widths, info)\n );\n return this;\n }\n query(filter3 = []) {\n const { from: from2, limit, offset: offset2, schema, sortColumn, sortDesc } = this;\n return Query.from(from2).select(schema.map((s2) => s2.column)).where(filter3).orderby(sortColumn ? sortDesc ? desc(sortColumn) : sortColumn : []).limit(limit).offset(offset2);\n }\n queryResult(data) {\n if (!this.pending) {\n this.loaded = false;\n this.data = [];\n this.body.replaceChildren();\n this.offset = 0;\n }\n this.data.push(toDataColumns(data));\n return this;\n }\n update() {\n const { body, formats, data, schema, limit } = this;\n const nf = schema.length;\n const n = data.length - 1;\n const rowCount = limit * n;\n const { numRows, columns } = data[n];\n const cols = schema.map((s2) => columns[s2.column]);\n for (let i = 0; i < numRows; ++i) {\n const tr = document.createElement(\"tr\");\n Object.assign(tr, { __row__: rowCount + i });\n for (let j = 0; j < nf; ++j) {\n const value = cols[j][i];\n const td = document.createElement(\"td\");\n td.innerText = value == null ? \"\" : formats[j](value);\n tr.appendChild(td);\n }\n body.appendChild(tr);\n }\n if (numRows < limit) {\n this.loaded = true;\n }\n this.pending = false;\n return this;\n }\n sort(event, column3) {\n if (column3 === this.sortColumn) {\n this.sortDesc = !this.sortDesc;\n } else {\n this.sortColumn = column3;\n this.sortDesc = false;\n }\n const th = event.currentTarget;\n const currentHeader = this.sortHeader;\n if (currentHeader === th && event.metaKey) {\n currentHeader.firstChild.textContent = \"\";\n this.sortHeader = null;\n this.sortColumn = null;\n } else {\n if (currentHeader) currentHeader.firstChild.textContent = \"\";\n this.sortHeader = th;\n th.firstChild.textContent = this.sortDesc ? \"\\u25BE\" : \"\\u25B4\";\n }\n this.requestData();\n }\n};\nfunction resolveRow(element) {\n const p = element.parentElement;\n return Object.hasOwn(p, \"__row__\") ? +p.__row__ : -1;\n}\nfunction formatof(base = {}, schema, locale3) {\n return schema.map(({ column: column3, type: type2 }) => {\n if (column3 in base) {\n return base[column3];\n } else {\n switch (type2) {\n case \"number\":\n return formatLocaleNumber(locale3);\n case \"date\":\n return formatDate;\n default:\n return formatLocaleAuto(locale3);\n }\n }\n });\n}\nfunction alignof(base = {}, schema) {\n return schema.map(({ column: column3, type: type2 }) => {\n if (column3 in base) {\n return base[column3];\n } else if (type2 === \"number\") {\n return \"right\";\n } else {\n return \"left\";\n }\n });\n}\nfunction widthof(base = {}, schema) {\n return schema.map(({ column: column3 }) => base[column3]);\n}\nfunction tableCSS(id2, aligns, widths) {\n const styles2 = [];\n aligns.forEach((a2, i) => {\n const w = +widths[i];\n if (a2 !== \"left\" || w) {\n const align3 = a2 !== \"left\" ? `text-align:${a2};` : \"\";\n const width2 = w ? `width:${w}px;max-width:${w}px;` : \"\";\n styles2.push(`#${id2} tr>:nth-child(${i + 1}) {${align3}${width2}}`);\n }\n });\n return styles2.join(\" \");\n}\n\n// ../vgplot/src/connect.js\nfunction connect(ctx, ...clients) {\n const coord = ctx?.context?.coordinator ?? coordinator();\n for (const client of clients) {\n coord.connect(client);\n }\n}\n\n// ../vgplot/src/inputs.js\nfunction input2(ctx, InputClass, options) {\n const input3 = new InputClass(options);\n connect(ctx, input3);\n return input3.element;\n}\nfunction menu2(options) {\n return input2(this, Menu, options);\n}\nfunction search2(options) {\n return input2(this, Search, options);\n}\nfunction slider2(options) {\n return input2(this, Slider, options);\n}\nfunction table2(options) {\n return input2(this, Table2, options);\n}\n\n// ../vgplot/src/layout/concat.js\nfunction concat2({ direction = \"vertical\", wrap: wrap3 = false }, children2) {\n const div = document.createElement(\"div\");\n div.style.display = \"flex\";\n div.style.flexDirection = direction === \"vertical\" ? \"column\" : \"row\";\n div.style.flexWrap = !wrap3 ? \"nowrap\" : wrap3 === true ? \"wrap\" : wrap3;\n div.style.justifyContent = \"flex-start\";\n div.style.alignItems = \"flex-start\";\n children2.forEach((child) => div.appendChild(child));\n Object.assign(div, { value: { element: div } });\n return div;\n}\nfunction vconcat(...plots) {\n return concat2({ direction: \"vertical\" }, plots.flat());\n}\nfunction hconcat(...plots) {\n return concat2({ direction: \"horizontal\" }, plots.flat());\n}\n\n// ../vgplot/src/layout/space.js\nfunction space({ dim = \"width\", size = 10 }) {\n const span = document.createElement(\"span\");\n span.style.display = \"inline-block\";\n span.style[dim] = Number.isNaN(+size) ? size : `${size}px`;\n return Object.assign(span, { value: { element: span } });\n}\nfunction vspace(size) {\n return space({ dim: \"height\", size });\n}\nfunction hspace(size) {\n return space({ dim: \"width\", size });\n}\n\n// ../vgplot/src/plot/attributes.js\nvar attributes_exports = {};\n__export(attributes_exports, {\n align: () => align2,\n aspectRatio: () => aspectRatio,\n axis: () => axis2,\n colorBase: () => colorBase,\n colorClamp: () => colorClamp,\n colorConstant: () => colorConstant2,\n colorDomain: () => colorDomain,\n colorExponent: () => colorExponent,\n colorInterpolate: () => colorInterpolate,\n colorLabel: () => colorLabel,\n colorN: () => colorN,\n colorNice: () => colorNice,\n colorPercent: () => colorPercent,\n colorPivot: () => colorPivot,\n colorRange: () => colorRange,\n colorReverse: () => colorReverse,\n colorScale: () => colorScale2,\n colorScheme: () => colorScheme2,\n colorSymmetric: () => colorSymmetric,\n colorTickFormat: () => colorTickFormat,\n colorZero: () => colorZero,\n facetGrid: () => facetGrid,\n facetLabel: () => facetLabel,\n facetMargin: () => facetMargin,\n facetMarginBottom: () => facetMarginBottom,\n facetMarginLeft: () => facetMarginLeft,\n facetMarginRight: () => facetMarginRight,\n facetMarginTop: () => facetMarginTop,\n fxAlign: () => fxAlign,\n fxAriaDescription: () => fxAriaDescription,\n fxAriaLabel: () => fxAriaLabel,\n fxAxis: () => fxAxis,\n fxDomain: () => fxDomain,\n fxFontVariant: () => fxFontVariant,\n fxGrid: () => fxGrid,\n fxInset: () => fxInset,\n fxInsetLeft: () => fxInsetLeft,\n fxInsetRight: () => fxInsetRight,\n fxLabel: () => fxLabel,\n fxLabelAnchor: () => fxLabelAnchor,\n fxLabelOffset: () => fxLabelOffset,\n fxLine: () => fxLine,\n fxPadding: () => fxPadding,\n fxPaddingInner: () => fxPaddingInner,\n fxPaddingOuter: () => fxPaddingOuter,\n fxRange: () => fxRange,\n fxReverse: () => fxReverse,\n fxRound: () => fxRound,\n fxTickFormat: () => fxTickFormat,\n fxTickPadding: () => fxTickPadding,\n fxTickRotate: () => fxTickRotate,\n fxTickSize: () => fxTickSize,\n fxTickSpacing: () => fxTickSpacing,\n fxTicks: () => fxTicks,\n fyAlign: () => fyAlign,\n fyAriaDescription: () => fyAriaDescription,\n fyAriaLabel: () => fyAriaLabel,\n fyAxis: () => fyAxis,\n fyDomain: () => fyDomain,\n fyFontVariant: () => fyFontVariant,\n fyGrid: () => fyGrid,\n fyInset: () => fyInset,\n fyInsetBottom: () => fyInsetBottom,\n fyInsetTop: () => fyInsetTop,\n fyLabel: () => fyLabel,\n fyLabelAnchor: () => fyLabelAnchor,\n fyLabelOffset: () => fyLabelOffset,\n fyLine: () => fyLine,\n fyPadding: () => fyPadding,\n fyPaddingInner: () => fyPaddingInner,\n fyPaddingOuter: () => fyPaddingOuter,\n fyRange: () => fyRange,\n fyReverse: () => fyReverse,\n fyRound: () => fyRound,\n fyTickFormat: () => fyTickFormat,\n fyTickPadding: () => fyTickPadding,\n fyTickRotate: () => fyTickRotate,\n fyTickSize: () => fyTickSize,\n fyTickSpacing: () => fyTickSpacing,\n fyTicks: () => fyTicks,\n grid: () => grid,\n height: () => height,\n inset: () => inset,\n label: () => label,\n lengthBase: () => lengthBase,\n lengthClamp: () => lengthClamp,\n lengthConstant: () => lengthConstant,\n lengthDomain: () => lengthDomain,\n lengthExponent: () => lengthExponent,\n lengthNice: () => lengthNice,\n lengthPercent: () => lengthPercent,\n lengthRange: () => lengthRange,\n lengthScale: () => lengthScale,\n lengthZero: () => lengthZero,\n margin: () => margin,\n marginBottom: () => marginBottom,\n marginLeft: () => marginLeft,\n marginRight: () => marginRight,\n marginTop: () => marginTop,\n margins: () => margins,\n name: () => name,\n opacityBase: () => opacityBase,\n opacityClamp: () => opacityClamp,\n opacityConstant: () => opacityConstant,\n opacityDomain: () => opacityDomain,\n opacityExponent: () => opacityExponent,\n opacityLabel: () => opacityLabel,\n opacityNice: () => opacityNice,\n opacityPercent: () => opacityPercent,\n opacityRange: () => opacityRange,\n opacityReverse: () => opacityReverse,\n opacityScale: () => opacityScale,\n opacityTickFormat: () => opacityTickFormat,\n opacityZero: () => opacityZero,\n padding: () => padding,\n projectionClip: () => projectionClip,\n projectionDomain: () => projectionDomain,\n projectionInset: () => projectionInset,\n projectionInsetBottom: () => projectionInsetBottom,\n projectionInsetLeft: () => projectionInsetLeft,\n projectionInsetRight: () => projectionInsetRight,\n projectionInsetTop: () => projectionInsetTop,\n projectionParallels: () => projectionParallels,\n projectionPrecision: () => projectionPrecision,\n projectionRotate: () => projectionRotate,\n projectionType: () => projectionType,\n rBase: () => rBase,\n rClamp: () => rClamp,\n rConstant: () => rConstant,\n rDomain: () => rDomain,\n rExponent: () => rExponent,\n rLabel: () => rLabel,\n rNice: () => rNice,\n rPercent: () => rPercent,\n rRange: () => rRange,\n rScale: () => rScale,\n rZero: () => rZero,\n style: () => style,\n symbolDomain: () => symbolDomain,\n symbolRange: () => symbolRange,\n symbolScale: () => symbolScale,\n width: () => width,\n xAlign: () => xAlign,\n xAriaDescription: () => xAriaDescription,\n xAriaLabel: () => xAriaLabel,\n xAxis: () => xAxis,\n xBase: () => xBase,\n xClamp: () => xClamp,\n xConstant: () => xConstant,\n xDomain: () => xDomain,\n xExponent: () => xExponent,\n xFontVariant: () => xFontVariant,\n xGrid: () => xGrid,\n xInset: () => xInset,\n xInsetLeft: () => xInsetLeft,\n xInsetRight: () => xInsetRight,\n xLabel: () => xLabel,\n xLabelAnchor: () => xLabelAnchor,\n xLabelArrow: () => xLabelArrow,\n xLabelOffset: () => xLabelOffset,\n xLine: () => xLine,\n xNice: () => xNice,\n xPadding: () => xPadding,\n xPaddingInner: () => xPaddingInner,\n xPaddingOuter: () => xPaddingOuter,\n xPercent: () => xPercent,\n xRange: () => xRange,\n xReverse: () => xReverse,\n xRound: () => xRound,\n xScale: () => xScale,\n xTickFormat: () => xTickFormat,\n xTickPadding: () => xTickPadding,\n xTickRotate: () => xTickRotate,\n xTickSize: () => xTickSize,\n xTickSpacing: () => xTickSpacing,\n xTicks: () => xTicks,\n xZero: () => xZero,\n xyDomain: () => xyDomain,\n yAlign: () => yAlign,\n yAriaDescription: () => yAriaDescription,\n yAriaLabel: () => yAriaLabel,\n yAxis: () => yAxis,\n yBase: () => yBase,\n yClamp: () => yClamp,\n yConstant: () => yConstant,\n yDomain: () => yDomain,\n yExponent: () => yExponent,\n yFontVariant: () => yFontVariant,\n yGrid: () => yGrid,\n yInset: () => yInset,\n yInsetBottom: () => yInsetBottom,\n yInsetTop: () => yInsetTop,\n yLabel: () => yLabel,\n yLabelAnchor: () => yLabelAnchor,\n yLabelArrow: () => yLabelArrow,\n yLabelOffset: () => yLabelOffset,\n yLine: () => yLine,\n yNice: () => yNice,\n yPadding: () => yPadding,\n yPaddingInner: () => yPaddingInner,\n yPaddingOuter: () => yPaddingOuter,\n yPercent: () => yPercent,\n yRange: () => yRange,\n yReverse: () => yReverse,\n yRound: () => yRound,\n yScale: () => yScale,\n yTickFormat: () => yTickFormat,\n yTickPadding: () => yTickPadding,\n yTickRotate: () => yTickRotate,\n yTickSize: () => yTickSize,\n yTickSpacing: () => yTickSpacing,\n yTicks: () => yTicks,\n yZero: () => yZero\n});\n\n// ../vgplot/src/plot/named-plots.js\nvar NamedPlots = class extends Map {\n request(name2, callback) {\n if (this.has(name2)) {\n callback(this.get(name2));\n } else {\n const waiting = this.waiting || (this.waiting = /* @__PURE__ */ new Map());\n const list2 = waiting.get(name2) || [];\n waiting.set(name2, list2.concat(callback));\n }\n }\n set(name2, plot3) {\n if (this.has(name2)) {\n console.warn(`Overwriting named plot \"${name2}\".`);\n }\n const { waiting } = this;\n if (waiting?.has(name2)) {\n waiting.get(name2).forEach((fn) => fn(plot3));\n waiting.delete(name2);\n }\n return super.set(name2, plot3);\n }\n clear() {\n this.waiting?.clear();\n return super.clear();\n }\n};\nvar namedPlots = new NamedPlots();\nfunction requestNamedPlot(ctx, name2, callback) {\n const map5 = ctx?.context?.namedPlots ?? namedPlots;\n map5.request(name2, callback);\n}\nfunction setNamedPlot(ctx, name2, plot3) {\n const map5 = ctx?.context?.namedPlots ?? namedPlots;\n map5.set(name2, plot3);\n}\n\n// ../vgplot/src/plot/attributes.js\nfunction name(name2) {\n return (plot3) => setNamedPlot(this, name2, plot3);\n}\nfunction setAttribute(plot3, name2, value) {\n if (isParam(value)) {\n value.addEventListener(\"value\", (value2) => {\n plot3.setAttribute(name2, value2);\n plot3.update();\n });\n if (value.value !== void 0) {\n plot3.setAttribute(name2, value.value);\n }\n } else {\n plot3.setAttribute(name2, value);\n }\n}\nfunction attribute(name2, value) {\n return (plot3) => {\n setAttribute(plot3, name2, value);\n };\n}\nfunction attributes(values2) {\n return (plot3) => {\n for (const [name2, value] of Object.entries(values2)) {\n setAttribute(plot3, name2, value);\n }\n };\n}\nfunction margins(object) {\n const { top: top2, bottom: bottom2, left: left2, right: right2 } = object;\n const attr = {};\n if (top2 !== void 0) attr.marginTop = top2;\n if (bottom2 !== void 0) attr.marginBottom = bottom2;\n if (left2 !== void 0) attr.marginLeft = left2;\n if (right2 !== void 0) attr.marginRight = right2;\n return attributes(attr);\n}\nfunction margin(value) {\n return attributes({\n marginTop: value,\n marginBottom: value,\n marginLeft: value,\n marginRight: value\n });\n}\nfunction xyDomain(value) {\n return attributes({ xDomain: value, yDomain: value });\n}\nvar attrf = (name2) => (value) => attribute(name2, value);\nvar style = attrf(\"style\");\nvar width = attrf(\"width\");\nvar height = attrf(\"height\");\nvar marginLeft = attrf(\"marginLeft\");\nvar marginRight = attrf(\"marginRight\");\nvar marginTop = attrf(\"marginTop\");\nvar marginBottom = attrf(\"marginBottom\");\nvar align2 = attrf(\"align\");\nvar aspectRatio = attrf(\"aspectRatio\");\nvar axis2 = attrf(\"axis\");\nvar inset = attrf(\"inset\");\nvar grid = attrf(\"grid\");\nvar label = attrf(\"label\");\nvar padding = attrf(\"padding\");\nvar xScale = attrf(\"xScale\");\nvar xDomain = attrf(\"xDomain\");\nvar xRange = attrf(\"xRange\");\nvar xNice = attrf(\"xNice\");\nvar xInset = attrf(\"xInset\");\nvar xInsetLeft = attrf(\"xInsetLeft\");\nvar xInsetRight = attrf(\"xInsetRight\");\nvar xClamp = attrf(\"xClamp\");\nvar xRound = attrf(\"xRound\");\nvar xAlign = attrf(\"xAlign\");\nvar xPadding = attrf(\"xPadding\");\nvar xPaddingInner = attrf(\"xPaddingInner\");\nvar xPaddingOuter = attrf(\"xPaddingOuter\");\nvar xAxis = attrf(\"xAxis\");\nvar xTicks = attrf(\"xTicks\");\nvar xTickSize = attrf(\"xTickSize\");\nvar xTickSpacing = attrf(\"xTickSpacing\");\nvar xTickPadding = attrf(\"xTickPadding\");\nvar xTickFormat = attrf(\"xTickFormat\");\nvar xTickRotate = attrf(\"xTickRotate\");\nvar xGrid = attrf(\"xGrid\");\nvar xLine = attrf(\"xLine\");\nvar xLabel = attrf(\"xLabel\");\nvar xLabelAnchor = attrf(\"xLabelAnchor\");\nvar xLabelArrow = attrf(\"xLabelArrow\");\nvar xLabelOffset = attrf(\"xLabelOffset\");\nvar xFontVariant = attrf(\"xFontVariant\");\nvar xAriaLabel = attrf(\"xAriaLabel\");\nvar xAriaDescription = attrf(\"xAriaDescription\");\nvar xPercent = attrf(\"xPercent\");\nvar xReverse = attrf(\"xReverse\");\nvar xZero = attrf(\"xZero\");\nvar xBase = attrf(\"xBase\");\nvar xExponent = attrf(\"xExponent\");\nvar xConstant = attrf(\"xConstant\");\nvar yScale = attrf(\"yScale\");\nvar yDomain = attrf(\"yDomain\");\nvar yRange = attrf(\"yRange\");\nvar yNice = attrf(\"yNice\");\nvar yInset = attrf(\"yInset\");\nvar yInsetTop = attrf(\"yInsetTop\");\nvar yInsetBottom = attrf(\"yInsetBottom\");\nvar yClamp = attrf(\"yClamp\");\nvar yRound = attrf(\"yRound\");\nvar yAlign = attrf(\"yAlign\");\nvar yPadding = attrf(\"yPadding\");\nvar yPaddingInner = attrf(\"yPaddingInner\");\nvar yPaddingOuter = attrf(\"yPaddingOuter\");\nvar yAxis = attrf(\"yAxis\");\nvar yTicks = attrf(\"yTicks\");\nvar yTickSize = attrf(\"yTickSize\");\nvar yTickSpacing = attrf(\"yTickSpacing\");\nvar yTickPadding = attrf(\"yTickPadding\");\nvar yTickFormat = attrf(\"yTickFormat\");\nvar yTickRotate = attrf(\"yTickRotate\");\nvar yGrid = attrf(\"yGrid\");\nvar yLine = attrf(\"yLine\");\nvar yLabel = attrf(\"yLabel\");\nvar yLabelAnchor = attrf(\"yLabelAnchor\");\nvar yLabelArrow = attrf(\"yLabelArrow\");\nvar yLabelOffset = attrf(\"yLabelOffset\");\nvar yFontVariant = attrf(\"yFontVariant\");\nvar yAriaLabel = attrf(\"yAriaLabel\");\nvar yAriaDescription = attrf(\"yAriaDescription\");\nvar yPercent = attrf(\"yPercent\");\nvar yReverse = attrf(\"yReverse\");\nvar yZero = attrf(\"yZero\");\nvar yBase = attrf(\"yBase\");\nvar yExponent = attrf(\"yExponent\");\nvar yConstant = attrf(\"yConstant\");\nvar facetMargin = attrf(\"facetMargin\");\nvar facetMarginTop = attrf(\"facetMarginTop\");\nvar facetMarginBottom = attrf(\"facetMarginBottom\");\nvar facetMarginLeft = attrf(\"facetMarginLeft\");\nvar facetMarginRight = attrf(\"facetMarginRight\");\nvar facetGrid = attrf(\"facetGrid\");\nvar facetLabel = attrf(\"facetLabel\");\nvar fxDomain = attrf(\"fxDomain\");\nvar fxRange = attrf(\"fxRange\");\nvar fxInset = attrf(\"fxInset\");\nvar fxInsetLeft = attrf(\"fxInsetLeft\");\nvar fxInsetRight = attrf(\"fxInsetRight\");\nvar fxRound = attrf(\"fxRound\");\nvar fxAlign = attrf(\"fxAlign\");\nvar fxPadding = attrf(\"fxPadding\");\nvar fxPaddingInner = attrf(\"fxPaddingInner\");\nvar fxPaddingOuter = attrf(\"fxPaddingOuter\");\nvar fxAxis = attrf(\"fxAxis\");\nvar fxTicks = attrf(\"fxTicks\");\nvar fxTickSize = attrf(\"fxTickSize\");\nvar fxTickSpacing = attrf(\"fxTickSpacing\");\nvar fxTickPadding = attrf(\"fxTickPadding\");\nvar fxTickFormat = attrf(\"fxTickFormat\");\nvar fxTickRotate = attrf(\"fxTickRotate\");\nvar fxGrid = attrf(\"fxGrid\");\nvar fxLine = attrf(\"fxLine\");\nvar fxLabel = attrf(\"fxLabel\");\nvar fxLabelAnchor = attrf(\"fxLabelAnchor\");\nvar fxLabelOffset = attrf(\"fxLabelOffset\");\nvar fxFontVariant = attrf(\"fxFontVariant\");\nvar fxAriaLabel = attrf(\"fxAriaLabel\");\nvar fxAriaDescription = attrf(\"fxAriaDescription\");\nvar fxReverse = attrf(\"fxReverse\");\nvar fyDomain = attrf(\"fyDomain\");\nvar fyRange = attrf(\"fyRange\");\nvar fyInset = attrf(\"fyInset\");\nvar fyInsetTop = attrf(\"fyInsetTop\");\nvar fyInsetBottom = attrf(\"fyInsetBottom\");\nvar fyRound = attrf(\"fyRound\");\nvar fyAlign = attrf(\"fyAlign\");\nvar fyPadding = attrf(\"fyPadding\");\nvar fyPaddingInner = attrf(\"fyPaddingInner\");\nvar fyPaddingOuter = attrf(\"fyPaddingOuter\");\nvar fyAxis = attrf(\"fyAxis\");\nvar fyTicks = attrf(\"fyTicks\");\nvar fyTickSize = attrf(\"fyTickSize\");\nvar fyTickSpacing = attrf(\"fyTickSpacing\");\nvar fyTickPadding = attrf(\"fyTickPadding\");\nvar fyTickFormat = attrf(\"fyTickFormat\");\nvar fyTickRotate = attrf(\"fyTickRotate\");\nvar fyGrid = attrf(\"fyGrid\");\nvar fyLine = attrf(\"fyLine\");\nvar fyLabel = attrf(\"fyLabel\");\nvar fyLabelAnchor = attrf(\"fyLabelAnchor\");\nvar fyLabelOffset = attrf(\"fyLabelOffset\");\nvar fyFontVariant = attrf(\"fyFontVariant\");\nvar fyAriaLabel = attrf(\"fyAriaLabel\");\nvar fyAriaDescription = attrf(\"fyAriaDescription\");\nvar fyReverse = attrf(\"fyReverse\");\nvar colorScale2 = attrf(\"colorScale\");\nvar colorDomain = attrf(\"colorDomain\");\nvar colorRange = attrf(\"colorRange\");\nvar colorClamp = attrf(\"colorClamp\");\nvar colorN = attrf(\"colorN\");\nvar colorNice = attrf(\"colorNice\");\nvar colorScheme2 = attrf(\"colorScheme\");\nvar colorInterpolate = attrf(\"colorInterpolate\");\nvar colorPivot = attrf(\"colorPivot\");\nvar colorSymmetric = attrf(\"colorSymmetric\");\nvar colorLabel = attrf(\"colorLabel\");\nvar colorPercent = attrf(\"colorPercent\");\nvar colorReverse = attrf(\"colorReverse\");\nvar colorZero = attrf(\"colorZero\");\nvar colorTickFormat = attrf(\"colorTickFormat\");\nvar colorBase = attrf(\"colorBase\");\nvar colorExponent = attrf(\"colorExponent\");\nvar colorConstant2 = attrf(\"colorConstant\");\nvar opacityScale = attrf(\"opacityScale\");\nvar opacityDomain = attrf(\"opacityDomain\");\nvar opacityRange = attrf(\"opacityRange\");\nvar opacityClamp = attrf(\"opacityClamp\");\nvar opacityNice = attrf(\"opacityNice\");\nvar opacityLabel = attrf(\"opacityLabel\");\nvar opacityPercent = attrf(\"opacityPercent\");\nvar opacityReverse = attrf(\"opacityReverse\");\nvar opacityZero = attrf(\"opacityZero\");\nvar opacityTickFormat = attrf(\"opacityTickFormat\");\nvar opacityBase = attrf(\"opacityBase\");\nvar opacityExponent = attrf(\"opacityExponent\");\nvar opacityConstant = attrf(\"opacityConstant\");\nvar symbolScale = attrf(\"symbolScale\");\nvar symbolDomain = attrf(\"symbolDomain\");\nvar symbolRange = attrf(\"symbolRange\");\nvar rScale = attrf(\"rScale\");\nvar rDomain = attrf(\"rDomain\");\nvar rRange = attrf(\"rRange\");\nvar rClamp = attrf(\"rClamp\");\nvar rNice = attrf(\"rNice\");\nvar rLabel = attrf(\"rLabel\");\nvar rPercent = attrf(\"rPercent\");\nvar rZero = attrf(\"rZero\");\nvar rBase = attrf(\"rBase\");\nvar rExponent = attrf(\"rExponent\");\nvar rConstant = attrf(\"rConstant\");\nvar lengthScale = attrf(\"lengthScale\");\nvar lengthDomain = attrf(\"lengthDomain\");\nvar lengthRange = attrf(\"lengthRange\");\nvar lengthClamp = attrf(\"lengthClamp\");\nvar lengthNice = attrf(\"lengthNice\");\nvar lengthPercent = attrf(\"lengthPercent\");\nvar lengthZero = attrf(\"lengthZero\");\nvar lengthBase = attrf(\"lengthBase\");\nvar lengthExponent = attrf(\"lengthExponent\");\nvar lengthConstant = attrf(\"lengthConstant\");\nvar projectionType = attrf(\"projectionType\");\nvar projectionParallels = attrf(\"projectionParallels\");\nvar projectionPrecision = attrf(\"projectionPrecision\");\nvar projectionRotate = attrf(\"projectionRotate\");\nvar projectionDomain = attrf(\"projectionDomain\");\nvar projectionInset = attrf(\"projectionInset\");\nvar projectionInsetLeft = attrf(\"projectionInsetLeft\");\nvar projectionInsetRight = attrf(\"projectionInsetRight\");\nvar projectionInsetTop = attrf(\"projectionInsetTop\");\nvar projectionInsetBottom = attrf(\"projectionInsetBottom\");\nvar projectionClip = attrf(\"projectionClip\");\n\n// ../vgplot/src/plot/data.js\nfunction from(table3, options) {\n return { table: table3, options };\n}\n\n// ../vgplot/src/plot/marks.js\nvar marks_exports = {};\n__export(marks_exports, {\n area: () => area2,\n areaX: () => areaX2,\n areaY: () => areaY2,\n arrow: () => arrow2,\n axisFx: () => axisFx2,\n axisFy: () => axisFy2,\n axisX: () => axisX2,\n axisY: () => axisY2,\n barX: () => barX2,\n barY: () => barY2,\n cell: () => cell2,\n cellX: () => cellX2,\n cellY: () => cellY2,\n circle: () => circle2,\n contour: () => contour2,\n delaunayLink: () => delaunayLink2,\n delaunayMesh: () => delaunayMesh2,\n denseLine: () => denseLine,\n density: () => density2,\n densityX: () => densityX,\n densityY: () => densityY,\n dot: () => dot2,\n dotX: () => dotX2,\n dotY: () => dotY2,\n errorbarX: () => errorbarX,\n errorbarY: () => errorbarY,\n frame: () => frame3,\n geo: () => geo2,\n graticule: () => graticule3,\n gridFx: () => gridFx2,\n gridFy: () => gridFy2,\n gridX: () => gridX2,\n gridY: () => gridY2,\n heatmap: () => heatmap,\n hexagon: () => hexagon2,\n hexbin: () => hexbin2,\n hexgrid: () => hexgrid2,\n hull: () => hull2,\n image: () => image2,\n line: () => line2,\n lineX: () => lineX2,\n lineY: () => lineY2,\n link: () => link3,\n raster: () => raster2,\n rasterTile: () => rasterTile,\n rect: () => rect2,\n rectX: () => rectX2,\n rectY: () => rectY2,\n regressionY: () => regressionY,\n ruleX: () => ruleX2,\n ruleY: () => ruleY2,\n sphere: () => sphere2,\n spike: () => spike2,\n text: () => text2,\n textX: () => textX2,\n textY: () => textY2,\n tickX: () => tickX2,\n tickY: () => tickY2,\n vector: () => vector2,\n vectorX: () => vectorX2,\n vectorY: () => vectorY2,\n voronoi: () => voronoi2,\n voronoiMesh: () => voronoiMesh2\n});\nvar decorators = /* @__PURE__ */ new Set([\n \"frame\",\n \"axisX\",\n \"axisY\",\n \"axisFx\",\n \"axisFy\",\n \"gridX\",\n \"gridY\",\n \"gridFx\",\n \"gridFy\",\n \"hexgrid\",\n \"graticule\",\n \"sphere\"\n]);\nfunction mark(type2, data, channels = {}) {\n if (arguments.length === 2 && !Array.isArray(data)) {\n channels = data;\n data = decorators.has(type2) ? null : [{}];\n }\n const MarkClass = type2.startsWith(\"area\") || type2.startsWith(\"line\") ? ConnectedMark : Mark2;\n return explicitType(MarkClass, type2, data, channels);\n}\nfunction explicitType(MarkClass, type2, data, channels) {\n return (plot3) => {\n plot3.addMark(new MarkClass(type2, data, channels));\n };\n}\nfunction implicitType(MarkClass, data, channels) {\n return (plot3) => {\n plot3.addMark(new MarkClass(data, channels));\n };\n}\nvar area2 = (...args) => mark(\"area\", ...args);\nvar areaX2 = (...args) => mark(\"areaX\", ...args);\nvar areaY2 = (...args) => mark(\"areaY\", ...args);\nvar line2 = (...args) => mark(\"line\", ...args);\nvar lineX2 = (...args) => mark(\"lineX\", ...args);\nvar lineY2 = (...args) => mark(\"lineY\", ...args);\nvar barX2 = (...args) => mark(\"barX\", ...args);\nvar barY2 = (...args) => mark(\"barY\", ...args);\nvar cell2 = (...args) => mark(\"cell\", ...args);\nvar cellX2 = (...args) => mark(\"cellX\", ...args);\nvar cellY2 = (...args) => mark(\"cellY\", ...args);\nvar rect2 = (...args) => mark(\"rect\", ...args);\nvar rectX2 = (...args) => mark(\"rectX\", ...args);\nvar rectY2 = (...args) => mark(\"rectY\", ...args);\nvar dot2 = (...args) => mark(\"dot\", ...args);\nvar dotX2 = (...args) => mark(\"dotX\", ...args);\nvar dotY2 = (...args) => mark(\"dotY\", ...args);\nvar circle2 = (...args) => mark(\"circle\", ...args);\nvar hexagon2 = (...args) => mark(\"hexagon\", ...args);\nvar text2 = (...args) => mark(\"text\", ...args);\nvar textX2 = (...args) => mark(\"textX\", ...args);\nvar textY2 = (...args) => mark(\"textY\", ...args);\nvar ruleX2 = (...args) => mark(\"ruleX\", ...args);\nvar ruleY2 = (...args) => mark(\"ruleY\", ...args);\nvar tickX2 = (...args) => mark(\"tickX\", ...args);\nvar tickY2 = (...args) => mark(\"tickY\", ...args);\nvar vector2 = (...args) => mark(\"vector\", ...args);\nvar vectorX2 = (...args) => mark(\"vectoX\", ...args);\nvar vectorY2 = (...args) => mark(\"vectorY\", ...args);\nvar spike2 = (...args) => mark(\"spike\", ...args);\nvar image2 = (...args) => mark(\"image\", ...args);\nvar densityX = (...args) => explicitType(Density1DMark, \"areaX\", ...args);\nvar densityY = (...args) => explicitType(Density1DMark, \"areaY\", ...args);\nvar density2 = (...args) => implicitType(Density2DMark, ...args);\nvar denseLine = (...args) => implicitType(DenseLineMark, ...args);\nvar contour2 = (...args) => implicitType(ContourMark, ...args);\nvar heatmap = (...args) => implicitType(HeatmapMark, ...args);\nvar raster2 = (...args) => implicitType(RasterMark, ...args);\nvar rasterTile = (...args) => implicitType(RasterTileMark, ...args);\nvar hexbin2 = (...args) => implicitType(HexbinMark, ...args);\nvar hexgrid2 = (...args) => mark(\"hexgrid\", ...args);\nvar regressionY = (...args) => implicitType(RegressionMark, ...args);\nvar errorbarX = (...args) => explicitType(ErrorBarMark, \"ruleY\", ...args);\nvar errorbarY = (...args) => implicitType(ErrorBarMark, \"ruleX\", ...args);\nvar voronoi2 = (...args) => mark(\"voronoi\", ...args);\nvar voronoiMesh2 = (...args) => mark(\"voronoiMesh\", ...args);\nvar delaunayLink2 = (...args) => mark(\"delaunayLink\", ...args);\nvar delaunayMesh2 = (...args) => mark(\"delaunayMesh\", ...args);\nvar hull2 = (...args) => mark(\"hull\", ...args);\nvar arrow2 = (...args) => mark(\"arrow\", ...args);\nvar link3 = (...args) => mark(\"link\", ...args);\nvar frame3 = (...args) => mark(\"frame\", ...args);\nvar axisX2 = (...args) => mark(\"axisX\", ...args);\nvar axisY2 = (...args) => mark(\"axisY\", ...args);\nvar axisFx2 = (...args) => mark(\"axisFx\", ...args);\nvar axisFy2 = (...args) => mark(\"axisFy\", ...args);\nvar gridX2 = (...args) => mark(\"gridX\", ...args);\nvar gridY2 = (...args) => mark(\"gridY\", ...args);\nvar gridFx2 = (...args) => mark(\"gridFx\", ...args);\nvar gridFy2 = (...args) => mark(\"gridFy\", ...args);\nvar geo2 = (...args) => implicitType(GeoMark, ...args);\nvar sphere2 = (...args) => mark(\"sphere\", ...args);\nvar graticule3 = (...args) => mark(\"graticule\", ...args);\n\n// ../vgplot/src/plot/interactors.js\nvar interactors_exports = {};\n__export(interactors_exports, {\n highlight: () => highlight,\n intervalX: () => intervalX,\n intervalXY: () => intervalXY,\n intervalY: () => intervalY,\n nearest: () => nearest,\n nearestX: () => nearestX,\n nearestY: () => nearestY,\n pan: () => pan,\n panX: () => panX,\n panY: () => panY,\n panZoom: () => panZoom,\n panZoomX: () => panZoomX,\n panZoomY: () => panZoomY,\n toggle: () => toggle,\n toggleColor: () => toggleColor,\n toggleX: () => toggleX,\n toggleY: () => toggleY,\n toggleZ: () => toggleZ\n});\nfunction interactor(InteractorClass, options) {\n return (plot3) => {\n const mark2 = plot3.marks[plot3.marks.length - 1];\n plot3.addInteractor(new InteractorClass(mark2, options));\n };\n}\nfunction highlight({ by, ...channels }) {\n return interactor(Highlight, { selection: by, channels });\n}\nfunction toggle({ as, ...rest }) {\n return interactor(Toggle, { ...rest, selection: as });\n}\nfunction toggleX(options) {\n return toggle({ ...options, channels: [\"x\"] });\n}\nfunction toggleY(options) {\n return toggle({ ...options, channels: [\"y\"] });\n}\nfunction toggleZ(options) {\n return toggle({ ...options, channels: [\"z\"] });\n}\nfunction toggleColor(options) {\n return toggle({ ...options, channels: [\"color\"] });\n}\nfunction nearest({ as, ...rest }) {\n return interactor(Nearest, { ...rest, selection: as, pointer: \"xy\" });\n}\nfunction nearestX({ as, ...rest }) {\n return interactor(Nearest, { ...rest, selection: as, pointer: \"x\" });\n}\nfunction nearestY({ as, ...rest }) {\n return interactor(Nearest, { ...rest, selection: as, pointer: \"y\" });\n}\nfunction intervalX({ as, ...rest }) {\n return interactor(Interval1D, { ...rest, selection: as, channel: \"x\" });\n}\nfunction intervalY({ as, ...rest }) {\n return interactor(Interval1D, { ...rest, selection: as, channel: \"y\" });\n}\nfunction intervalXY({ as, ...rest }) {\n return interactor(Interval2D, { ...rest, selection: as });\n}\nfunction zoom(options) {\n return interactor(PanZoom, options);\n}\nfunction pan(options = {}) {\n return zoom({ ...options, zoom: false });\n}\nfunction panX(options = {}) {\n return zoom({ ...options, zoom: false, pany: false });\n}\nfunction panY(options = {}) {\n return zoom({ ...options, zoom: false, panx: false });\n}\nfunction panZoom(options = {}) {\n return zoom(options);\n}\nfunction panZoomX(options = {}) {\n return zoom({ ...options, pany: false });\n}\nfunction panZoomY(options = {}) {\n return zoom({ ...options, panx: false });\n}\n\n// ../vgplot/src/plot/legends.js\nvar legends_exports = {};\n__export(legends_exports, {\n colorLegend: () => colorLegend,\n opacityLegend: () => opacityLegend,\n symbolLegend: () => symbolLegend\n});\nfunction legend2(channel, options = {}) {\n if (options.for) {\n const { for: maybePlot, ...rest } = options;\n const legend3 = new Legend(channel, rest);\n const type2 = typeof maybePlot;\n const add2 = (plot3) => plot3.addLegend(legend3, false);\n if (type2 === \"string\") {\n requestNamedPlot(this, maybePlot, add2);\n } else if (maybePlot.value) {\n add2(maybePlot.value);\n }\n return legend3.element;\n } else {\n return (plot3) => plot3.addLegend(new Legend(channel, options));\n }\n}\nfunction colorLegend(options) {\n return legend2.call(this, \"color\", options);\n}\nfunction opacityLegend(options) {\n return legend2.call(this, \"opacity\", options);\n}\nfunction symbolLegend(options) {\n return legend2.call(this, \"symbol\", options);\n}\n\n// ../vgplot/src/plot/plot.js\nfunction plot2(...directives) {\n const p = new Plot();\n directives.flat().forEach((dir) => dir(p));\n connect(this, ...p.marks);\n p.update();\n return p.element;\n}\n\n// ../vgplot/src/context.js\nfunction createAPIContext({\n coordinator: coordinator2 = coordinator(),\n namedPlots: namedPlots2 = new NamedPlots(),\n extensions = null,\n ...options\n} = {}) {\n return {\n ...api_exports,\n ...extensions,\n context: {\n coordinator: coordinator2,\n namedPlots: namedPlots2,\n ...options\n }\n };\n}\n\n// ../spec/src/constants.js\nvar SPEC = \"spec\";\nvar LITERAL = \"literal\";\nvar OPTIONS = \"options\";\nvar SELECTION = \"selection\";\nvar PARAMREF = \"paramref\";\nvar PARAM = \"param\";\nvar INCLUDE = \"include\";\nvar SELECT = \"select\";\nvar VALUE = \"value\";\nvar CROSSFILTER = \"crossfilter\";\nvar INTERSECT = \"intersect\";\nvar UNION = \"union\";\nvar SINGLE = \"single\";\nvar DATA = \"data\";\nvar EXPRESSION = \"expression\";\nvar SQL = \"sql\";\nvar AGG = \"agg\";\nvar INPUT = \"input\";\nvar HCONCAT = \"hconcat\";\nvar VCONCAT = \"vconcat\";\nvar HSPACE = \"hspace\";\nvar VSPACE = \"vspace\";\nvar MARK = \"mark\";\nvar FROM = \"from\";\nvar PLOT = \"plot\";\nvar LEGEND = \"legend\";\nvar ATTRIBUTE = \"attribute\";\nvar TRANSFORM = \"transform\";\nvar INTERACTOR = \"interactor\";\nvar FIXED = \"Fixed\";\n\n// ../spec/src/ast/ASTNode.js\nvar ASTNode = class {\n constructor(type2, children2 = null) {\n this.type = type2;\n this.children = children2;\n }\n /**\n * Instantiate this AST node to use in a live web application.\n * @param {import('../ast-to-dom.js').InstantiateContext} ctx The instantiation context.\n * @returns {*} The instantiated value of this node.\n */\n instantiate(ctx) {\n throw Error(\"instantiate not implemented\");\n }\n /**\n * Generate ESM code for this AST node.\n * @param {import('../ast-to-esm.js').CodegenContext} ctx The code generator context.\n * @returns {string|void} The generated ESM code for the node.\n */\n codegen(ctx) {\n return Error(\"codegen not implemented\");\n }\n /**\n * @returns {*} This AST node in JSON specification format.\n */\n toJSON() {\n return Error(\"toJSON not implemented\");\n }\n};\n\n// ../spec/src/ast/SpecNode.js\nvar SpecNode = class extends ASTNode {\n constructor(root2, meta, config, data, params, plotDefaults) {\n super(SPEC, [root2]);\n this.root = root2;\n this.meta = meta;\n this.config = config;\n this.data = data;\n this.params = params;\n this.plotDefaults = plotDefaults;\n }\n toJSON() {\n const { root: root2, meta, config, plotDefaults } = this;\n const dataDefs = new Map(Object.entries(this.data));\n const paramDefs = new Map(Object.entries(this.params));\n const spec = {};\n if (meta) spec.meta = { ...meta };\n if (config) spec.config = { ...config };\n if (dataDefs?.size) {\n const data = spec.data = {};\n for (const [name2, node] of dataDefs) {\n data[name2] = node.toJSON();\n }\n }\n if (paramDefs?.size) {\n const params = spec.params = {};\n for (const [name2, node] of paramDefs) {\n params[name2] = node.toJSON();\n }\n }\n if (plotDefaults?.length) {\n const defaults22 = spec.plotDefaults = {};\n for (const node of plotDefaults) {\n Object.assign(defaults22, node.toJSON());\n }\n }\n return Object.assign(spec, root2.toJSON());\n }\n};\n\n// ../spec/src/util.js\nfunction paramRef(value) {\n const type2 = typeof value;\n return type2 === \"object\" ? value?.param : type2 === \"string\" ? paramStr(value) : null;\n}\nfunction paramStr(value) {\n return value?.[0] === \"$\" ? value.slice(1) : null;\n}\nfunction toParamRef(name2) {\n return `$${name2}`;\n}\nfunction toArray(value) {\n return [value].flat();\n}\nfunction isArray3(value) {\n return Array.isArray(value);\n}\nfunction isObject3(value) {\n return value !== null && typeof value === \"object\" && !isArray3(value);\n}\nfunction isString(value) {\n return typeof value === \"string\";\n}\nfunction error(message, data) {\n throw Object.assign(Error(message), { data });\n}\nvar re3 = /^(?:[-+]\\d{2})?\\d{4}(?:-\\d{2}(?:-\\d{2})?)?(?:T\\d{2}:\\d{2}(?::\\d{2}(?:\\.\\d{3})?)?(?:Z|[-+]\\d{2}:?\\d{2})?)?$/;\nfunction isoparse(string2, fallback) {\n if (!re3.test(string2 += \"\")) return fallback;\n return new Date(string2);\n}\n\n// ../spec/src/ast/OptionsNode.js\nfunction parseOptions(spec, ctx) {\n const options = {};\n for (const key in spec) {\n options[key] = ctx.maybeSelection(spec[key]);\n }\n return new OptionsNode(options);\n}\nvar OptionsNode = class _OptionsNode extends ASTNode {\n constructor(options) {\n super(OPTIONS);\n this.options = options;\n }\n filter(predicate) {\n const opt = Object.fromEntries(\n Object.entries(this.options).filter(([key, value]) => predicate(key, value))\n );\n return new _OptionsNode(opt);\n }\n instantiate(ctx) {\n const { options } = this;\n const opt = {};\n for (const key in options) {\n opt[key] = options[key].instantiate(ctx);\n }\n return opt;\n }\n codegen(ctx) {\n const { options } = this;\n const opt = [];\n for (const key in options) {\n opt.push(`${key}: ${options[key].codegen(ctx)}`);\n }\n return opt.length ? `{${ctx.maybeLineWrap(opt)}}` : \"\";\n }\n toJSON() {\n const { options } = this;\n const opt = {};\n for (const key in options) {\n opt[key] = options[key].toJSON();\n }\n return opt;\n }\n};\n\n// ../spec/src/ast/DataNode.js\nvar TABLE_DATA = \"table\";\nvar PARQUET_DATA = \"parquet\";\nvar CSV_DATA = \"csv\";\nvar JSON_DATA = \"json\";\nvar SPATIAL_DATA = \"spatial\";\nvar dataFormats = /* @__PURE__ */ new Map([\n [TABLE_DATA, parseTableData],\n [PARQUET_DATA, parseParquetData],\n [CSV_DATA, parseCSVData],\n [JSON_DATA, parseJSONData],\n [SPATIAL_DATA, parseSpatialData]\n]);\nfunction parseData(name2, spec, ctx) {\n const def = resolveDataSpec(spec);\n if (dataFormats.has(def.type)) {\n const parse2 = dataFormats.get(def.type);\n return parse2(name2, def, ctx);\n } else {\n ctx.error(`Unrecognized data format type.`, spec);\n }\n}\nfunction resolveDataSpec(spec) {\n if (isArray3(spec)) spec = { type: \"json\", data: spec };\n if (isString(spec)) spec = { type: \"table\", query: spec };\n return { ...spec, type: inferType2(spec) };\n}\nfunction inferType2(spec) {\n return spec.type || fileExtension(spec.file) || \"table\";\n}\nfunction fileExtension(file) {\n const idx = file?.lastIndexOf(\".\");\n return idx > 0 ? file.slice(idx + 1) : null;\n}\nfunction parseTableData(name2, spec, ctx) {\n const { query, type: type2, ...options } = spec;\n return new TableDataNode(name2, query, parseOptions(options, ctx));\n}\nfunction parseParquetData(name2, spec, ctx) {\n const { file, type: type2, ...options } = spec;\n return new ParquetDataNode(name2, file, parseOptions(options, ctx));\n}\nfunction parseCSVData(name2, spec, ctx) {\n const { file, type: type2, ...options } = spec;\n return new CSVDataNode(name2, file, parseOptions(options, ctx));\n}\nfunction parseJSONData(name2, spec, ctx) {\n const { data, file, type: type2, ...options } = spec;\n const opt = parseOptions(options, ctx);\n return data ? new LiteralJSONDataNode(name2, data, opt) : new JSONDataNode(name2, file, opt);\n}\nfunction parseSpatialData(name2, spec, ctx) {\n const { file, type: type2, ...options } = spec;\n return new SpatialDataNode(name2, file, parseOptions(options, ctx));\n}\nfunction resolveFileURL(file, baseURL) {\n return baseURL ? new URL(file, baseURL).toString() : file;\n}\nfunction codegenOptions(options, ctx) {\n const code = options?.codegen(ctx);\n return code ? `, ${code}` : \"\";\n}\nvar DataNode = class extends ASTNode {\n constructor(name2, format3) {\n super(DATA);\n this.name = name2;\n this.format = format3;\n }\n};\nvar QueryDataNode = class extends DataNode {\n constructor(name2, format3) {\n super(name2, format3);\n }\n /**\n * Instantiate a table creation query.\n * @param {import('../ast-to-dom.js').InstantiateContext} ctx The instantiation context.\n * @returns {string|void} The instantiated query.\n */\n instantiateQuery(ctx) {\n ctx.error(\"instantiateQuery not implemented\");\n }\n /**\n * Code generate a table creation query.\n * @param {import('../ast-to-esm.js').CodegenContext} ctx The code generator context.\n * @returns {string|void} The generated query code.\n */\n codegenQuery(ctx) {\n ctx.error(\"codegenQuery not implemented\");\n }\n /**\n * Instantiate this AST node to use in a live web application.\n * @param {import('../ast-to-dom.js').InstantiateContext} ctx The instantiation context.\n * @returns {*} The instantiated value of this node.\n */\n instantiate(ctx) {\n const query = this.instantiateQuery(ctx);\n if (query) return query;\n }\n /**\n * Generate ESM code for this AST node.\n * @param {import('../ast-to-esm.js').CodegenContext} ctx The code generator context.\n * @returns {string|void} The generated ESM code for the node.\n */\n codegen(ctx) {\n const query = this.codegenQuery(ctx);\n if (query) return query;\n }\n};\nvar TableDataNode = class extends QueryDataNode {\n constructor(name2, query, options) {\n super(name2, TABLE_DATA);\n this.query = query?.trim();\n this.options = options;\n }\n /**\n * Instantiate a table creation query.\n * @param {import('../ast-to-dom.js').InstantiateContext} ctx The instantiation context.\n * @returns {string|void} The instantiated query.\n */\n instantiateQuery(ctx) {\n const { name: name2, query, options } = this;\n if (query) {\n return ctx.api.create(name2, query, options.instantiate(ctx));\n }\n }\n /**\n * Code generate a table creation query.\n * @param {import('../ast-to-esm.js').CodegenContext} ctx The code generator context.\n * @returns {string|void} The generated query code.\n */\n codegenQuery(ctx) {\n const { name: name2, query, options } = this;\n if (query) {\n return `\\`${create(name2, query, options.instantiate(ctx))}\\``;\n }\n }\n toJSON() {\n const { format: format3, query, options } = this;\n return { type: format3, query, ...options.toJSON() };\n }\n};\nvar FileDataNode = class extends QueryDataNode {\n constructor(name2, format3, method, file, options) {\n super(name2, format3);\n this.file = file;\n this.method = method;\n this.options = options;\n }\n /**\n * Instantiate a table creation query.\n * @param {import('../ast-to-dom.js').InstantiateContext} ctx The instantiation context.\n * @returns {string|void} The instantiated query.\n */\n instantiateQuery(ctx) {\n const { name: name2, method, file, options } = this;\n const url = resolveFileURL(file, ctx.baseURL);\n const opt = options?.instantiate(ctx);\n return ctx.api[method](name2, url, opt);\n }\n /**\n * Code generate a table creation query.\n * @param {import('../ast-to-esm.js').CodegenContext} ctx The code generator context.\n * @returns {string|void} The generated query code.\n */\n codegenQuery(ctx) {\n const { name: name2, method, file, options } = this;\n const url = resolveFileURL(file, ctx.baseURL);\n const opt = codegenOptions(options, ctx);\n return `${ctx.ns()}${method}(\"${name2}\", \"${url}\"${opt})`;\n }\n toJSON() {\n const { format: format3, file, options } = this;\n return { type: format3, file, ...options.toJSON() };\n }\n};\nvar SpatialDataNode = class extends FileDataNode {\n constructor(name2, file, options) {\n super(name2, SPATIAL_DATA, \"loadSpatial\", file, options);\n }\n};\nvar ParquetDataNode = class extends FileDataNode {\n constructor(name2, file, options) {\n super(name2, PARQUET_DATA, \"loadParquet\", file, options);\n }\n};\nvar CSVDataNode = class extends FileDataNode {\n constructor(name2, file, options) {\n super(name2, CSV_DATA, \"loadCSV\", file, options);\n }\n};\nvar JSONDataNode = class extends FileDataNode {\n constructor(name2, file, options) {\n super(name2, JSON_DATA, \"loadJSON\", file, options);\n }\n};\nvar LiteralJSONDataNode = class extends QueryDataNode {\n constructor(name2, data, options) {\n super(name2, JSON_DATA);\n this.data = data;\n this.options = options;\n }\n /**\n * Instantiate a table creation query.\n * @param {import('../ast-to-dom.js').InstantiateContext} ctx The instantiation context.\n * @returns {string|void} The instantiated query.\n */\n instantiateQuery(ctx) {\n const { name: name2, data, options } = this;\n return ctx.api.loadObjects(name2, data, options.instantiate(ctx));\n }\n /**\n * Code generate a table creation query.\n * @param {import('../ast-to-esm.js').CodegenContext} ctx The code generator context.\n * @returns {string|void} The generated query code.\n */\n codegenQuery(ctx) {\n const { name: name2, data, options } = this;\n const opt = options ? \",\" + options.codegen(ctx) : \"\";\n const d = \"[\\n \" + data.map((d2) => JSON.stringify(d2)).join(\",\\n \") + \"\\n ]\";\n return `${ctx.ns()}loadObjects(\"${name2}\", ${d}${opt})`;\n }\n toJSON() {\n const { format: format3, data, options } = this;\n return { type: format3, data, ...options.toJSON() };\n }\n};\n\n// ../spec/src/config/extensions.js\nfunction resolveExtensions(ast) {\n const spec = ast.config?.extensions;\n const exts = new Set(spec ? toArray(spec) : []);\n for (const def of Object.values(ast.data)) {\n if (def.format === SPATIAL_DATA) {\n exts.add(\"spatial\");\n }\n }\n return exts;\n}\n\n// ../spec/src/ast-to-dom.js\nasync function astToDOM(ast, options) {\n const { data, params, plotDefaults } = ast;\n const ctx = new InstantiateContext({ plotDefaults, ...options });\n const queries = [];\n const exts = resolveExtensions(ast);\n queries.push(...Array.from(exts).map((name2) => loadExtension(name2)));\n for (const node of Object.values(data)) {\n const query = node.instantiate(ctx);\n if (query) queries.push(query);\n }\n if (queries.length > 0) {\n await ctx.coordinator.exec(queries);\n }\n for (const [name2, node] of Object.entries(params)) {\n if (!ctx.activeParams.has(name2)) {\n const param = node.instantiate(ctx);\n ctx.activeParams.set(name2, param);\n }\n }\n return {\n element: ast.root.instantiate(ctx),\n params: ctx.activeParams\n };\n}\nvar InstantiateContext = class {\n constructor({\n api = createAPIContext(),\n plotDefaults = [],\n params = /* @__PURE__ */ new Map(),\n baseURL = null\n } = {}) {\n this.api = api;\n this.plotDefaults = plotDefaults;\n this.activeParams = params;\n this.baseURL = baseURL;\n this.coordinator = api.context.coordinator;\n }\n error(message, data) {\n error(message, data);\n }\n};\n\n// ../spec/src/ast/LiteralNode.js\nvar LiteralNode = class extends ASTNode {\n constructor(value) {\n super(LITERAL);\n this.value = value;\n }\n instantiate() {\n return this.value;\n }\n codegen(ctx) {\n return ctx.stringify(this.value);\n }\n toJSON() {\n return this.value;\n }\n};\n\n// ../spec/src/ast/SelectionNode.js\nfunction parseSelection(spec, ctx) {\n const { select: select2, include, ...options } = spec;\n const opt = parseOptions(options, ctx);\n if (include) {\n opt.options.include = new IncludeNode(\n toArray(include).map((ref) => ctx.selectionRef(paramRef(ref)))\n );\n }\n return new SelectionNode(select2, opt);\n}\nvar SelectionNode = class extends ASTNode {\n /**\n * Create a Selection AST node.\n * @param {string} select The selection type.\n * @param {OptionsNode} options Selection options.\n */\n constructor(select2 = INTERSECT, options = new OptionsNode({})) {\n super(SELECTION);\n this.select = select2;\n this.options = options;\n }\n instantiate(ctx) {\n const { select: select2, options } = this;\n return ctx.api.Selection[select2](options.instantiate(ctx));\n }\n codegen(ctx) {\n const { select: select2, options } = this;\n return `${ctx.ns()}Selection.${select2}(${options.codegen(ctx)})`;\n }\n toJSON() {\n const { select: select2, options } = this;\n return { select: select2, ...options.toJSON() };\n }\n};\nvar IncludeNode = class extends ASTNode {\n constructor(refs) {\n super(INCLUDE);\n this.refs = refs;\n }\n instantiate(ctx) {\n return this.refs.map((ref) => ref.instantiate(ctx));\n }\n codegen(ctx) {\n return `[${this.refs.map((ref) => ref.codegen(ctx)).join(\", \")}]`;\n }\n toJSON() {\n return this.refs.map((ref) => ref.toJSON());\n }\n};\n\n// ../spec/src/ast/ParamNode.js\nvar paramTypes = /* @__PURE__ */ new Set([VALUE, SINGLE, CROSSFILTER, INTERSECT, UNION]);\nfunction parseParam(spec, ctx) {\n const param = isObject3(spec) ? spec : { value: spec };\n const { select: select2 = VALUE, value, date: date3 } = param;\n if (!paramTypes.has(select2)) {\n ctx.error(`Unrecognized param type: ${select2}`, param);\n }\n if (select2 !== VALUE) {\n return parseSelection(spec, ctx);\n } else if (isArray3(value)) {\n return new ParamNode(value.map((v2) => ctx.maybeParam(v2)));\n } else {\n return new ParamNode(value, date3);\n }\n}\nvar ParamNode = class extends ASTNode {\n constructor(value, date3) {\n super(PARAM);\n this.value = value;\n this.date = date3;\n }\n instantiate(ctx) {\n const { date: date3, value } = this;\n const { Param: Param2 } = ctx.api;\n return isArray3(value) ? Param2.array(value.map((v2) => v2.instantiate(ctx))) : Param2.value(isoparse(date3, value));\n }\n codegen(ctx) {\n const { value, date: date3 } = this;\n const prefix2 = `${ctx.ns()}Param.`;\n return isArray3(value) ? `${prefix2}array([${value.map((v2) => v2.codegen(ctx)).join(\", \")}])` : date3 ? `${prefix2}value(new Date(${JSON.stringify(date3)}))` : `${prefix2}value(${JSON.stringify(value)})`;\n }\n toJSON() {\n const { date: date3, value } = this;\n return isArray3(value) ? value.map((v2) => v2.toJSON()) : date3 ? { date: date3 } : value;\n }\n};\n\n// ../spec/src/ast/ParamRefNode.js\nvar ParamRefNode = class extends ASTNode {\n constructor(name2) {\n super(PARAMREF);\n this.name = name2;\n }\n instantiate(ctx) {\n return ctx.activeParams?.get(this.name);\n }\n codegen(ctx) {\n return toParamRef(this.name);\n }\n toJSON() {\n return toParamRef(this.name);\n }\n};\n\n// ../spec/src/ast/PlotAttributeNode.js\nfunction parseAttribute(key, value, ctx) {\n if (!ctx.plot?.attributes?.has(key)) {\n ctx.error(`Unrecognized attribute: ${key}`);\n }\n return new PlotAttributeNode(\n key,\n value === FIXED ? new PlotFixedNode() : ctx.maybeParam(value)\n );\n}\nvar PlotAttributeNode = class extends ASTNode {\n constructor(name2, value) {\n super(ATTRIBUTE);\n this.name = name2;\n this.value = value;\n }\n instantiate(ctx) {\n const { name: name2, value } = this;\n return ctx.api[name2](value.instantiate(ctx));\n }\n codegen(ctx) {\n const { name: name2, value } = this;\n return `${ctx.tab()}${ctx.ns()}${name2}(${value.codegen(ctx)})`;\n }\n toJSON() {\n const { name: name2, value } = this;\n return { [name2]: value.toJSON() };\n }\n};\nvar PlotFixedNode = class extends ASTNode {\n constructor() {\n super(LITERAL);\n this.value = FIXED;\n }\n instantiate(ctx) {\n return ctx.api[FIXED];\n }\n codegen(ctx) {\n return `${ctx.ns()}${FIXED}`;\n }\n toJSON() {\n return this.value;\n }\n};\n\n// ../spec/src/ast/HConcatNode.js\nfunction parseHConcat(spec, ctx) {\n const children2 = spec[HCONCAT].map((s2) => ctx.parseComponent(s2));\n return new HConcatNode(children2);\n}\nvar HConcatNode = class extends ASTNode {\n constructor(children2) {\n super(HCONCAT, children2);\n }\n instantiate(ctx) {\n return ctx.api[HCONCAT](this.children.map((c4) => c4.instantiate(ctx)));\n }\n codegen(ctx) {\n ctx.indent();\n const items = this.children.map((c4) => c4.codegen(ctx));\n ctx.undent();\n return `${ctx.tab()}${ctx.ns()}${this.type}(\n${items.join(\",\\n\")}\n${ctx.tab()})`;\n }\n toJSON() {\n return { [this.type]: this.children.map((c4) => c4.toJSON()) };\n }\n};\n\n// ../spec/src/ast/HSpaceNode.js\nfunction parseHSpace(spec) {\n return new HSpaceNode(spec[HSPACE]);\n}\nvar HSpaceNode = class extends ASTNode {\n constructor(value) {\n super(HSPACE);\n this.value = value;\n }\n instantiate(ctx) {\n return ctx.api[HSPACE](this.value);\n }\n codegen(ctx) {\n return `${ctx.tab()}${ctx.ns()}${this.type}(${ctx.stringify(this.value)})`;\n }\n toJSON() {\n return { [this.type]: this.value };\n }\n};\n\n// ../spec/src/ast/InputNode.js\nfunction parseInput(spec, ctx) {\n const { [INPUT]: name2, ...options } = spec;\n if (!ctx.inputs?.has(name2)) {\n ctx.error(`Unrecognized input type: ${name2}`, spec);\n }\n return new InputNode(name2, parseOptions(options, ctx));\n}\nvar InputNode = class extends ASTNode {\n constructor(name2, options) {\n super(INPUT);\n this.name = name2;\n this.options = options;\n }\n instantiate(ctx) {\n return ctx.api[this.name](this.options.instantiate(ctx));\n }\n codegen(ctx) {\n const opt = this.options.codegen(ctx);\n return `${ctx.tab()}${ctx.ns()}${this.name}(${opt})`;\n }\n toJSON() {\n const { type: type2, name: name2, options } = this;\n return { [type2]: name2, ...options.toJSON() };\n }\n};\n\n// ../spec/src/ast/PlotLegendNode.js\nfunction parseLegend(spec, ctx) {\n const { [LEGEND]: name2, ...options } = spec;\n const key = `${name2}Legend`;\n if (!ctx.plot?.legends?.has(key)) {\n ctx.error(`Unrecognized legend type: ${name2}`, spec);\n }\n return new PlotLegendNode(key, name2, parseOptions(options, ctx));\n}\nvar PlotLegendNode = class extends ASTNode {\n constructor(key, name2, options) {\n super(LEGEND);\n this.key = key;\n this.name = name2;\n this.options = options;\n }\n instantiate(ctx) {\n return ctx.api[this.key](this.options.instantiate(ctx));\n }\n codegen(ctx) {\n const opt = this.options.codegen(ctx);\n return `${ctx.tab()}${ctx.ns()}${this.key}(${opt})`;\n }\n toJSON() {\n const { type: type2, name: name2, options } = this;\n return { [type2]: name2, ...options.toJSON() };\n }\n};\n\n// ../spec/src/ast/PlotInteractorNode.js\nfunction parseInteractor(spec, ctx) {\n const { [SELECT]: name2, ...options } = spec;\n if (!ctx.plot?.interactors?.has(name2)) {\n ctx.error(`Unrecognized interactor type: ${name2}`, spec);\n }\n return new PlotInteractorNode(name2, parseOptions(options, ctx));\n}\nvar PlotInteractorNode = class extends ASTNode {\n constructor(name2, options) {\n super(INTERACTOR);\n this.name = name2;\n this.options = options;\n }\n instantiate(ctx) {\n return ctx.api[this.name](this.options.instantiate(ctx));\n }\n codegen(ctx) {\n const opt = this.options.codegen(ctx);\n return `${ctx.tab()}${ctx.ns()}${this.name}(${opt})`;\n }\n toJSON() {\n const { name: name2, options } = this;\n return { [SELECT]: name2, ...options.toJSON() };\n }\n};\n\n// ../spec/src/ast/ExpressionNode.js\nfunction parseExpression(spec, ctx) {\n const { label: label2 } = spec;\n const key = spec[SQL] ? SQL : spec[AGG] ? AGG : ctx.error(\"Unrecognized expression type\", spec);\n const expr = spec[key];\n const tokens = expr.split(/(\\\\'|\\\\\"|\"(?:\\\\\"|[^\"])*\"|'(?:\\\\'|[^'])*'|\\$\\w+)/g);\n const spans = [\"\"];\n const params = [];\n for (let i = 0, k2 = 0; i < tokens.length; ++i) {\n const tok = tokens[i];\n if (tok.startsWith(\"$\")) {\n params[k2] = ctx.maybeParam(tok);\n spans[++k2] = \"\";\n } else {\n spans[k2] += tok;\n }\n }\n return new ExpressionNode(expr, spans, params, label2, key === AGG);\n}\nvar ExpressionNode = class extends ASTNode {\n constructor(value, spans, params, label2, aggregate) {\n super(EXPRESSION);\n this.value = value;\n this.spans = spans;\n this.params = params;\n this.label = label2;\n this.aggregate = aggregate;\n }\n instantiate(ctx) {\n const { spans, params, label: label2, aggregate } = this;\n const tag = ctx.api[aggregate ? AGG : SQL];\n const args = params.map((e) => e.instantiate(ctx));\n return tag(spans, ...args).annotate({ label: label2 });\n }\n codegen(ctx) {\n const { spans, params, label: label2, aggregate } = this;\n const method = aggregate ? AGG : SQL;\n let str = \"\";\n const n = params.length;\n for (let i = 0; i < n; ++i) {\n str += spans[i] + \"${\" + params[i].codegen(ctx) + \"}\";\n }\n str += spans[n];\n return `${ctx.ns()}${method}\\`${str}\\`` + (label2 ? `.annotate({ label: ${JSON.stringify(label2)} })` : \"\");\n }\n toJSON() {\n const key = this.aggregate ? AGG : SQL;\n return { [key]: this.value };\n }\n};\n\n// ../spec/src/ast/PlotFromNode.js\nfunction parseMarkData(spec, ctx) {\n if (!spec) {\n return null;\n }\n if (isArray3(spec)) {\n return new LiteralNode(spec);\n }\n const { from: table3, ...options } = spec;\n return new PlotFromNode(table3, parseOptions(options, ctx));\n}\nvar PlotFromNode = class extends ASTNode {\n constructor(table3, options) {\n super(FROM);\n this.table = table3;\n this.options = options;\n }\n instantiate(ctx) {\n const { table: table3, options } = this;\n return ctx.api[FROM](table3, options.instantiate(ctx));\n }\n codegen(ctx) {\n const { type: type2, table: table3, options } = this;\n const opt = options.codegen(ctx);\n return `${ctx.ns()}${type2}(\"${table3}\"${opt ? \", \" + opt : \"\"})`;\n }\n toJSON() {\n const { type: type2, table: table3, options } = this;\n return { [type2]: table3, ...options.toJSON() };\n }\n};\n\n// ../spec/src/ast/TransformNode.js\nfunction toArray2(value) {\n return value == null ? [] : [value].flat();\n}\nfunction parseTransform(spec, ctx) {\n let name2;\n for (const key in spec) {\n if (ctx.transforms.has(key)) {\n name2 = key;\n }\n }\n if (!name2) {\n return;\n }\n if (name2 === \"bin\") {\n const { bin: bin3, ...options } = spec;\n const [arg] = toArray2(bin3);\n return new BinTransformNode(name2, arg, parseOptions(options, ctx));\n } else {\n const args = name2 === \"count\" && !spec[name2] ? [] : toArray2(spec[name2]);\n const options = {\n distinct: spec.distinct,\n orderby: toArray2(spec.orderby).map((v2) => ctx.maybeParam(v2)),\n partitionby: toArray2(spec.partitionby).map((v2) => ctx.maybeParam(v2)),\n rows: spec.rows ? ctx.maybeParam(spec.rows) : null,\n range: spec.range ? ctx.maybeParam(spec.range) : null\n };\n return new TransformNode(name2, args, options);\n }\n}\nvar TransformNode = class extends ASTNode {\n constructor(name2, args, options) {\n super(TRANSFORM);\n this.name = name2;\n this.args = args;\n this.options = options;\n }\n instantiate(ctx) {\n const { name: name2, args, options } = this;\n const { distinct: distinct2, orderby, partitionby, rows, range: range3 } = options;\n let expr = ctx.api[name2](...args);\n if (distinct2) {\n expr = expr.distinct();\n }\n if (orderby.length) {\n expr = expr.orderby(orderby.map((v2) => v2.instantiate(ctx)));\n }\n if (partitionby.length) {\n expr = expr.partitionby(partitionby.map((v2) => v2.instantiate(ctx)));\n }\n if (rows != null) {\n expr = expr.rows(rows.instantiate(ctx));\n } else if (range3 != null) {\n expr = expr.range(range3.instantiate(ctx));\n }\n return expr;\n }\n codegen(ctx) {\n const { name: name2, args, options } = this;\n const { distinct: distinct2, orderby, partitionby, rows, range: range3 } = options;\n let str = `${ctx.ns()}${name2}(` + args.map((v2) => JSON.stringify(v2)).join(\", \") + \")\";\n if (distinct2) {\n str += \".distinct()\";\n }\n if (orderby.length) {\n const p = orderby.map((v2) => v2.codegen(ctx));\n str += `.orderby(${p.join(\", \")})`;\n }\n if (partitionby.length) {\n const p = partitionby.map((v2) => v2.codegen(ctx));\n str += `.partitionby(${p.join(\", \")})`;\n }\n if (rows) {\n str += `.rows(${rows.codegen(ctx)})`;\n } else if (range3) {\n str += `.range(${range3.codegen(ctx)})`;\n }\n return str;\n }\n toJSON() {\n const { name: name2, args, options } = this;\n const { distinct: distinct2, orderby, partitionby, rows, range: range3 } = options;\n const json = { [name2]: simplify(args) };\n if (distinct2) {\n json.distinct = true;\n }\n if (orderby.length) {\n json.orderby = simplify(orderby.map((v2) => v2.toJSON()));\n }\n if (partitionby.length) {\n json.partitionby = simplify(partitionby.map((v2) => v2.toJSON()));\n }\n if (rows) {\n json.rows = rows.toJSON();\n } else if (range3) {\n json.range = range3.toJSON();\n }\n return json;\n }\n};\nvar BinTransformNode = class extends ASTNode {\n constructor(name2, arg, options) {\n super(TRANSFORM);\n this.name = name2;\n this.arg = arg;\n this.options = options;\n }\n instantiate(ctx) {\n const { name: name2, arg, options } = this;\n return ctx.api[name2](arg, options.instantiate(ctx));\n }\n codegen(ctx) {\n const { name: name2, arg, options } = this;\n const opt = options.codegen(ctx);\n return `${ctx.ns()}${name2}(` + JSON.stringify(arg) + (opt ? `, ${opt}` : \"\") + \")\";\n }\n toJSON() {\n const { name: name2, arg, options } = this;\n return { [name2]: arg, ...options.toJSON() };\n }\n};\nfunction simplify(array4) {\n return array4.length === 0 ? \"\" : array4.length === 1 ? array4[0] : array4;\n}\n\n// ../spec/src/ast/PlotMarkNode.js\nfunction maybeTransform(value, ctx) {\n if (isObject3(value)) {\n return value[SQL] || value[AGG] ? parseExpression(value, ctx) : parseTransform(value, ctx);\n }\n}\nfunction parseMark(spec, ctx) {\n const { mark: mark2, data, ...options } = spec;\n if (!ctx.plot?.marks?.has(mark2)) {\n ctx.error(`Unrecognized mark type: ${mark2}`, spec);\n }\n const input3 = parseMarkData(data, ctx);\n const opt = {};\n for (const key in options) {\n const value = options[key];\n opt[key] = maybeTransform(value, ctx) || ctx.maybeParam(value);\n }\n return new PlotMarkNode(mark2, input3, new OptionsNode(opt));\n}\nvar PlotMarkNode = class extends ASTNode {\n constructor(name2, data, options) {\n super(MARK);\n this.name = name2;\n this.data = data;\n this.options = options;\n }\n instantiate(ctx) {\n const { name: name2, data, options } = this;\n const opt = options.instantiate(ctx);\n return data ? ctx.api[name2](data.instantiate(ctx), opt) : ctx.api[name2](opt);\n }\n codegen(ctx) {\n const { name: name2, data, options } = this;\n const d = data ? data.codegen(ctx) : \"\";\n const o = options.codegen(ctx);\n let arg;\n if (d && o) {\n ctx.indent();\n const opt = options.codegen(ctx);\n arg = `\n${ctx.tab()}${d},\n${ctx.tab()}${opt}\n`;\n ctx.undent();\n arg += ctx.tab();\n } else {\n arg = `${d}${o}`;\n }\n return `${ctx.tab()}${ctx.ns()}${name2}(${arg})`;\n }\n toJSON() {\n const { type: type2, name: name2, data, options } = this;\n return {\n [type2]: name2,\n ...data ? { data: data.toJSON() } : {},\n ...options.toJSON()\n };\n }\n};\n\n// ../spec/src/ast/PlotNode.js\nfunction parseTopLevelMark(spec, ctx) {\n return parsePlot({ plot: [spec] }, ctx);\n}\nfunction parsePlot(spec, ctx) {\n const { [PLOT]: entries, ...attrs } = spec;\n const attributes2 = Object.entries(attrs).map(([key, value]) => parseAttribute(key, value, ctx));\n const children2 = entries.map((spec2) => {\n return isString(spec2.mark) ? parseMark(spec2, ctx) : isString(spec2.legend) ? parseLegend(spec2, ctx) : isString(spec2.select) ? parseInteractor(spec2, ctx) : ctx.error(`Invalid plot entry.`, spec2);\n });\n return new PlotNode(children2, attributes2);\n}\nvar PlotNode = class extends ASTNode {\n constructor(children2, attributes2) {\n super(PLOT, children2);\n this.attributes = attributes2;\n }\n instantiate(ctx) {\n const attrs = [\n ...ctx.plotDefaults || [],\n ...this.attributes || []\n ];\n return ctx.api[PLOT](\n this.children.map((c4) => c4.instantiate(ctx)),\n attrs.map((a2) => a2.instantiate(ctx))\n );\n }\n codegen(ctx) {\n const { type: type2, children: children2, attributes: attributes2 } = this;\n ctx.indent();\n const entries = [\n ...children2.map((c4) => c4.codegen(ctx)),\n ...ctx.plotDefaults?.length ? [`${ctx.tab()}...defaultAttributes`] : [],\n ...attributes2.map((a2) => a2.codegen(ctx))\n ].join(\",\\n\");\n ctx.undent();\n return `${ctx.tab()}${ctx.ns()}${type2}(\n${entries}\n${ctx.tab()})`;\n }\n toJSON() {\n const { type: type2, children: children2, attributes: attributes2 } = this;\n const plot3 = { [type2]: children2.map((c4) => c4.toJSON()) };\n for (const a2 of attributes2) {\n Object.assign(plot3, a2.toJSON());\n }\n return plot3;\n }\n};\n\n// ../spec/src/ast/VConcatNode.js\nfunction parseVConcat(spec, ctx) {\n const children2 = spec[VCONCAT].map((s2) => ctx.parseComponent(s2));\n return new VConcatNode(children2);\n}\nvar VConcatNode = class extends ASTNode {\n constructor(children2) {\n super(VCONCAT, children2);\n }\n instantiate(ctx) {\n return ctx.api[VCONCAT](this.children.map((c4) => c4.instantiate(ctx)));\n }\n codegen(ctx) {\n ctx.indent();\n const items = this.children.map((c4) => c4.codegen(ctx));\n ctx.undent();\n return `${ctx.tab()}${ctx.ns()}${this.type}(\n${items.join(\",\\n\")}\n${ctx.tab()})`;\n }\n toJSON() {\n return { [this.type]: this.children.map((c4) => c4.toJSON()) };\n }\n};\n\n// ../spec/src/ast/VSpaceNode.js\nfunction parseVSpace(spec) {\n return new VSpaceNode(spec[VSPACE]);\n}\nvar VSpaceNode = class extends ASTNode {\n constructor(value) {\n super(VSPACE);\n this.value = value;\n }\n instantiate(ctx) {\n return ctx.api[VSPACE](this.value);\n }\n codegen(ctx) {\n return `${ctx.tab()}${ctx.ns()}${this.type}(${ctx.stringify(this.value)})`;\n }\n toJSON() {\n return { [this.type]: this.value };\n }\n};\n\n// ../spec/src/config/components.js\nfunction componentMap(overrides = []) {\n return new Map([\n [PLOT, parsePlot],\n [MARK, parseTopLevelMark],\n [LEGEND, parseLegend],\n [INPUT, parseInput],\n [HCONCAT, parseHConcat],\n [VCONCAT, parseVConcat],\n [HSPACE, parseHSpace],\n [VSPACE, parseVSpace],\n ...overrides\n ]);\n}\n\n// ../spec/src/config/inputs.js\nfunction inputNames(overrides = []) {\n return /* @__PURE__ */ new Set([\n \"menu\",\n \"search\",\n \"slider\",\n \"table\",\n ...overrides\n ]);\n}\n\n// ../spec/src/config/plots.js\nfunction plotNames({\n attributes: attributes2 = plotAttributeNames(),\n interactors = plotInteractorNames(),\n legends = plotLegendNames(),\n marks: marks2 = plotMarkNames()\n} = {}) {\n return { attributes: attributes2, interactors, legends, marks: marks2 };\n}\nfunction plotAttributeNames(overrides = []) {\n return /* @__PURE__ */ new Set([\n ...Object.keys(attributes_exports),\n ...overrides\n ]);\n}\nfunction plotInteractorNames(overrides = []) {\n return /* @__PURE__ */ new Set([\n ...Object.keys(interactors_exports),\n ...overrides\n ]);\n}\nfunction plotLegendNames(overrides = []) {\n return /* @__PURE__ */ new Set([\n ...Object.keys(legends_exports),\n ...overrides\n ]);\n}\nfunction plotMarkNames(overrides = []) {\n return /* @__PURE__ */ new Set([\n ...Object.keys(marks_exports),\n ...overrides\n ]);\n}\n\n// ../spec/src/config/transforms.js\nfunction transformNames(overrides = []) {\n return /* @__PURE__ */ new Set([\n \"argmin\",\n \"argmax\",\n \"avg\",\n \"bin\",\n \"centroid\",\n \"centroidX\",\n \"centroidY\",\n \"count\",\n \"covariance\",\n \"covarPop\",\n \"dateMonth\",\n \"dateMonthDay\",\n \"dateDay\",\n \"first\",\n \"geojson\",\n \"last\",\n \"max\",\n \"median\",\n \"min\",\n \"mode\",\n \"product\",\n \"quantile\",\n \"stddev\",\n \"stddevPop\",\n \"sum\",\n \"variance\",\n \"varPop\",\n \"row_number\",\n \"rank\",\n \"dense_rank\",\n \"percent_rank\",\n \"cume_dist\",\n \"ntile\",\n \"lag\",\n \"lead\",\n \"first_value\",\n \"last_value\",\n \"nth_value\",\n ...overrides\n ]);\n}\n\n// ../spec/src/parse-spec.js\nfunction parseSpec(spec, options) {\n return new ParseContext(options).parse(spec);\n}\nvar ParseContext = class {\n /**\n * Create a new parser context.\n * @param {object} [options]\n * @param {Map} [options.components] Map of component names to parse functions.\n * @param {Set} [options.transforms] The names of allowed transform functions.\n * @param {Set} [options.inputs] The names of supported input widgets.\n * @param {PlotNames} [options.plot] The names of supported plot elements.\n * @param {any[]} [options.params] An array of [name, node] pairs of pre-parsed\n * Param or Selection AST nodes.\n * @param {any[]} [options.datasets] An array of [name, node] pairs of pre-parsed\n * dataset definition AST nodes.\n */\n constructor({\n components = componentMap(),\n transforms = transformNames(),\n inputs = inputNames(),\n plot: plot3 = plotNames(),\n params = [],\n datasets = []\n } = {}) {\n this.components = components;\n this.transforms = transforms;\n this.inputs = inputs;\n this.plot = plot3;\n this.params = new Map(params);\n this.datasets = new Map(datasets);\n }\n parse(spec) {\n const {\n meta,\n config,\n data = {},\n params,\n plotDefaults = {},\n ...root2\n } = spec;\n for (const name2 in data) {\n this.datasets.set(name2, parseData(name2, data[name2], this));\n }\n this.plotDefaults = Object.entries(plotDefaults).map(([key, value]) => parseAttribute(key, value, this));\n for (const name2 in params) {\n this.params.set(name2, parseParam(params[name2], this));\n }\n return new SpecNode(\n this.parseComponent(root2),\n meta ? { ...meta } : void 0,\n config ? { ...config } : void 0,\n Object.fromEntries(this.datasets),\n Object.fromEntries(this.params),\n this.plotDefaults\n );\n }\n parseComponent(spec) {\n for (const [key, parse2] of this.components) {\n const value = spec[key];\n if (value != null) {\n return parse2(spec, this);\n }\n }\n this.error(`Invalid specification.`, spec);\n }\n /**\n * Test if a value is a param reference, if so, generates a parameter\n * definition as needed and returns a new ParamRefNode. Otherwise,\n * returns a LiteralNode for the given value.\n * @param {*} value The value to test.\n * @returns {ParamRefNode|LiteralNode} An AST node for the input value.\n */\n maybeParam(value) {\n const name2 = paramRef(value);\n return name2 ? this.paramRef(name2) : new LiteralNode(value);\n }\n /**\n * Test if a value is a param reference, if so, generates a selection\n * definition as needed and returns a new ParamRefNode. Otherwise,\n * returns a LiteralNode for the given value.\n * @param {*} value The value to test.\n * @returns {ParamRefNode|LiteralNode} An AST node for the input value.\n */\n maybeSelection(value) {\n const name2 = paramRef(value);\n return name2 ? this.selectionRef(name2) : new LiteralNode(value);\n }\n /**\n * Create a parameter reference. Generates a parameter definition if needed\n * and returns a new ParamRefNode.\n * @param {string} name The parameter name.\n * @param {() => ParamNode | SelectionNode} [makeNode] A Param or Selection AST\n * node constructor.\n * @returns {ParamRefNode|null} A node referring to the param or selection.\n */\n paramRef(name2, makeNode = () => new ParamNode()) {\n const { params } = this;\n if (!name2) return null;\n let p = params.get(name2);\n if (!p) {\n p = makeNode();\n params.set(name2, p);\n }\n return new ParamRefNode(name2);\n }\n /**\n * Create a selection reference. Generates a selection definition if needed\n * and returns a new ParamRefNode. Returns null if a non-selection parameter\n * with the same name already exists and *strict* is true.\n * @param {string} name The selection name.\n * @param {boolean} [strict=false] Indicates if this method may return param\n * references (false, default) or only selection references (true).\n * @returns {ParamRefNode|null} A node referring to the param or selection.\n */\n selectionRef(name2, strict = false) {\n const p = this.params.get(name2);\n if (strict && p && !(p instanceof SelectionNode)) {\n return null;\n }\n return this.paramRef(name2, () => new SelectionNode());\n }\n error(message, data) {\n error(message, data);\n }\n};\n\n// ../../node_modules/uuid/dist/esm-browser/stringify.js\nvar byteToHex = [];\nfor (i = 0; i < 256; ++i) {\n byteToHex.push((i + 256).toString(16).slice(1));\n}\nvar i;\nfunction unsafeStringify(arr, offset2 = 0) {\n return (byteToHex[arr[offset2 + 0]] + byteToHex[arr[offset2 + 1]] + byteToHex[arr[offset2 + 2]] + byteToHex[arr[offset2 + 3]] + \"-\" + byteToHex[arr[offset2 + 4]] + byteToHex[arr[offset2 + 5]] + \"-\" + byteToHex[arr[offset2 + 6]] + byteToHex[arr[offset2 + 7]] + \"-\" + byteToHex[arr[offset2 + 8]] + byteToHex[arr[offset2 + 9]] + \"-\" + byteToHex[arr[offset2 + 10]] + byteToHex[arr[offset2 + 11]] + byteToHex[arr[offset2 + 12]] + byteToHex[arr[offset2 + 13]] + byteToHex[arr[offset2 + 14]] + byteToHex[arr[offset2 + 15]]).toLowerCase();\n}\n\n// ../../node_modules/uuid/dist/esm-browser/rng.js\nvar getRandomValues;\nvar rnds8 = new Uint8Array(16);\nfunction rng() {\n if (!getRandomValues) {\n getRandomValues = typeof crypto !== \"undefined\" && crypto.getRandomValues && crypto.getRandomValues.bind(crypto);\n if (!getRandomValues) {\n throw new Error(\"crypto.getRandomValues() not supported. See https://github.com/uuidjs/uuid#getrandomvalues-not-supported\");\n }\n }\n return getRandomValues(rnds8);\n}\n\n// ../../node_modules/uuid/dist/esm-browser/native.js\nvar randomUUID = typeof crypto !== \"undefined\" && crypto.randomUUID && crypto.randomUUID.bind(crypto);\nvar native_default = {\n randomUUID\n};\n\n// ../../node_modules/uuid/dist/esm-browser/v4.js\nfunction v4(options, buf2, offset2) {\n if (native_default.randomUUID && !buf2 && !options) {\n return native_default.randomUUID();\n }\n options = options || {};\n var rnds = options.random || (options.rng || rng)();\n rnds[6] = rnds[6] & 15 | 64;\n rnds[8] = rnds[8] & 63 | 128;\n if (buf2) {\n offset2 = offset2 || 0;\n for (var i = 0; i < 16; ++i) {\n buf2[offset2 + i] = rnds[i];\n }\n return buf2;\n }\n return unsafeStringify(rnds);\n}\nvar v4_default = v4;\n\n// src/index.js\nvar src_default = {\n /** @type {import('anywidget/types').Initialize} */\n initialize(view) {\n view.model.set(\"data_cube_schema\", coordinator().dataCubeIndexer.schema);\n },\n /** @type {import('anywidget/types').Render} */\n render(view) {\n view.el.classList.add(\"mosaic-widget\");\n const getSpec = () => view.model.get(\"spec\");\n const getDataCubeSchema = () => view.model.get(\"data_cube_schema\");\n const logger = coordinator().logger();\n const openQueries = /* @__PURE__ */ new Map();\n function send(query, resolve, reject) {\n const uuid = v4_default();\n openQueries.set(uuid, {\n query,\n startTime: performance.now(),\n resolve,\n reject\n });\n view.model.send({ ...query, uuid });\n }\n const connector = {\n query(query) {\n return new Promise((resolve, reject) => send(query, resolve, reject));\n }\n };\n function reset() {\n coordinator().clear();\n }\n async function updateSpec() {\n const spec = getSpec();\n reset();\n logger.log(\"Setting spec:\", spec);\n const dom = await instantiateSpec(spec);\n view.el.replaceChildren(dom.element);\n const params = {};\n for (const [name2, param] of dom.params) {\n params[name2] = {\n value: param.value,\n ...isSelection(param) ? { predicate: String(param.predicate()) } : {}\n };\n param.addEventListener(\"value\", (value) => {\n params[name2] = {\n value,\n ...isSelection(param) ? { predicate: String(param.predicate()) } : {}\n };\n view.model.set(\"params\", params);\n view.model.save_changes();\n });\n }\n view.model.set(\"params\", params);\n view.model.save_changes();\n }\n view.model.on(\"change:spec\", () => updateSpec());\n function configureCoordinator() {\n coordinator().dataCubeIndexer.schema = getDataCubeSchema();\n }\n view.model.on(\"change:data_cube_schema\", () => configureCoordinator());\n view.model.on(\"msg:custom\", (msg, buffers) => {\n logger.group(`query ${msg.uuid}`);\n logger.log(\"received message\", msg, buffers);\n const query = openQueries.get(msg.uuid);\n openQueries.delete(msg.uuid);\n logger.log(query.query.sql, (performance.now() - query.startTime).toFixed(1));\n if (msg.error) {\n query.reject(msg.error);\n logger.error(msg.error);\n } else {\n switch (msg.type) {\n case \"arrow\": {\n const table3 = decodeIPC2(buffers[0].buffer);\n logger.log(\"table\", table3);\n query.resolve(table3);\n break;\n }\n case \"json\": {\n logger.log(\"json\", msg.result);\n query.resolve(msg.result);\n break;\n }\n default: {\n query.resolve({});\n break;\n }\n }\n }\n logger.groupEnd(\"query\");\n });\n coordinator().databaseConnector(connector);\n configureCoordinator();\n updateSpec();\n return () => {\n reset();\n };\n }\n};\nfunction instantiateSpec(spec) {\n return astToDOM(parseSpec(spec));\n}\nexport {\n src_default as default\n};\n", + "_model_module": "anywidget", + "_model_module_version": "~0.9.*", + "_model_name": "AnyModel", + "_view_count": null, + "_view_module": "anywidget", + "_view_module_version": "~0.9.*", + "_view_name": "AnyView", + "data_cube_schema": "mosaic", + "layout": "IPY_MODEL_8b39014475ce4ed6b27504c98c23e845", + "params": {}, + "spec": { + "height": 200, + "plot": [ + { + "data": { + "from": "aapl" + }, + "mark": "lineY", + "x": "Date", + "y": "Close" + } + ], + "width": 680 + } + } + }, + "8b39014475ce4ed6b27504c98c23e845": { + "model_module": "@jupyter-widgets/base", + "model_name": "LayoutModel", + "model_module_version": "1.2.0", + "state": { + "_model_module": "@jupyter-widgets/base", + "_model_module_version": "1.2.0", + "_model_name": "LayoutModel", + "_view_count": null, + "_view_module": "@jupyter-widgets/base", + "_view_module_version": "1.2.0", + "_view_name": "LayoutView", + "align_content": null, + "align_items": null, + "align_self": null, + "border": null, + "bottom": null, + "display": null, + "flex": null, + "flex_flow": null, + "grid_area": null, + "grid_auto_columns": null, + "grid_auto_flow": null, + "grid_auto_rows": null, + "grid_column": null, + "grid_gap": null, + "grid_row": null, + "grid_template_areas": null, + "grid_template_columns": null, + "grid_template_rows": null, + "height": null, + "justify_content": null, + "justify_items": null, + "left": null, + "margin": null, + "max_height": null, + "max_width": null, + "min_height": null, + "min_width": null, + "object_fit": null, + "object_position": null, + "order": null, + "overflow": null, + "overflow_x": null, + "overflow_y": null, + "padding": null, + "right": null, + "top": null, + "visibility": null, + "width": null + } + } + } + } + }, + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/" + }, + "collapsed": true, + "id": "CHxC8jtcxTSv", + "outputId": "6480809a-5069-48bb-a3c5-1904e23639bf" + }, + "outputs": [ + { + "output_type": "stream", + "name": "stdout", + "text": [ + "Requirement already satisfied: pandas in /usr/local/lib/python3.10/dist-packages (2.2.2)\n", + "Collecting mosaic_widget\n", + " Downloading mosaic_widget-0.11.0-py3-none-any.whl.metadata (2.0 kB)\n", + "Requirement already satisfied: numpy>=1.22.4 in /usr/local/lib/python3.10/dist-packages (from pandas) (1.26.4)\n", + "Requirement already satisfied: python-dateutil>=2.8.2 in /usr/local/lib/python3.10/dist-packages (from pandas) (2.8.2)\n", + "Requirement already satisfied: pytz>=2020.1 in /usr/local/lib/python3.10/dist-packages (from pandas) (2024.2)\n", + "Requirement already satisfied: tzdata>=2022.7 in /usr/local/lib/python3.10/dist-packages (from pandas) (2024.2)\n", + "Collecting anywidget>=0.9.0 (from mosaic_widget)\n", + " Downloading anywidget-0.9.13-py3-none-any.whl.metadata (7.2 kB)\n", + "Collecting duckdb==1.0.0 (from mosaic_widget)\n", + " Downloading duckdb-1.0.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.metadata (762 bytes)\n", + "Requirement already satisfied: pyarrow in /usr/local/lib/python3.10/dist-packages (from mosaic_widget) (17.0.0)\n", + "Requirement already satisfied: ipywidgets>=7.6.0 in /usr/local/lib/python3.10/dist-packages (from anywidget>=0.9.0->mosaic_widget) (7.7.1)\n", + "Collecting psygnal>=0.8.1 (from anywidget>=0.9.0->mosaic_widget)\n", + " Downloading psygnal-0.11.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.metadata (7.2 kB)\n", + "Requirement already satisfied: typing-extensions>=4.2.0 in /usr/local/lib/python3.10/dist-packages (from anywidget>=0.9.0->mosaic_widget) (4.12.2)\n", + "Requirement already satisfied: six>=1.5 in /usr/local/lib/python3.10/dist-packages (from python-dateutil>=2.8.2->pandas) (1.16.0)\n", + "Requirement already satisfied: ipykernel>=4.5.1 in /usr/local/lib/python3.10/dist-packages (from ipywidgets>=7.6.0->anywidget>=0.9.0->mosaic_widget) (5.5.6)\n", + "Requirement already satisfied: ipython-genutils~=0.2.0 in /usr/local/lib/python3.10/dist-packages (from ipywidgets>=7.6.0->anywidget>=0.9.0->mosaic_widget) (0.2.0)\n", + "Requirement already satisfied: traitlets>=4.3.1 in /usr/local/lib/python3.10/dist-packages (from ipywidgets>=7.6.0->anywidget>=0.9.0->mosaic_widget) (5.7.1)\n", + "Requirement already satisfied: widgetsnbextension~=3.6.0 in /usr/local/lib/python3.10/dist-packages (from ipywidgets>=7.6.0->anywidget>=0.9.0->mosaic_widget) (3.6.10)\n", + "Requirement already satisfied: ipython>=4.0.0 in /usr/local/lib/python3.10/dist-packages (from ipywidgets>=7.6.0->anywidget>=0.9.0->mosaic_widget) (7.34.0)\n", + "Requirement already satisfied: jupyterlab-widgets>=1.0.0 in /usr/local/lib/python3.10/dist-packages (from ipywidgets>=7.6.0->anywidget>=0.9.0->mosaic_widget) (3.0.13)\n", + "Requirement already satisfied: jupyter-client in /usr/local/lib/python3.10/dist-packages (from ipykernel>=4.5.1->ipywidgets>=7.6.0->anywidget>=0.9.0->mosaic_widget) (6.1.12)\n", + "Requirement already satisfied: tornado>=4.2 in /usr/local/lib/python3.10/dist-packages (from ipykernel>=4.5.1->ipywidgets>=7.6.0->anywidget>=0.9.0->mosaic_widget) (6.3.3)\n", + "Requirement already satisfied: setuptools>=18.5 in /usr/local/lib/python3.10/dist-packages (from ipython>=4.0.0->ipywidgets>=7.6.0->anywidget>=0.9.0->mosaic_widget) (75.1.0)\n", + "Collecting jedi>=0.16 (from ipython>=4.0.0->ipywidgets>=7.6.0->anywidget>=0.9.0->mosaic_widget)\n", + " Downloading jedi-0.19.2-py2.py3-none-any.whl.metadata (22 kB)\n", + "Requirement already satisfied: decorator in /usr/local/lib/python3.10/dist-packages (from ipython>=4.0.0->ipywidgets>=7.6.0->anywidget>=0.9.0->mosaic_widget) (4.4.2)\n", + "Requirement already satisfied: pickleshare in /usr/local/lib/python3.10/dist-packages (from ipython>=4.0.0->ipywidgets>=7.6.0->anywidget>=0.9.0->mosaic_widget) (0.7.5)\n", + "Requirement already satisfied: prompt-toolkit!=3.0.0,!=3.0.1,<3.1.0,>=2.0.0 in /usr/local/lib/python3.10/dist-packages (from ipython>=4.0.0->ipywidgets>=7.6.0->anywidget>=0.9.0->mosaic_widget) (3.0.48)\n", + "Requirement already satisfied: pygments in /usr/local/lib/python3.10/dist-packages (from ipython>=4.0.0->ipywidgets>=7.6.0->anywidget>=0.9.0->mosaic_widget) (2.18.0)\n", + "Requirement already satisfied: backcall in /usr/local/lib/python3.10/dist-packages (from ipython>=4.0.0->ipywidgets>=7.6.0->anywidget>=0.9.0->mosaic_widget) (0.2.0)\n", + "Requirement already satisfied: matplotlib-inline in /usr/local/lib/python3.10/dist-packages (from ipython>=4.0.0->ipywidgets>=7.6.0->anywidget>=0.9.0->mosaic_widget) (0.1.7)\n", + "Requirement already satisfied: pexpect>4.3 in /usr/local/lib/python3.10/dist-packages (from ipython>=4.0.0->ipywidgets>=7.6.0->anywidget>=0.9.0->mosaic_widget) (4.9.0)\n", + "Requirement already satisfied: notebook>=4.4.1 in /usr/local/lib/python3.10/dist-packages (from widgetsnbextension~=3.6.0->ipywidgets>=7.6.0->anywidget>=0.9.0->mosaic_widget) (6.5.5)\n", + "Requirement already satisfied: parso<0.9.0,>=0.8.4 in /usr/local/lib/python3.10/dist-packages (from jedi>=0.16->ipython>=4.0.0->ipywidgets>=7.6.0->anywidget>=0.9.0->mosaic_widget) (0.8.4)\n", + "Requirement already satisfied: jinja2 in /usr/local/lib/python3.10/dist-packages (from notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets>=7.6.0->anywidget>=0.9.0->mosaic_widget) (3.1.4)\n", + "Requirement already satisfied: pyzmq<25,>=17 in /usr/local/lib/python3.10/dist-packages (from notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets>=7.6.0->anywidget>=0.9.0->mosaic_widget) (24.0.1)\n", + "Requirement already satisfied: argon2-cffi in /usr/local/lib/python3.10/dist-packages (from notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets>=7.6.0->anywidget>=0.9.0->mosaic_widget) (23.1.0)\n", + "Requirement already satisfied: jupyter-core>=4.6.1 in /usr/local/lib/python3.10/dist-packages (from notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets>=7.6.0->anywidget>=0.9.0->mosaic_widget) (5.7.2)\n", + "Requirement already satisfied: nbformat in /usr/local/lib/python3.10/dist-packages (from notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets>=7.6.0->anywidget>=0.9.0->mosaic_widget) (5.10.4)\n", + "Requirement already satisfied: nbconvert>=5 in /usr/local/lib/python3.10/dist-packages (from notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets>=7.6.0->anywidget>=0.9.0->mosaic_widget) (7.16.4)\n", + "Requirement already satisfied: nest-asyncio>=1.5 in /usr/local/lib/python3.10/dist-packages (from notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets>=7.6.0->anywidget>=0.9.0->mosaic_widget) (1.6.0)\n", + "Requirement already satisfied: Send2Trash>=1.8.0 in /usr/local/lib/python3.10/dist-packages (from notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets>=7.6.0->anywidget>=0.9.0->mosaic_widget) (1.8.3)\n", + "Requirement already satisfied: terminado>=0.8.3 in /usr/local/lib/python3.10/dist-packages (from notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets>=7.6.0->anywidget>=0.9.0->mosaic_widget) (0.18.1)\n", + "Requirement already satisfied: prometheus-client in /usr/local/lib/python3.10/dist-packages (from notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets>=7.6.0->anywidget>=0.9.0->mosaic_widget) (0.21.0)\n", + "Requirement already satisfied: nbclassic>=0.4.7 in /usr/local/lib/python3.10/dist-packages (from notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets>=7.6.0->anywidget>=0.9.0->mosaic_widget) (1.1.0)\n", + "Requirement already satisfied: ptyprocess>=0.5 in /usr/local/lib/python3.10/dist-packages (from pexpect>4.3->ipython>=4.0.0->ipywidgets>=7.6.0->anywidget>=0.9.0->mosaic_widget) (0.7.0)\n", + "Requirement already satisfied: wcwidth in /usr/local/lib/python3.10/dist-packages (from prompt-toolkit!=3.0.0,!=3.0.1,<3.1.0,>=2.0.0->ipython>=4.0.0->ipywidgets>=7.6.0->anywidget>=0.9.0->mosaic_widget) (0.2.13)\n", + "Requirement already satisfied: platformdirs>=2.5 in /usr/local/lib/python3.10/dist-packages (from jupyter-core>=4.6.1->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets>=7.6.0->anywidget>=0.9.0->mosaic_widget) (4.3.6)\n", + "Requirement already satisfied: notebook-shim>=0.2.3 in /usr/local/lib/python3.10/dist-packages (from nbclassic>=0.4.7->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets>=7.6.0->anywidget>=0.9.0->mosaic_widget) (0.2.4)\n", + "Requirement already satisfied: beautifulsoup4 in /usr/local/lib/python3.10/dist-packages (from nbconvert>=5->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets>=7.6.0->anywidget>=0.9.0->mosaic_widget) (4.12.3)\n", + "Requirement already satisfied: bleach!=5.0.0 in /usr/local/lib/python3.10/dist-packages (from nbconvert>=5->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets>=7.6.0->anywidget>=0.9.0->mosaic_widget) (6.2.0)\n", + "Requirement already satisfied: defusedxml in /usr/local/lib/python3.10/dist-packages (from nbconvert>=5->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets>=7.6.0->anywidget>=0.9.0->mosaic_widget) (0.7.1)\n", + "Requirement already satisfied: jupyterlab-pygments in /usr/local/lib/python3.10/dist-packages (from nbconvert>=5->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets>=7.6.0->anywidget>=0.9.0->mosaic_widget) (0.3.0)\n", + "Requirement already satisfied: markupsafe>=2.0 in /usr/local/lib/python3.10/dist-packages (from nbconvert>=5->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets>=7.6.0->anywidget>=0.9.0->mosaic_widget) (3.0.2)\n", + "Requirement already satisfied: mistune<4,>=2.0.3 in /usr/local/lib/python3.10/dist-packages (from nbconvert>=5->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets>=7.6.0->anywidget>=0.9.0->mosaic_widget) (3.0.2)\n", + "Requirement already satisfied: nbclient>=0.5.0 in /usr/local/lib/python3.10/dist-packages (from nbconvert>=5->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets>=7.6.0->anywidget>=0.9.0->mosaic_widget) (0.10.0)\n", + "Requirement already satisfied: packaging in /usr/local/lib/python3.10/dist-packages (from nbconvert>=5->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets>=7.6.0->anywidget>=0.9.0->mosaic_widget) (24.1)\n", + "Requirement already satisfied: pandocfilters>=1.4.1 in /usr/local/lib/python3.10/dist-packages (from nbconvert>=5->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets>=7.6.0->anywidget>=0.9.0->mosaic_widget) (1.5.1)\n", + "Requirement already satisfied: tinycss2 in /usr/local/lib/python3.10/dist-packages (from nbconvert>=5->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets>=7.6.0->anywidget>=0.9.0->mosaic_widget) (1.4.0)\n", + "Requirement already satisfied: fastjsonschema>=2.15 in /usr/local/lib/python3.10/dist-packages (from nbformat->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets>=7.6.0->anywidget>=0.9.0->mosaic_widget) (2.20.0)\n", + "Requirement already satisfied: jsonschema>=2.6 in /usr/local/lib/python3.10/dist-packages (from nbformat->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets>=7.6.0->anywidget>=0.9.0->mosaic_widget) (4.23.0)\n", + "Requirement already satisfied: argon2-cffi-bindings in /usr/local/lib/python3.10/dist-packages (from argon2-cffi->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets>=7.6.0->anywidget>=0.9.0->mosaic_widget) (21.2.0)\n", + "Requirement already satisfied: webencodings in /usr/local/lib/python3.10/dist-packages (from bleach!=5.0.0->nbconvert>=5->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets>=7.6.0->anywidget>=0.9.0->mosaic_widget) (0.5.1)\n", + "Requirement already satisfied: attrs>=22.2.0 in /usr/local/lib/python3.10/dist-packages (from jsonschema>=2.6->nbformat->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets>=7.6.0->anywidget>=0.9.0->mosaic_widget) (24.2.0)\n", + "Requirement already satisfied: jsonschema-specifications>=2023.03.6 in /usr/local/lib/python3.10/dist-packages (from jsonschema>=2.6->nbformat->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets>=7.6.0->anywidget>=0.9.0->mosaic_widget) (2024.10.1)\n", + "Requirement already satisfied: referencing>=0.28.4 in /usr/local/lib/python3.10/dist-packages (from jsonschema>=2.6->nbformat->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets>=7.6.0->anywidget>=0.9.0->mosaic_widget) (0.35.1)\n", + "Requirement already satisfied: rpds-py>=0.7.1 in /usr/local/lib/python3.10/dist-packages (from jsonschema>=2.6->nbformat->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets>=7.6.0->anywidget>=0.9.0->mosaic_widget) (0.20.1)\n", + "Requirement already satisfied: jupyter-server<3,>=1.8 in /usr/local/lib/python3.10/dist-packages (from notebook-shim>=0.2.3->nbclassic>=0.4.7->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets>=7.6.0->anywidget>=0.9.0->mosaic_widget) (1.24.0)\n", + "Requirement already satisfied: cffi>=1.0.1 in /usr/local/lib/python3.10/dist-packages (from argon2-cffi-bindings->argon2-cffi->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets>=7.6.0->anywidget>=0.9.0->mosaic_widget) (1.17.1)\n", + "Requirement already satisfied: soupsieve>1.2 in /usr/local/lib/python3.10/dist-packages (from beautifulsoup4->nbconvert>=5->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets>=7.6.0->anywidget>=0.9.0->mosaic_widget) (2.6)\n", + "Requirement already satisfied: pycparser in /usr/local/lib/python3.10/dist-packages (from cffi>=1.0.1->argon2-cffi-bindings->argon2-cffi->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets>=7.6.0->anywidget>=0.9.0->mosaic_widget) (2.22)\n", + "Requirement already satisfied: anyio<4,>=3.1.0 in /usr/local/lib/python3.10/dist-packages (from jupyter-server<3,>=1.8->notebook-shim>=0.2.3->nbclassic>=0.4.7->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets>=7.6.0->anywidget>=0.9.0->mosaic_widget) (3.7.1)\n", + "Requirement already satisfied: websocket-client in /usr/local/lib/python3.10/dist-packages (from jupyter-server<3,>=1.8->notebook-shim>=0.2.3->nbclassic>=0.4.7->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets>=7.6.0->anywidget>=0.9.0->mosaic_widget) (1.8.0)\n", + "Requirement already satisfied: idna>=2.8 in /usr/local/lib/python3.10/dist-packages (from anyio<4,>=3.1.0->jupyter-server<3,>=1.8->notebook-shim>=0.2.3->nbclassic>=0.4.7->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets>=7.6.0->anywidget>=0.9.0->mosaic_widget) (3.10)\n", + "Requirement already satisfied: sniffio>=1.1 in /usr/local/lib/python3.10/dist-packages (from anyio<4,>=3.1.0->jupyter-server<3,>=1.8->notebook-shim>=0.2.3->nbclassic>=0.4.7->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets>=7.6.0->anywidget>=0.9.0->mosaic_widget) (1.3.1)\n", + "Requirement already satisfied: exceptiongroup in /usr/local/lib/python3.10/dist-packages (from anyio<4,>=3.1.0->jupyter-server<3,>=1.8->notebook-shim>=0.2.3->nbclassic>=0.4.7->notebook>=4.4.1->widgetsnbextension~=3.6.0->ipywidgets>=7.6.0->anywidget>=0.9.0->mosaic_widget) (1.2.2)\n", + "Downloading mosaic_widget-0.11.0-py3-none-any.whl (286 kB)\n", + "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m286.8/286.8 kB\u001b[0m \u001b[31m6.1 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", + "\u001b[?25hDownloading duckdb-1.0.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (18.5 MB)\n", + "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m18.5/18.5 MB\u001b[0m \u001b[31m58.0 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", + "\u001b[?25hDownloading anywidget-0.9.13-py3-none-any.whl (213 kB)\n", + "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m213.7/213.7 kB\u001b[0m \u001b[31m14.4 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", + "\u001b[?25hDownloading psygnal-0.11.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (727 kB)\n", + "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m727.4/727.4 kB\u001b[0m \u001b[31m18.9 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", + "\u001b[?25hDownloading jedi-0.19.2-py2.py3-none-any.whl (1.6 MB)\n", + "\u001b[2K \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m1.6/1.6 MB\u001b[0m \u001b[31m49.9 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n", + "\u001b[?25hInstalling collected packages: psygnal, jedi, duckdb, anywidget, mosaic_widget\n", + " Attempting uninstall: duckdb\n", + " Found existing installation: duckdb 1.1.3\n", + " Uninstalling duckdb-1.1.3:\n", + " Successfully uninstalled duckdb-1.1.3\n", + "Successfully installed anywidget-0.9.13 duckdb-1.0.0 jedi-0.19.2 mosaic_widget-0.11.0 psygnal-0.11.1\n" + ] + } + ], + "source": [ + "!pip install pandas mosaic_widget" + ] + }, + { + "cell_type": "code", + "source": [ + "import pandas as pd\n", + "from mosaic_widget import MosaicWidget" + ], + "metadata": { + "id": "AdrxigM4yLMf" + }, + "execution_count": 2, + "outputs": [] + }, + { + "cell_type": "code", + "source": [ + "weather = pd.read_csv(\"https://uwdata.github.io/mosaic-datasets/data/seattle-weather.csv\", parse_dates=['date'])\n", + "weather" + ], + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 424 + }, + "id": "kl0i0QznyNbw", + "outputId": "694638df-9164-4616-dd6f-cc4d7f84688f" + }, + "execution_count": 3, + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": [ + " date precipitation temp_max temp_min wind weather\n", + "0 2012-01-01 0.0 12.8 5.0 4.7 drizzle\n", + "1 2012-01-02 10.9 10.6 2.8 4.5 rain\n", + "2 2012-01-03 0.8 11.7 7.2 2.3 rain\n", + "3 2012-01-04 20.3 12.2 5.6 4.7 rain\n", + "4 2012-01-05 1.3 8.9 2.8 6.1 rain\n", + "... ... ... ... ... ... ...\n", + "1456 2015-12-27 8.6 4.4 1.7 2.9 rain\n", + "1457 2015-12-28 1.5 5.0 1.7 1.3 rain\n", + "1458 2015-12-29 0.0 7.2 0.6 2.6 fog\n", + "1459 2015-12-30 0.0 5.6 -1.0 3.4 sun\n", + "1460 2015-12-31 0.0 5.6 -2.1 3.5 sun\n", + "\n", + "[1461 rows x 6 columns]" + ], + "text/html": [ + "\n", + "
\n", + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
dateprecipitationtemp_maxtemp_minwindweather
02012-01-010.012.85.04.7drizzle
12012-01-0210.910.62.84.5rain
22012-01-030.811.77.22.3rain
32012-01-0420.312.25.64.7rain
42012-01-051.38.92.86.1rain
.....................
14562015-12-278.64.41.72.9rain
14572015-12-281.55.01.71.3rain
14582015-12-290.07.20.62.6fog
14592015-12-300.05.6-1.03.4sun
14602015-12-310.05.6-2.13.5sun
\n", + "

1461 rows × 6 columns

\n", + "
\n", + "
\n", + "\n", + "
\n", + " \n", + "\n", + " \n", + "\n", + " \n", + "
\n", + "\n", + "\n", + "
\n", + " \n", + "\n", + "\n", + "\n", + " \n", + "
\n", + "\n", + "
\n", + " \n", + " \n", + " \n", + "
\n", + "\n", + "
\n", + "
\n" + ], + "application/vnd.google.colaboratory.intrinsic+json": { + "type": "dataframe", + "variable_name": "weather", + "summary": "{\n \"name\": \"weather\",\n \"rows\": 1461,\n \"fields\": [\n {\n \"column\": \"date\",\n \"properties\": {\n \"dtype\": \"date\",\n \"min\": \"2012-01-01 00:00:00\",\n \"max\": \"2015-12-31 00:00:00\",\n \"num_unique_values\": 1461,\n \"samples\": [\n \"2014-06-11 00:00:00\",\n \"2015-01-10 00:00:00\",\n \"2013-02-17 00:00:00\"\n ],\n \"semantic_type\": \"\",\n \"description\": \"\"\n }\n },\n {\n \"column\": \"precipitation\",\n \"properties\": {\n \"dtype\": \"number\",\n \"std\": 6.680194322314731,\n \"min\": 0.0,\n \"max\": 55.9,\n \"num_unique_values\": 111,\n \"samples\": [\n 43.4,\n 8.1,\n 1.3\n ],\n \"semantic_type\": \"\",\n \"description\": \"\"\n }\n },\n {\n \"column\": \"temp_max\",\n \"properties\": {\n \"dtype\": \"number\",\n \"std\": 7.349758097360185,\n \"min\": -1.6,\n \"max\": 35.6,\n \"num_unique_values\": 67,\n \"samples\": [\n 25.6,\n 8.3,\n 8.9\n ],\n \"semantic_type\": \"\",\n \"description\": \"\"\n }\n },\n {\n \"column\": \"temp_min\",\n \"properties\": {\n \"dtype\": \"number\",\n \"std\": 5.023004179961267,\n \"min\": -7.1,\n \"max\": 18.3,\n \"num_unique_values\": 55,\n \"samples\": [\n 13.3,\n 0.6,\n 14.4\n ],\n \"semantic_type\": \"\",\n \"description\": \"\"\n }\n },\n {\n \"column\": \"wind\",\n \"properties\": {\n \"dtype\": \"number\",\n \"std\": 1.4378250588746244,\n \"min\": 0.4,\n \"max\": 9.5,\n \"num_unique_values\": 79,\n \"samples\": [\n 8.1,\n 4.7,\n 2.6\n ],\n \"semantic_type\": \"\",\n \"description\": \"\"\n }\n },\n {\n \"column\": \"weather\",\n \"properties\": {\n \"dtype\": \"category\",\n \"num_unique_values\": 5,\n \"samples\": [\n \"rain\",\n \"fog\",\n \"sun\"\n ],\n \"semantic_type\": \"\",\n \"description\": \"\"\n }\n }\n ]\n}" + } + }, + "metadata": {}, + "execution_count": 3 + } + ] + }, + { + "cell_type": "code", + "source": [ + "spec = {\n", + " 'colorDomain': '$domain', 'colorRange': '$colors', 'plot': [{'data': {'filterBy': '$click', 'from': 'weather'}, 'fill': 'weather', 'mark': 'dot', 'r': 'precipitation', 'x': {'dateMonthDay': 'date'}, 'y': 'temp_max'}], 'rDomain': 'Fixed', 'rRange': [2, 10], 'width': 800, 'xTickFormat': '%b', 'xyDomain': 'Fixed'\n", + "}" + ], + "metadata": { + "id": "PwFrBqr_yO1B" + }, + "execution_count": 5, + "outputs": [] + }, + { + "cell_type": "code", + "source": [ + "MosaicWidget(spec, data = {\"weather\": weather})" + ], + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 417, + "referenced_widgets": [ + "eb92c981b51c4bc29cca78b2cd5a3f50", + "a5b987df120a4739848e2e8bd96a2fef" + ] + }, + "id": "gLSsFTRGyfPA", + "outputId": "63163b3b-607d-4b66-df41-d7d18d032bae" + }, + "execution_count": 6, + "outputs": [ + { + "output_type": "display_data", + "data": { + "text/plain": [ + "MosaicWidget(spec={'colorDomain': '$domain', 'colorRange': '$colors', 'plot': [{'data': {'filterBy': '$click',…" + ], + "application/vnd.jupyter.widget-view+json": { + "version_major": 2, + "version_minor": 0, + "model_id": "eb92c981b51c4bc29cca78b2cd5a3f50" + } + }, + "metadata": { + "application/vnd.jupyter.widget-view+json": { + "colab": { + "custom_widget_manager": { + "url": "https://ssl.gstatic.com/colaboratory-static/widgets/colab-cdn-widget-manager/2b70e893a8ba7c0f/manager.min.js" + } + } + } + } + } + ] + }, + { + "cell_type": "code", + "source": [ + "spec = {'height': 200, 'plot': [{'data': {'from': 'aapl'}, 'mark': 'lineY', 'x': 'Date', 'y': 'Close'}], 'width': 680}" + ], + "metadata": { + "id": "KLWVL2CdzqNz" + }, + "execution_count": 7, + "outputs": [] + }, + { + "cell_type": "code", + "source": [ + "stocks = pd.read_csv(\"https://uwdata.github.io/mosaic-datasets/data/stocks.csv\", parse_dates=['Date'])\n", + "stocks" + ], + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 424 + }, + "id": "CLuHuy-Mz2lm", + "outputId": "c29552fc-d7bc-4eac-d9f3-1e4e590bce0f" + }, + "execution_count": 9, + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": [ + " Symbol Date Open High Low Close \\\n", + "0 AAPL 2013-05-13 64.501427 65.414284 64.500000 64.962860 \n", + "1 AAPL 2013-05-14 64.835716 65.028572 63.164288 63.408573 \n", + "2 AAPL 2013-05-15 62.737144 63.000000 60.337143 61.264286 \n", + "3 AAPL 2013-05-16 60.462856 62.549999 59.842857 62.082859 \n", + "4 AAPL 2013-05-17 62.721428 62.869999 61.572857 61.894287 \n", + "... ... ... ... ... ... ... \n", + "5035 IBM 2018-05-07 144.000000 144.320007 142.639999 143.220001 \n", + "5036 IBM 2018-05-08 143.000000 143.509995 142.059998 143.000000 \n", + "5037 IBM 2018-05-09 141.899994 143.020004 141.279999 142.610001 \n", + "5038 IBM 2018-05-10 143.149994 144.330002 143.009995 144.240005 \n", + "5039 IBM 2018-05-11 144.110001 144.850006 143.580002 144.139999 \n", + "\n", + " AdjClose Volume \n", + "0 50.961628 79237200 \n", + "1 49.742329 111779500 \n", + "2 48.060188 185403400 \n", + "3 48.702328 150801000 \n", + "4 48.554409 106976100 \n", + "... ... ... \n", + "5035 141.647583 3657000 \n", + "5036 141.430008 5369100 \n", + "5037 142.610001 4196000 \n", + "5038 144.240005 3726600 \n", + "5039 144.139999 3069400 \n", + "\n", + "[5040 rows x 8 columns]" + ], + "text/html": [ + "\n", + "
\n", + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
SymbolDateOpenHighLowCloseAdjCloseVolume
0AAPL2013-05-1364.50142765.41428464.50000064.96286050.96162879237200
1AAPL2013-05-1464.83571665.02857263.16428863.40857349.742329111779500
2AAPL2013-05-1562.73714463.00000060.33714361.26428648.060188185403400
3AAPL2013-05-1660.46285662.54999959.84285762.08285948.702328150801000
4AAPL2013-05-1762.72142862.86999961.57285761.89428748.554409106976100
...........................
5035IBM2018-05-07144.000000144.320007142.639999143.220001141.6475833657000
5036IBM2018-05-08143.000000143.509995142.059998143.000000141.4300085369100
5037IBM2018-05-09141.899994143.020004141.279999142.610001142.6100014196000
5038IBM2018-05-10143.149994144.330002143.009995144.240005144.2400053726600
5039IBM2018-05-11144.110001144.850006143.580002144.139999144.1399993069400
\n", + "

5040 rows × 8 columns

\n", + "
\n", + "
\n", + "\n", + "
\n", + " \n", + "\n", + " \n", + "\n", + " \n", + "
\n", + "\n", + "\n", + "
\n", + " \n", + "\n", + "\n", + "\n", + " \n", + "
\n", + "\n", + "
\n", + " \n", + " \n", + " \n", + "
\n", + "\n", + "
\n", + "
\n" + ], + "application/vnd.google.colaboratory.intrinsic+json": { + "type": "dataframe", + "variable_name": "stocks", + "summary": "{\n \"name\": \"stocks\",\n \"rows\": 5040,\n \"fields\": [\n {\n \"column\": \"Symbol\",\n \"properties\": {\n \"dtype\": \"category\",\n \"num_unique_values\": 4,\n \"samples\": [\n \"AMZN\",\n \"IBM\",\n \"AAPL\"\n ],\n \"semantic_type\": \"\",\n \"description\": \"\"\n }\n },\n {\n \"column\": \"Date\",\n \"properties\": {\n \"dtype\": \"date\",\n \"min\": \"2013-05-13 00:00:00\",\n \"max\": \"2018-05-11 00:00:00\",\n \"num_unique_values\": 1260,\n \"samples\": [\n \"2013-08-29 00:00:00\",\n \"2017-06-08 00:00:00\",\n \"2013-07-15 00:00:00\"\n ],\n \"semantic_type\": \"\",\n \"description\": \"\"\n }\n },\n {\n \"column\": \"Open\",\n \"properties\": {\n \"dtype\": \"number\",\n \"std\": 331.7405922174677,\n \"min\": 55.908573,\n \"max\": 1634.01001,\n \"num_unique_values\": 4682,\n \"samples\": [\n 128.369995,\n 707.330017,\n 998.590027\n ],\n \"semantic_type\": \"\",\n \"description\": \"\"\n }\n },\n {\n \"column\": \"High\",\n \"properties\": {\n \"dtype\": \"number\",\n \"std\": 334.52220666253055,\n \"min\": 57.181427,\n \"max\": 1638.099976,\n \"num_unique_values\": 4688,\n \"samples\": [\n 388.980011,\n 708.820007,\n 113.050003\n ],\n \"semantic_type\": \"\",\n \"description\": \"\"\n }\n },\n {\n \"column\": \"Low\",\n \"properties\": {\n \"dtype\": \"number\",\n \"std\": 328.3726430959014,\n \"min\": 55.552856,\n \"max\": 1603.439941,\n \"num_unique_values\": 4674,\n \"samples\": [\n 529.349976,\n 154.630005,\n 189.800003\n ],\n \"semantic_type\": \"\",\n \"description\": \"\"\n }\n },\n {\n \"column\": \"Close\",\n \"properties\": {\n \"dtype\": \"number\",\n \"std\": 331.63901967413744,\n \"min\": 56.254284,\n \"max\": 1609.079956,\n \"num_unique_values\": 4731,\n \"samples\": [\n 300.359985,\n 526.690002,\n 74.781425\n ],\n \"semantic_type\": \"\",\n \"description\": \"\"\n }\n },\n {\n \"column\": \"AdjClose\",\n \"properties\": {\n \"dtype\": \"number\",\n \"std\": 335.91134259680024,\n \"min\": 44.129971,\n \"max\": 1609.079956,\n \"num_unique_values\": 4960,\n \"samples\": [\n 743.400024,\n 850.5,\n 300.75\n ],\n \"semantic_type\": \"\",\n \"description\": \"\"\n }\n },\n {\n \"column\": \"Volume\",\n \"properties\": {\n \"dtype\": \"number\",\n \"std\": 24921219,\n \"min\": 7900,\n \"max\": 266380800,\n \"num_unique_values\": 4917,\n \"samples\": [\n 5034200,\n 5369100,\n 42343600\n ],\n \"semantic_type\": \"\",\n \"description\": \"\"\n }\n }\n ]\n}" + } + }, + "metadata": {}, + "execution_count": 9 + } + ] + }, + { + "cell_type": "code", + "source": [ + "# Filter for AAPL records\n", + "aapl = stocks[stocks['Symbol'] == 'AAPL']\n", + "aapl" + ], + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 424 + }, + "id": "GzuVvGRQ45Gl", + "outputId": "362e2064-e34a-4e16-9d71-7d39f5ef1762" + }, + "execution_count": 10, + "outputs": [ + { + "output_type": "execute_result", + "data": { + "text/plain": [ + " Symbol Date Open High Low Close \\\n", + "0 AAPL 2013-05-13 64.501427 65.414284 64.500000 64.962860 \n", + "1 AAPL 2013-05-14 64.835716 65.028572 63.164288 63.408573 \n", + "2 AAPL 2013-05-15 62.737144 63.000000 60.337143 61.264286 \n", + "3 AAPL 2013-05-16 60.462856 62.549999 59.842857 62.082859 \n", + "4 AAPL 2013-05-17 62.721428 62.869999 61.572857 61.894287 \n", + "... ... ... ... ... ... ... \n", + "1255 AAPL 2018-05-07 185.179993 187.669998 184.750000 185.160004 \n", + "1256 AAPL 2018-05-08 184.990005 186.220001 183.669998 186.050003 \n", + "1257 AAPL 2018-05-09 186.550003 187.399994 185.220001 187.360001 \n", + "1258 AAPL 2018-05-10 187.740005 190.369995 187.649994 190.039993 \n", + "1259 AAPL 2018-05-11 189.490005 190.059998 187.449997 188.589996 \n", + "\n", + " AdjClose Volume \n", + "0 50.961628 79237200 \n", + "1 49.742329 111779500 \n", + "2 48.060188 185403400 \n", + "3 48.702328 150801000 \n", + "4 48.554409 106976100 \n", + "... ... ... \n", + "1255 184.448746 42451400 \n", + "1256 185.335327 28402800 \n", + "1257 186.640305 23211200 \n", + "1258 189.309998 27989300 \n", + "1259 188.589996 25806600 \n", + "\n", + "[1260 rows x 8 columns]" + ], + "text/html": [ + "\n", + "
\n", + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
SymbolDateOpenHighLowCloseAdjCloseVolume
0AAPL2013-05-1364.50142765.41428464.50000064.96286050.96162879237200
1AAPL2013-05-1464.83571665.02857263.16428863.40857349.742329111779500
2AAPL2013-05-1562.73714463.00000060.33714361.26428648.060188185403400
3AAPL2013-05-1660.46285662.54999959.84285762.08285948.702328150801000
4AAPL2013-05-1762.72142862.86999961.57285761.89428748.554409106976100
...........................
1255AAPL2018-05-07185.179993187.669998184.750000185.160004184.44874642451400
1256AAPL2018-05-08184.990005186.220001183.669998186.050003185.33532728402800
1257AAPL2018-05-09186.550003187.399994185.220001187.360001186.64030523211200
1258AAPL2018-05-10187.740005190.369995187.649994190.039993189.30999827989300
1259AAPL2018-05-11189.490005190.059998187.449997188.589996188.58999625806600
\n", + "

1260 rows × 8 columns

\n", + "
\n", + "
\n", + "\n", + "
\n", + " \n", + "\n", + " \n", + "\n", + " \n", + "
\n", + "\n", + "\n", + "
\n", + " \n", + "\n", + "\n", + "\n", + " \n", + "
\n", + "\n", + "
\n", + " \n", + " \n", + " \n", + "
\n", + "\n", + "
\n", + "
\n" + ], + "application/vnd.google.colaboratory.intrinsic+json": { + "type": "dataframe", + "variable_name": "aapl", + "summary": "{\n \"name\": \"aapl\",\n \"rows\": 1260,\n \"fields\": [\n {\n \"column\": \"Symbol\",\n \"properties\": {\n \"dtype\": \"category\",\n \"num_unique_values\": 1,\n \"samples\": [\n \"AAPL\"\n ],\n \"semantic_type\": \"\",\n \"description\": \"\"\n }\n },\n {\n \"column\": \"Date\",\n \"properties\": {\n \"dtype\": \"date\",\n \"min\": \"2013-05-13 00:00:00\",\n \"max\": \"2018-05-11 00:00:00\",\n \"num_unique_values\": 1260,\n \"samples\": [\n \"2013-08-29 00:00:00\"\n ],\n \"semantic_type\": \"\",\n \"description\": \"\"\n }\n },\n {\n \"column\": \"Open\",\n \"properties\": {\n \"dtype\": \"number\",\n \"std\": 31.685469112905416,\n \"min\": 55.908573,\n \"max\": 189.490005,\n \"num_unique_values\": 1190,\n \"samples\": [\n 114.099998\n ],\n \"semantic_type\": \"\",\n \"description\": \"\"\n }\n },\n {\n \"column\": \"High\",\n \"properties\": {\n \"dtype\": \"number\",\n \"std\": 31.9040050032445,\n \"min\": 57.181427,\n \"max\": 190.369995,\n \"num_unique_values\": 1185,\n \"samples\": [\n 100.940002\n ],\n \"semantic_type\": \"\",\n \"description\": \"\"\n }\n },\n {\n \"column\": \"Low\",\n \"properties\": {\n \"dtype\": \"number\",\n \"std\": 31.479318107457743,\n \"min\": 55.552856,\n \"max\": 187.649994,\n \"num_unique_values\": 1184,\n \"samples\": [\n 100.699997\n ],\n \"semantic_type\": \"\",\n \"description\": \"\"\n }\n },\n {\n \"column\": \"Close\",\n \"properties\": {\n \"dtype\": \"number\",\n \"std\": 31.705475348633097,\n \"min\": 56.254284,\n \"max\": 190.039993,\n \"num_unique_values\": 1175,\n \"samples\": [\n 96.879997\n ],\n \"semantic_type\": \"\",\n \"description\": \"\"\n }\n },\n {\n \"column\": \"AdjClose\",\n \"properties\": {\n \"dtype\": \"number\",\n \"std\": 34.629223085227544,\n \"min\": 44.129971,\n \"max\": 189.309998,\n \"num_unique_values\": 1236,\n \"samples\": [\n 88.599915\n ],\n \"semantic_type\": \"\",\n \"description\": \"\"\n }\n },\n {\n \"column\": \"Volume\",\n \"properties\": {\n \"dtype\": \"number\",\n \"std\": 29211461,\n \"min\": 11475900,\n \"max\": 266380800,\n \"num_unique_values\": 1258,\n \"samples\": [\n 99312600\n ],\n \"semantic_type\": \"\",\n \"description\": \"\"\n }\n }\n ]\n}" + } + }, + "metadata": {}, + "execution_count": 10 + } + ] + }, + { + "cell_type": "code", + "source": [ + "# Create the widget with the filtered data\n", + "MosaicWidget(spec, data={\"aapl\": aapl})" + ], + "metadata": { + "colab": { + "base_uri": "https://localhost:8080/", + "height": 217, + "referenced_widgets": [ + "b91226e5c1b24aa0a602d1aab529936a", + "8b39014475ce4ed6b27504c98c23e845" + ] + }, + "id": "4P7Z_S2n469v", + "outputId": "696edd28-71e1-48ee-96d9-6032ad2b7ee1" + }, + "execution_count": 11, + "outputs": [ + { + "output_type": "display_data", + "data": { + "text/plain": [ + "MosaicWidget(spec={'height': 200, 'plot': [{'data': {'from': 'aapl'}, 'mark': 'lineY', 'x': 'Date', 'y': 'Clos…" + ], + "application/vnd.jupyter.widget-view+json": { + "version_major": 2, + "version_minor": 0, + "model_id": "b91226e5c1b24aa0a602d1aab529936a" + } + }, + "metadata": { + "application/vnd.jupyter.widget-view+json": { + "colab": { + "custom_widget_manager": { + "url": "https://ssl.gstatic.com/colaboratory-static/widgets/colab-cdn-widget-manager/2b70e893a8ba7c0f/manager.min.js" + } + } + } + } + } + ] + } + ] +} \ No newline at end of file diff --git a/packages/schema_wrapper/testingSchema.json b/packages/schema_wrapper/testingSchema.json new file mode 100644 index 00000000..0e47df9b --- /dev/null +++ b/packages/schema_wrapper/testingSchema.json @@ -0,0 +1,192743 @@ +{ + "$ref": "#/definitions/Spec", + "$schema": "http://json-schema.org/draft-07/schema#", + "definitions": { + "AggregateExpression": { + "additionalProperties": false, + "description": "A custom SQL aggregate expression.", + "properties": { + "agg": { + "description": "A SQL expression string to calculate an aggregate value. Embedded Param references, such as `SUM($param + 1)`, are supported. For expressions without aggregate functions, use *sql* instead.", + "type": "string" + }, + "label": { + "description": "A label for this expression, for example to label a plot axis.", + "type": "string" + } + }, + "required": [ + "agg" + ], + "type": "object" + }, + "AggregateTransform": { + "anyOf": [ + { + "$ref": "#/definitions/Argmax" + }, + { + "$ref": "#/definitions/Argmin" + }, + { + "$ref": "#/definitions/Avg" + }, + { + "$ref": "#/definitions/Count" + }, + { + "$ref": "#/definitions/Max" + }, + { + "$ref": "#/definitions/Min" + }, + { + "$ref": "#/definitions/First" + }, + { + "$ref": "#/definitions/Last" + }, + { + "$ref": "#/definitions/Median" + }, + { + "$ref": "#/definitions/Mode" + }, + { + "$ref": "#/definitions/Product" + }, + { + "$ref": "#/definitions/Quantile" + }, + { + "$ref": "#/definitions/Stddev" + }, + { + "$ref": "#/definitions/StddevPop" + }, + { + "$ref": "#/definitions/Sum" + }, + { + "$ref": "#/definitions/Variance" + }, + { + "$ref": "#/definitions/VarPop" + } + ], + "description": "An aggregate transform that combines multiple values." + }, + "Area": { + "additionalProperties": false, + "description": "The area mark.", + "properties": { + "ariaDescription": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-description][1]; a constant textual description.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-description" + }, + "ariaHidden": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-hidden][1] state; a constant indicating whether the element is exposed to an accessibility API.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-hidden" + }, + "ariaLabel": { + "$ref": "#/definitions/ChannelValue", + "description": "The [aria-label][1]; a channel specifying short textual labels representing the value in the accessibility tree.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-label" + }, + "clip": { + "anyOf": [ + { + "const": "frame", + "type": "string" + }, + { + "const": "sphere", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to clip the mark; one of:\n\n- *frame* or true - clip to the plot’s frame (inner area)\n- *sphere* - clip to the projected sphere (*e.g.*, front hemisphere)\n- null or false - do not clip\n\nThe *sphere* clip option requires a geographic projection." + }, + "curve": { + "anyOf": [ + { + "$ref": "#/definitions/Curve" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The curve (interpolation) method for connecting adjacent points. One of:\n\n- *basis* - a cubic basis spline (repeating the end points)\n- *basis-open* - an open cubic basis spline\n- *basis-closed* - a closed cubic basis spline\n- *bump-x* - a Bézier curve with horizontal tangents\n- *bump-y* - a Bézier curve with vertical tangents\n- *bundle* - a straightened cubic basis spline (suitable for lines only, not areas)\n- *cardinal* - a cubic cardinal spline (with one-sided differences at the ends)\n- *cardinal-open* - an open cubic cardinal spline\n- *cardinal-closed* - an closed cubic cardinal spline\n- *catmull-rom* - a cubic Catmull–Rom spline (with one-sided differences at the ends)\n- *catmull-rom-open* - an open cubic Catmull–Rom spline\n- *catmull-rom-closed* - a closed cubic Catmull–Rom spline\n- *linear* - a piecewise linear curve (*i.e.*, straight line segments)\n- *linear-closed* - a closed piecewise linear curve (*i.e.*, straight line segments)\n- *monotone-x* - a cubic spline that preserves monotonicity in *x*\n- *monotone-y* - a cubic spline that preserves monotonicity in *y*\n- *natural* - a natural cubic spline\n- *step* - a piecewise constant function where *y* changes at the midpoint of *x*\n- *step-after* - a piecewise constant function where *y* changes after *x*\n- *step-before* - a piecewise constant function where *x* changes after *y*" + }, + "data": { + "$ref": "#/definitions/PlotMarkData", + "description": "The data source for the mark." + }, + "dx": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The horizontal offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "dy": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The vertical offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "facet": { + "anyOf": [ + { + "const": "auto", + "type": "string" + }, + { + "const": "include", + "type": "string" + }, + { + "const": "exclude", + "type": "string" + }, + { + "const": "super", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to enable or disable faceting; one of:\n\n- *auto* (default) - automatically determine if this mark should be faceted\n- *include* (or true) - draw the subset of the mark’s data in the current facet\n- *exclude* - draw the subset of the mark’s data *not* in the current facet\n- *super* - draw this mark in a single frame that covers all facets\n- null (or false) - repeat this mark’s data across all facets (*i.e.*, no faceting)\n\nWhen a mark uses *super* faceting, it is not allowed to use position scales (*x*, *y*, *fx*, or *fy*); *super* faceting is intended for decorations, such as labels and legends.\n\nWhen top-level faceting is used, the default *auto* setting is equivalent to *include* when the mark data is strictly equal to the top-level facet data; otherwise it is equivalent to null. When the *include* or *exclude* facet mode is chosen, the mark data must be parallel to the top-level facet data: the data must have the same length and order. If the data are not parallel, then the wrong data may be shown in each facet. The default\n*auto* therefore requires strict equality (`===`) for safety, and using the facet data as mark data is recommended when using the *exclude* facet mode. (To construct parallel data safely, consider using [*array*.map][1] on the facet data.)\n\nWhen mark-level faceting is used, the default *auto* setting is equivalent to *include*: the mark will be faceted if either the **fx** or **fy** channel option (or both) is specified. The null or false option will disable faceting, while *exclude* draws the subset of the mark’s data *not* in the current facet.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map" + }, + "facetAnchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "right", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "const": "left", + "type": "string" + }, + { + "const": "top-left", + "type": "string" + }, + { + "const": "top-right", + "type": "string" + }, + { + "const": "bottom-left", + "type": "string" + }, + { + "const": "bottom-right", + "type": "string" + }, + { + "const": "top-empty", + "type": "string" + }, + { + "const": "right-empty", + "type": "string" + }, + { + "const": "bottom-empty", + "type": "string" + }, + { + "const": "left-empty", + "type": "string" + }, + { + "const": "empty", + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to place the mark with respect to facets; one of:\n\n- null (default for most marks) - display the mark in each non-empty facet\n- *top*, *right*, *bottom*, or *left* - display the mark only in facets on the given side\n- *top-empty*, *right-empty*, *bottom-empty*, or *left-empty* (default for axis marks) - display the mark only in facets that have empty space on the given side: either the margin, or an empty facet\n- *empty* - display the mark in empty facets only" + }, + "fill": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill" + }, + "fillOpacity": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill-opacity][1]; a constant number between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill-opacity" + }, + "filter": { + "$ref": "#/definitions/ChannelValue", + "description": "Applies a transform to filter the mark’s index according to the given channel values; only truthy values are retained.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "fx": { + "$ref": "#/definitions/ChannelValue", + "description": "The horizontal facet position channel, for mark-level faceting, bound to the *fx* scale." + }, + "fy": { + "$ref": "#/definitions/ChannelValue", + "description": "The vertical facet position channel, for mark-level faceting, bound to the\n*fy* scale." + }, + "href": { + "$ref": "#/definitions/ChannelValue", + "description": "The [href][1]; a channel specifying URLs for clickable links. May be used in conjunction with the **target** option to open links in another window.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/href" + }, + "imageFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A CSS [filter][1]; a constant string used to adjust the rendering of images, such as *blur(5px)*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/filter" + }, + "margin": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four mark margins: **marginTop**,\n**marginRight**, **marginBottom**, and **marginLeft**; typically defaults to 0, except for axis marks." + }, + "marginBottom": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s bottom margin; the minimum distance in pixels between the bottom edges of the inner and outer plot area." + }, + "marginLeft": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s left margin; the minimum distance in pixels between the left edges of the inner and outer plot area." + }, + "marginRight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s right margin; the minimum distance in pixels between the right edges of the mark’s inner and outer plot area." + }, + "marginTop": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s top margin; the minimum distance in pixels between the top edges of the inner and outer plot area." + }, + "mark": { + "const": "area", + "description": "An area mark. The area mark is rarely used directly; it is only needed when the baseline and topline have neither *x* nor *y* values in common. Use areaY for a horizontal orientation where the baseline and topline share *x* values, or areaX for a vertical orientation where the baseline and topline share *y* values.", + "type": "string" + }, + "mixBlendMode": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [mix-blend-mode][1]; a constant string specifying how to blend content such as *multiply*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode" + }, + "offset": { + "anyOf": [ + { + "$ref": "#/definitions/StackOffset" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "After stacking, an optional **offset** can be applied to translate and scale stacks, say to produce a streamgraph; defaults to null for a zero baseline (**y** = 0 for stackY, and **x** = 0 for stackX). If the *wiggle* offset is used, the default **order** changes to *inside-out*." + }, + "opacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally. For faster rendering, prefer the **strokeOpacity** or **fillOpacity** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/opacity" + }, + "order": { + "anyOf": [ + { + "$ref": "#/definitions/StackOrder" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The order in which stacks are layered; one of:\n\n- null (default) for input order\n- a named stack order method such as *inside-out* or *sum*\n- a field name, for natural order of the corresponding values\n- a function of data, for natural order of the corresponding values\n- an array of explicit **z** values in the desired order\n\nIf the *wiggle* **offset** is used, as for a streamgraph, the default changes to *inside-out*." + }, + "paintOrder": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [paint-order][1]; a constant string specifying the order in which the\n**fill**, **stroke**, and any markers are drawn; defaults to *normal*, which draws the fill, then stroke, then markers; defaults to *stroke* for the text mark to create a “halo” around text to improve legibility.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/paint-order" + }, + "pointerEvents": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [pointer-events][1] property; a constant string such as *none*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/pointer-events" + }, + "reverse": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Applies a transform to reverse the order of the mark’s index, say for reverse input order." + }, + "select": { + "$ref": "#/definitions/SelectFilter", + "description": "Applies a filter transform after data is loaded to highlight selected values only. For example, `first` and `last` select the first or last values of series only (using the *z* channel to separate series). Meanwhile, `nearestX` and `nearestY` select the point nearest to the pointer along the *x* or *y* channel dimension. Unlike Mosaic selections, a mark level *select* is internal to the mark only, and does not populate a param or selection value to be shared across clients.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "shapeRendering": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [shape-rendering][1]; a constant string such as *crispEdges*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/shape-rendering" + }, + "sort": { + "anyOf": [ + { + "$ref": "#/definitions/SortOrder" + }, + { + "$ref": "#/definitions/ChannelDomainSort" + } + ], + "description": "Either applies a transform to sort the mark’s index by the specified channel values, or imputes ordinal scale domains from this mark’s channels.\n\nWhen imputing ordinal scale domains from channel values, the **sort** option is an object whose keys are ordinal scale names such as *x* or *fx*, and whose values are channel names such as *y*, *y1*, or *y2*. For example, to impute the *y* scale’s domain from the associated *x* channel values in ascending order:\n\n```js sort: {y: \"x\"} ```\n\nFor different sort options for different scales, replace the channel name with a *value* object and per-scale options:\n\n```js sort: {y: {value: \"-x\"}} ```\n\nWhen sorting the mark’s index, the **sort** option is instead one of:\n\n- a channel value definition for sorting given values in ascending order\n- a {value, order} object for sorting given values\n- a {channel, order} object for sorting the named channel’s values" + }, + "stroke": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke" + }, + "strokeDasharray": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dasharray][1]; a constant number indicating the length in pixels of alternating dashes and gaps, or a constant string of numbers separated by spaces or commas (_e.g._, *10 2* for dashes of 10 pixels separated by gaps of 2 pixels), or *none* (the default) for no dashing\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dasharray" + }, + "strokeDashoffset": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dashoffset][1]; a constant indicating the offset in pixels of the first dash along the stroke; defaults to zero.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dashoffset" + }, + "strokeLinecap": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linecap][1]; a constant specifying how to cap stroked paths, such as *butt*, *round*, or *square*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linecap" + }, + "strokeLinejoin": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linejoin][1]; a constant specifying how to join stroked paths, such as *bevel*, *miter*, *miter-clip*, or *round*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linejoin" + }, + "strokeMiterlimit": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-miterlimit][1]; a constant number specifying how to limit the length of *miter* joins on stroked paths.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-miterlimit" + }, + "strokeOpacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-opacity" + }, + "strokeWidth": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-width][1]; a constant number in pixels, or a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-width" + }, + "target": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [target][1]; a constant string specifying the target window (_e.g._,\n*_blank*) for clickable links; used in conjunction with the **href** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/target" + }, + "tension": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The tension option only has an effect on bundle, cardinal and Catmull–Rom splines (*bundle*, *cardinal*, *cardinal-open*, *cardinal-closed*,\n*catmull-rom*, *catmull-rom-open*, and *catmull-rom-closed*). For bundle splines, it corresponds to [beta][1]; for cardinal splines, [tension][2]; for Catmull–Rom splines, [alpha][3].\n\n[1]: https://d3js.org/d3-shape/curve#curveBundle_beta [2]: https://d3js.org/d3-shape/curve#curveCardinal_tension [3]: https://d3js.org/d3-shape/curve#curveCatmullRom_alpha" + }, + "tip": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/TipPointer" + }, + { + "properties": { + "anchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The tip anchor specifies how to orient the tip box relative to its anchor position; it refers to the part of the tip box that is attached to the anchor point. For example, the *top-left* anchor places the top-left corner of tip box near the anchor position, hence placing the tip box below and to the right of the anchor position." + }, + "fontFamily": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font-family][1]; a constant; defaults to the plot’s font family, which is typically [*system-ui*][2].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-family [2]: https://drafts.csswg.org/css-fonts-4/#valdef-font-family-system-ui" + }, + "fontSize": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font size][1] in pixels; either a constant or a channel; defaults to the plot’s font size, which is typically 10. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-size" + }, + "fontStyle": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font style][1]; a constant; defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-style" + }, + "fontVariant": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font variant][1]; a constant; if the **text** channel contains numbers or dates, defaults to *tabular-nums* to facilitate comparing numbers; otherwise defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant" + }, + "fontWeight": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font weight][1]; a constant; defaults to the plot’s font weight, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight" + }, + "format": { + "additionalProperties": false, + "description": "How channel values are formatted for display. If a format is a string, it is interpreted as a (UTC) time format for temporal channels, and otherwise a number format.", + "properties": { + "ariaLabel": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fill": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fillOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fontSize": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fx": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fy": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "geometry": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "height": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "href": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "length": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "opacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "path": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "r": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "rotate": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "src": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "stroke": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeWidth": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "symbol": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "text": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "title": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "weight": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "width": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "z": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + } + }, + "type": "object" + }, + "frameAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The frame anchor specifies defaults for **x** and **y** based on the plot’s frame; it may be one of the four sides (*top*, *right*, *bottom*, *left*), one of the four corners (*top-left*, *top-right*, *bottom-right*,\n*bottom-left*), or the *middle* of the frame. For example, for tips distributed horizontally at the top of the frame:\n\n```js Plot.tip(data, {x: \"date\", frameAnchor: \"top\"}) ```" + }, + "lineHeight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line height in ems; defaults to 1. The line height affects the (typically vertical) separation between adjacent baselines of text, as well as the separation between the text and its anchor point." + }, + "lineWidth": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line width in ems (e.g., 10 for about 20 characters); defaults to infinity, disabling wrapping and clipping.\n\nIf **textOverflow** is null, lines will be wrapped at the specified length. If a line is split at a soft hyphen (\\xad), a hyphen (-) will be displayed at the end of the line. If **textOverflow** is not null, lines will be clipped according to the given strategy." + }, + "monospace": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, changes the default **fontFamily** to *monospace*, and uses simplified monospaced text metrics calculations." + }, + "pathFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The image filter for the tip’s box; defaults to a drop shadow." + }, + "pointer": { + "$ref": "#/definitions/TipPointer" + }, + "pointerSize": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The size of the tip’s pointer in pixels; defaults to 12." + }, + "preferredAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If an explicit tip anchor is not specified, an anchor is chosen automatically such that the tip fits within the plot’s frame; if the preferred anchor fits, it is chosen." + }, + "textAnchor": { + "anyOf": [ + { + "const": "start", + "type": "string" + }, + { + "const": "middle", + "type": "string" + }, + { + "const": "end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [text anchor][1] controls how text is aligned (typically horizontally) relative to its anchor point; it is one of *start*, *end*, or *middle*. If the frame anchor is *left*, *top-left*, or *bottom-left*, the default text anchor is *start*; if the frame anchor is *right*, *top-right*, or\n*bottom-right*, the default is *end*; otherwise it is *middle*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/text-anchor" + }, + "textOverflow": { + "anyOf": [ + { + "type": "null" + }, + { + "const": "clip", + "type": "string" + }, + { + "const": "ellipsis", + "type": "string" + }, + { + "const": "clip-start", + "type": "string" + }, + { + "const": "clip-end", + "type": "string" + }, + { + "const": "ellipsis-start", + "type": "string" + }, + { + "const": "ellipsis-middle", + "type": "string" + }, + { + "const": "ellipsis-end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How truncate (or wrap) lines of text longer than the given **lineWidth**; one of:\n\n- null (default) - preserve overflowing characters (and wrap if needed)\n- *clip* or *clip-end* - remove characters from the end\n- *clip-start* - remove characters from the start\n- *ellipsis* or *ellipsis-end* - replace characters from the end with an ellipsis (…)\n- *ellipsis-start* - replace characters from the start with an ellipsis (…)\n- *ellipsis-middle* - replace characters from the middle with an ellipsis (…)\n\nIf no **title** was specified, if text requires truncation, a title containing the non-truncated text will be implicitly added." + }, + "textPadding": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The padding around the text in pixels; defaults to 8." + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + } + }, + "type": "object" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to generate a tooltip for this mark, and any tip options." + }, + "title": { + "$ref": "#/definitions/ChannelValue", + "description": "The title; a channel specifying accessible, short textual descriptions as strings (possibly with newlines). If the tip option is specified, the title will be displayed with an interactive tooltip instead of using the SVG [title element][1].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/title" + }, + "x1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The required primary (starting, often left) horizontal position channel, representing the area’s baseline, typically bound to the *x* scale. For areaX, setting this option disables the implicit stackX transform." + }, + "x2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The optional secondary (ending, often right) horizontal position channel, representing the area’s topline, typically bound to the *x* scale; if not specified, **x1** is used. For areaX, setting this option disables the implicit stackX transform." + }, + "y1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The required primary (starting, often bottom) vertical position channel, representing the area’s baseline, typically bound to the *y* scale. For areaY, setting this option disables the implicit stackY transform." + }, + "y2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The optional secondary (ending, often top) vertical position channel, representing the area’s topline, typically bound to the *y* scale; if not specified, **y1** is used. For areaY, setting this option disables the implicit stackY transform." + }, + "z": { + "$ref": "#/definitions/ChannelValue", + "description": "An optional ordinal channel for grouping data into (possibly stacked) series to be drawn as separate areas; defaults to **fill** if a channel, or\n**stroke** if a channel." + } + }, + "required": [ + "data", + "mark" + ], + "type": "object" + }, + "AreaX": { + "additionalProperties": false, + "description": "The areaX mark.", + "properties": { + "ariaDescription": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-description][1]; a constant textual description.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-description" + }, + "ariaHidden": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-hidden][1] state; a constant indicating whether the element is exposed to an accessibility API.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-hidden" + }, + "ariaLabel": { + "$ref": "#/definitions/ChannelValue", + "description": "The [aria-label][1]; a channel specifying short textual labels representing the value in the accessibility tree.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-label" + }, + "clip": { + "anyOf": [ + { + "const": "frame", + "type": "string" + }, + { + "const": "sphere", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to clip the mark; one of:\n\n- *frame* or true - clip to the plot’s frame (inner area)\n- *sphere* - clip to the projected sphere (*e.g.*, front hemisphere)\n- null or false - do not clip\n\nThe *sphere* clip option requires a geographic projection." + }, + "curve": { + "anyOf": [ + { + "$ref": "#/definitions/Curve" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The curve (interpolation) method for connecting adjacent points. One of:\n\n- *basis* - a cubic basis spline (repeating the end points)\n- *basis-open* - an open cubic basis spline\n- *basis-closed* - a closed cubic basis spline\n- *bump-x* - a Bézier curve with horizontal tangents\n- *bump-y* - a Bézier curve with vertical tangents\n- *bundle* - a straightened cubic basis spline (suitable for lines only, not areas)\n- *cardinal* - a cubic cardinal spline (with one-sided differences at the ends)\n- *cardinal-open* - an open cubic cardinal spline\n- *cardinal-closed* - an closed cubic cardinal spline\n- *catmull-rom* - a cubic Catmull–Rom spline (with one-sided differences at the ends)\n- *catmull-rom-open* - an open cubic Catmull–Rom spline\n- *catmull-rom-closed* - a closed cubic Catmull–Rom spline\n- *linear* - a piecewise linear curve (*i.e.*, straight line segments)\n- *linear-closed* - a closed piecewise linear curve (*i.e.*, straight line segments)\n- *monotone-x* - a cubic spline that preserves monotonicity in *x*\n- *monotone-y* - a cubic spline that preserves monotonicity in *y*\n- *natural* - a natural cubic spline\n- *step* - a piecewise constant function where *y* changes at the midpoint of *x*\n- *step-after* - a piecewise constant function where *y* changes after *x*\n- *step-before* - a piecewise constant function where *x* changes after *y*" + }, + "data": { + "$ref": "#/definitions/PlotMarkData", + "description": "The data source for the mark." + }, + "dx": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The horizontal offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "dy": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The vertical offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "facet": { + "anyOf": [ + { + "const": "auto", + "type": "string" + }, + { + "const": "include", + "type": "string" + }, + { + "const": "exclude", + "type": "string" + }, + { + "const": "super", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to enable or disable faceting; one of:\n\n- *auto* (default) - automatically determine if this mark should be faceted\n- *include* (or true) - draw the subset of the mark’s data in the current facet\n- *exclude* - draw the subset of the mark’s data *not* in the current facet\n- *super* - draw this mark in a single frame that covers all facets\n- null (or false) - repeat this mark’s data across all facets (*i.e.*, no faceting)\n\nWhen a mark uses *super* faceting, it is not allowed to use position scales (*x*, *y*, *fx*, or *fy*); *super* faceting is intended for decorations, such as labels and legends.\n\nWhen top-level faceting is used, the default *auto* setting is equivalent to *include* when the mark data is strictly equal to the top-level facet data; otherwise it is equivalent to null. When the *include* or *exclude* facet mode is chosen, the mark data must be parallel to the top-level facet data: the data must have the same length and order. If the data are not parallel, then the wrong data may be shown in each facet. The default\n*auto* therefore requires strict equality (`===`) for safety, and using the facet data as mark data is recommended when using the *exclude* facet mode. (To construct parallel data safely, consider using [*array*.map][1] on the facet data.)\n\nWhen mark-level faceting is used, the default *auto* setting is equivalent to *include*: the mark will be faceted if either the **fx** or **fy** channel option (or both) is specified. The null or false option will disable faceting, while *exclude* draws the subset of the mark’s data *not* in the current facet.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map" + }, + "facetAnchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "right", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "const": "left", + "type": "string" + }, + { + "const": "top-left", + "type": "string" + }, + { + "const": "top-right", + "type": "string" + }, + { + "const": "bottom-left", + "type": "string" + }, + { + "const": "bottom-right", + "type": "string" + }, + { + "const": "top-empty", + "type": "string" + }, + { + "const": "right-empty", + "type": "string" + }, + { + "const": "bottom-empty", + "type": "string" + }, + { + "const": "left-empty", + "type": "string" + }, + { + "const": "empty", + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to place the mark with respect to facets; one of:\n\n- null (default for most marks) - display the mark in each non-empty facet\n- *top*, *right*, *bottom*, or *left* - display the mark only in facets on the given side\n- *top-empty*, *right-empty*, *bottom-empty*, or *left-empty* (default for axis marks) - display the mark only in facets that have empty space on the given side: either the margin, or an empty facet\n- *empty* - display the mark in empty facets only" + }, + "fill": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill" + }, + "fillOpacity": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill-opacity][1]; a constant number between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill-opacity" + }, + "filter": { + "$ref": "#/definitions/ChannelValue", + "description": "Applies a transform to filter the mark’s index according to the given channel values; only truthy values are retained.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "fx": { + "$ref": "#/definitions/ChannelValue", + "description": "The horizontal facet position channel, for mark-level faceting, bound to the *fx* scale." + }, + "fy": { + "$ref": "#/definitions/ChannelValue", + "description": "The vertical facet position channel, for mark-level faceting, bound to the\n*fy* scale." + }, + "href": { + "$ref": "#/definitions/ChannelValue", + "description": "The [href][1]; a channel specifying URLs for clickable links. May be used in conjunction with the **target** option to open links in another window.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/href" + }, + "imageFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A CSS [filter][1]; a constant string used to adjust the rendering of images, such as *blur(5px)*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/filter" + }, + "margin": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four mark margins: **marginTop**,\n**marginRight**, **marginBottom**, and **marginLeft**; typically defaults to 0, except for axis marks." + }, + "marginBottom": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s bottom margin; the minimum distance in pixels between the bottom edges of the inner and outer plot area." + }, + "marginLeft": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s left margin; the minimum distance in pixels between the left edges of the inner and outer plot area." + }, + "marginRight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s right margin; the minimum distance in pixels between the right edges of the mark’s inner and outer plot area." + }, + "marginTop": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s top margin; the minimum distance in pixels between the top edges of the inner and outer plot area." + }, + "mark": { + "const": "areaX", + "description": "A vertically-oriented area mark, where the baseline and topline share\n**y** values, as in a time-series area chart where time goes up↑.\n\nIf neither **x1** nor **x2** is specified, an implicit stackX transform is applied and **x** defaults to the identity function, assuming that *data* = [*x₀*, *x₁*, *x₂*, …]. Otherwise, if only one of **x1** or **x2** is specified, the other defaults to **x**, which defaults to zero.\n\nIf an **interval** is specified, **y** values are binned accordingly, allowing zeroes for empty bins instead of interpolating across gaps. This is recommended to “regularize” sampled data; for example, if your data represents timestamped observations and you expect one observation per day, use *day* as the **interval**.\n\nVariable aesthetic channels are supported: if the **fill** is defined as a channel, the area will be broken into contiguous overlapping sections when the fill color changes; the fill color will apply to the interval spanning the current data point and the following data point. This behavior also applies to the **fillOpacity**, **stroke**, **strokeOpacity**,\n**strokeWidth**, **opacity**, **href**, **title**, and **ariaLabel** channels. When any of these channels are used, setting an explicit **z** channel (possibly to null) is strongly recommended.", + "type": "string" + }, + "mixBlendMode": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [mix-blend-mode][1]; a constant string specifying how to blend content such as *multiply*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode" + }, + "offset": { + "anyOf": [ + { + "$ref": "#/definitions/StackOffset" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "After stacking, an optional **offset** can be applied to translate and scale stacks, say to produce a streamgraph; defaults to null for a zero baseline (**y** = 0 for stackY, and **x** = 0 for stackX). If the *wiggle* offset is used, the default **order** changes to *inside-out*." + }, + "opacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally. For faster rendering, prefer the **strokeOpacity** or **fillOpacity** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/opacity" + }, + "order": { + "anyOf": [ + { + "$ref": "#/definitions/StackOrder" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The order in which stacks are layered; one of:\n\n- null (default) for input order\n- a named stack order method such as *inside-out* or *sum*\n- a field name, for natural order of the corresponding values\n- a function of data, for natural order of the corresponding values\n- an array of explicit **z** values in the desired order\n\nIf the *wiggle* **offset** is used, as for a streamgraph, the default changes to *inside-out*." + }, + "paintOrder": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [paint-order][1]; a constant string specifying the order in which the\n**fill**, **stroke**, and any markers are drawn; defaults to *normal*, which draws the fill, then stroke, then markers; defaults to *stroke* for the text mark to create a “halo” around text to improve legibility.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/paint-order" + }, + "pointerEvents": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [pointer-events][1] property; a constant string such as *none*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/pointer-events" + }, + "reverse": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Applies a transform to reverse the order of the mark’s index, say for reverse input order." + }, + "select": { + "$ref": "#/definitions/SelectFilter", + "description": "Applies a filter transform after data is loaded to highlight selected values only. For example, `first` and `last` select the first or last values of series only (using the *z* channel to separate series). Meanwhile, `nearestX` and `nearestY` select the point nearest to the pointer along the *x* or *y* channel dimension. Unlike Mosaic selections, a mark level *select* is internal to the mark only, and does not populate a param or selection value to be shared across clients.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "shapeRendering": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [shape-rendering][1]; a constant string such as *crispEdges*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/shape-rendering" + }, + "sort": { + "anyOf": [ + { + "$ref": "#/definitions/SortOrder" + }, + { + "$ref": "#/definitions/ChannelDomainSort" + } + ], + "description": "Either applies a transform to sort the mark’s index by the specified channel values, or imputes ordinal scale domains from this mark’s channels.\n\nWhen imputing ordinal scale domains from channel values, the **sort** option is an object whose keys are ordinal scale names such as *x* or *fx*, and whose values are channel names such as *y*, *y1*, or *y2*. For example, to impute the *y* scale’s domain from the associated *x* channel values in ascending order:\n\n```js sort: {y: \"x\"} ```\n\nFor different sort options for different scales, replace the channel name with a *value* object and per-scale options:\n\n```js sort: {y: {value: \"-x\"}} ```\n\nWhen sorting the mark’s index, the **sort** option is instead one of:\n\n- a channel value definition for sorting given values in ascending order\n- a {value, order} object for sorting given values\n- a {channel, order} object for sorting the named channel’s values" + }, + "stroke": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke" + }, + "strokeDasharray": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dasharray][1]; a constant number indicating the length in pixels of alternating dashes and gaps, or a constant string of numbers separated by spaces or commas (_e.g._, *10 2* for dashes of 10 pixels separated by gaps of 2 pixels), or *none* (the default) for no dashing\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dasharray" + }, + "strokeDashoffset": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dashoffset][1]; a constant indicating the offset in pixels of the first dash along the stroke; defaults to zero.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dashoffset" + }, + "strokeLinecap": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linecap][1]; a constant specifying how to cap stroked paths, such as *butt*, *round*, or *square*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linecap" + }, + "strokeLinejoin": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linejoin][1]; a constant specifying how to join stroked paths, such as *bevel*, *miter*, *miter-clip*, or *round*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linejoin" + }, + "strokeMiterlimit": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-miterlimit][1]; a constant number specifying how to limit the length of *miter* joins on stroked paths.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-miterlimit" + }, + "strokeOpacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-opacity" + }, + "strokeWidth": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-width][1]; a constant number in pixels, or a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-width" + }, + "target": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [target][1]; a constant string specifying the target window (_e.g._,\n*_blank*) for clickable links; used in conjunction with the **href** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/target" + }, + "tension": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The tension option only has an effect on bundle, cardinal and Catmull–Rom splines (*bundle*, *cardinal*, *cardinal-open*, *cardinal-closed*,\n*catmull-rom*, *catmull-rom-open*, and *catmull-rom-closed*). For bundle splines, it corresponds to [beta][1]; for cardinal splines, [tension][2]; for Catmull–Rom splines, [alpha][3].\n\n[1]: https://d3js.org/d3-shape/curve#curveBundle_beta [2]: https://d3js.org/d3-shape/curve#curveCardinal_tension [3]: https://d3js.org/d3-shape/curve#curveCatmullRom_alpha" + }, + "tip": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/TipPointer" + }, + { + "properties": { + "anchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The tip anchor specifies how to orient the tip box relative to its anchor position; it refers to the part of the tip box that is attached to the anchor point. For example, the *top-left* anchor places the top-left corner of tip box near the anchor position, hence placing the tip box below and to the right of the anchor position." + }, + "fontFamily": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font-family][1]; a constant; defaults to the plot’s font family, which is typically [*system-ui*][2].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-family [2]: https://drafts.csswg.org/css-fonts-4/#valdef-font-family-system-ui" + }, + "fontSize": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font size][1] in pixels; either a constant or a channel; defaults to the plot’s font size, which is typically 10. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-size" + }, + "fontStyle": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font style][1]; a constant; defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-style" + }, + "fontVariant": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font variant][1]; a constant; if the **text** channel contains numbers or dates, defaults to *tabular-nums* to facilitate comparing numbers; otherwise defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant" + }, + "fontWeight": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font weight][1]; a constant; defaults to the plot’s font weight, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight" + }, + "format": { + "additionalProperties": false, + "description": "How channel values are formatted for display. If a format is a string, it is interpreted as a (UTC) time format for temporal channels, and otherwise a number format.", + "properties": { + "ariaLabel": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fill": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fillOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fontSize": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fx": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fy": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "geometry": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "height": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "href": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "length": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "opacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "path": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "r": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "rotate": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "src": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "stroke": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeWidth": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "symbol": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "text": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "title": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "weight": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "width": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "z": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + } + }, + "type": "object" + }, + "frameAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The frame anchor specifies defaults for **x** and **y** based on the plot’s frame; it may be one of the four sides (*top*, *right*, *bottom*, *left*), one of the four corners (*top-left*, *top-right*, *bottom-right*,\n*bottom-left*), or the *middle* of the frame. For example, for tips distributed horizontally at the top of the frame:\n\n```js Plot.tip(data, {x: \"date\", frameAnchor: \"top\"}) ```" + }, + "lineHeight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line height in ems; defaults to 1. The line height affects the (typically vertical) separation between adjacent baselines of text, as well as the separation between the text and its anchor point." + }, + "lineWidth": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line width in ems (e.g., 10 for about 20 characters); defaults to infinity, disabling wrapping and clipping.\n\nIf **textOverflow** is null, lines will be wrapped at the specified length. If a line is split at a soft hyphen (\\xad), a hyphen (-) will be displayed at the end of the line. If **textOverflow** is not null, lines will be clipped according to the given strategy." + }, + "monospace": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, changes the default **fontFamily** to *monospace*, and uses simplified monospaced text metrics calculations." + }, + "pathFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The image filter for the tip’s box; defaults to a drop shadow." + }, + "pointer": { + "$ref": "#/definitions/TipPointer" + }, + "pointerSize": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The size of the tip’s pointer in pixels; defaults to 12." + }, + "preferredAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If an explicit tip anchor is not specified, an anchor is chosen automatically such that the tip fits within the plot’s frame; if the preferred anchor fits, it is chosen." + }, + "textAnchor": { + "anyOf": [ + { + "const": "start", + "type": "string" + }, + { + "const": "middle", + "type": "string" + }, + { + "const": "end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [text anchor][1] controls how text is aligned (typically horizontally) relative to its anchor point; it is one of *start*, *end*, or *middle*. If the frame anchor is *left*, *top-left*, or *bottom-left*, the default text anchor is *start*; if the frame anchor is *right*, *top-right*, or\n*bottom-right*, the default is *end*; otherwise it is *middle*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/text-anchor" + }, + "textOverflow": { + "anyOf": [ + { + "type": "null" + }, + { + "const": "clip", + "type": "string" + }, + { + "const": "ellipsis", + "type": "string" + }, + { + "const": "clip-start", + "type": "string" + }, + { + "const": "clip-end", + "type": "string" + }, + { + "const": "ellipsis-start", + "type": "string" + }, + { + "const": "ellipsis-middle", + "type": "string" + }, + { + "const": "ellipsis-end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How truncate (or wrap) lines of text longer than the given **lineWidth**; one of:\n\n- null (default) - preserve overflowing characters (and wrap if needed)\n- *clip* or *clip-end* - remove characters from the end\n- *clip-start* - remove characters from the start\n- *ellipsis* or *ellipsis-end* - replace characters from the end with an ellipsis (…)\n- *ellipsis-start* - replace characters from the start with an ellipsis (…)\n- *ellipsis-middle* - replace characters from the middle with an ellipsis (…)\n\nIf no **title** was specified, if text requires truncation, a title containing the non-truncated text will be implicitly added." + }, + "textPadding": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The padding around the text in pixels; defaults to 8." + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + } + }, + "type": "object" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to generate a tooltip for this mark, and any tip options." + }, + "title": { + "$ref": "#/definitions/ChannelValue", + "description": "The title; a channel specifying accessible, short textual descriptions as strings (possibly with newlines). If the tip option is specified, the title will be displayed with an interactive tooltip instead of using the SVG [title element][1].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/title" + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position (or length) channel, typically bound to the *x* scale.\n\nIf neither **x1** nor **x2** is specified, an implicit stackX transform is applied and **x** defaults to the identity function, assuming that *data* = [*x₀*, *x₁*, *x₂*, …]. Otherwise, if only one of **x1** or **x2** is specified, the other defaults to **x**, which defaults to zero." + }, + "x1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The required primary (starting, often left) horizontal position channel, representing the area’s baseline, typically bound to the *x* scale. For areaX, setting this option disables the implicit stackX transform." + }, + "x2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The optional secondary (ending, often right) horizontal position channel, representing the area’s topline, typically bound to the *x* scale; if not specified, **x1** is used. For areaX, setting this option disables the implicit stackX transform." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel, typically bound to the *y* scale; defaults to the zero-based index of the data [0, 1, 2, …]." + }, + "z": { + "$ref": "#/definitions/ChannelValue", + "description": "An optional ordinal channel for grouping data into (possibly stacked) series to be drawn as separate areas; defaults to **fill** if a channel, or\n**stroke** if a channel." + } + }, + "required": [ + "data", + "mark" + ], + "type": "object" + }, + "AreaY": { + "additionalProperties": false, + "description": "The areaY mark.", + "properties": { + "ariaDescription": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-description][1]; a constant textual description.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-description" + }, + "ariaHidden": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-hidden][1] state; a constant indicating whether the element is exposed to an accessibility API.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-hidden" + }, + "ariaLabel": { + "$ref": "#/definitions/ChannelValue", + "description": "The [aria-label][1]; a channel specifying short textual labels representing the value in the accessibility tree.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-label" + }, + "clip": { + "anyOf": [ + { + "const": "frame", + "type": "string" + }, + { + "const": "sphere", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to clip the mark; one of:\n\n- *frame* or true - clip to the plot’s frame (inner area)\n- *sphere* - clip to the projected sphere (*e.g.*, front hemisphere)\n- null or false - do not clip\n\nThe *sphere* clip option requires a geographic projection." + }, + "curve": { + "anyOf": [ + { + "$ref": "#/definitions/Curve" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The curve (interpolation) method for connecting adjacent points. One of:\n\n- *basis* - a cubic basis spline (repeating the end points)\n- *basis-open* - an open cubic basis spline\n- *basis-closed* - a closed cubic basis spline\n- *bump-x* - a Bézier curve with horizontal tangents\n- *bump-y* - a Bézier curve with vertical tangents\n- *bundle* - a straightened cubic basis spline (suitable for lines only, not areas)\n- *cardinal* - a cubic cardinal spline (with one-sided differences at the ends)\n- *cardinal-open* - an open cubic cardinal spline\n- *cardinal-closed* - an closed cubic cardinal spline\n- *catmull-rom* - a cubic Catmull–Rom spline (with one-sided differences at the ends)\n- *catmull-rom-open* - an open cubic Catmull–Rom spline\n- *catmull-rom-closed* - a closed cubic Catmull–Rom spline\n- *linear* - a piecewise linear curve (*i.e.*, straight line segments)\n- *linear-closed* - a closed piecewise linear curve (*i.e.*, straight line segments)\n- *monotone-x* - a cubic spline that preserves monotonicity in *x*\n- *monotone-y* - a cubic spline that preserves monotonicity in *y*\n- *natural* - a natural cubic spline\n- *step* - a piecewise constant function where *y* changes at the midpoint of *x*\n- *step-after* - a piecewise constant function where *y* changes after *x*\n- *step-before* - a piecewise constant function where *x* changes after *y*" + }, + "data": { + "$ref": "#/definitions/PlotMarkData", + "description": "The data source for the mark." + }, + "dx": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The horizontal offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "dy": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The vertical offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "facet": { + "anyOf": [ + { + "const": "auto", + "type": "string" + }, + { + "const": "include", + "type": "string" + }, + { + "const": "exclude", + "type": "string" + }, + { + "const": "super", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to enable or disable faceting; one of:\n\n- *auto* (default) - automatically determine if this mark should be faceted\n- *include* (or true) - draw the subset of the mark’s data in the current facet\n- *exclude* - draw the subset of the mark’s data *not* in the current facet\n- *super* - draw this mark in a single frame that covers all facets\n- null (or false) - repeat this mark’s data across all facets (*i.e.*, no faceting)\n\nWhen a mark uses *super* faceting, it is not allowed to use position scales (*x*, *y*, *fx*, or *fy*); *super* faceting is intended for decorations, such as labels and legends.\n\nWhen top-level faceting is used, the default *auto* setting is equivalent to *include* when the mark data is strictly equal to the top-level facet data; otherwise it is equivalent to null. When the *include* or *exclude* facet mode is chosen, the mark data must be parallel to the top-level facet data: the data must have the same length and order. If the data are not parallel, then the wrong data may be shown in each facet. The default\n*auto* therefore requires strict equality (`===`) for safety, and using the facet data as mark data is recommended when using the *exclude* facet mode. (To construct parallel data safely, consider using [*array*.map][1] on the facet data.)\n\nWhen mark-level faceting is used, the default *auto* setting is equivalent to *include*: the mark will be faceted if either the **fx** or **fy** channel option (or both) is specified. The null or false option will disable faceting, while *exclude* draws the subset of the mark’s data *not* in the current facet.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map" + }, + "facetAnchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "right", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "const": "left", + "type": "string" + }, + { + "const": "top-left", + "type": "string" + }, + { + "const": "top-right", + "type": "string" + }, + { + "const": "bottom-left", + "type": "string" + }, + { + "const": "bottom-right", + "type": "string" + }, + { + "const": "top-empty", + "type": "string" + }, + { + "const": "right-empty", + "type": "string" + }, + { + "const": "bottom-empty", + "type": "string" + }, + { + "const": "left-empty", + "type": "string" + }, + { + "const": "empty", + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to place the mark with respect to facets; one of:\n\n- null (default for most marks) - display the mark in each non-empty facet\n- *top*, *right*, *bottom*, or *left* - display the mark only in facets on the given side\n- *top-empty*, *right-empty*, *bottom-empty*, or *left-empty* (default for axis marks) - display the mark only in facets that have empty space on the given side: either the margin, or an empty facet\n- *empty* - display the mark in empty facets only" + }, + "fill": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill" + }, + "fillOpacity": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill-opacity][1]; a constant number between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill-opacity" + }, + "filter": { + "$ref": "#/definitions/ChannelValue", + "description": "Applies a transform to filter the mark’s index according to the given channel values; only truthy values are retained.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "fx": { + "$ref": "#/definitions/ChannelValue", + "description": "The horizontal facet position channel, for mark-level faceting, bound to the *fx* scale." + }, + "fy": { + "$ref": "#/definitions/ChannelValue", + "description": "The vertical facet position channel, for mark-level faceting, bound to the\n*fy* scale." + }, + "href": { + "$ref": "#/definitions/ChannelValue", + "description": "The [href][1]; a channel specifying URLs for clickable links. May be used in conjunction with the **target** option to open links in another window.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/href" + }, + "imageFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A CSS [filter][1]; a constant string used to adjust the rendering of images, such as *blur(5px)*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/filter" + }, + "margin": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four mark margins: **marginTop**,\n**marginRight**, **marginBottom**, and **marginLeft**; typically defaults to 0, except for axis marks." + }, + "marginBottom": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s bottom margin; the minimum distance in pixels between the bottom edges of the inner and outer plot area." + }, + "marginLeft": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s left margin; the minimum distance in pixels between the left edges of the inner and outer plot area." + }, + "marginRight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s right margin; the minimum distance in pixels between the right edges of the mark’s inner and outer plot area." + }, + "marginTop": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s top margin; the minimum distance in pixels between the top edges of the inner and outer plot area." + }, + "mark": { + "const": "areaY", + "description": "A horizontally-oriented area mark, where the baseline and topline share\n**x** values, as in a time-series area chart where time goes right→.\n\nIf neither **y1** nor **y2** is specified, an implicit stackY transform is applied and **y** defaults to the identity function, assuming that *data* = [*y₀*, *y₁*, *y₂*, …]. Otherwise, if only one of **y1** or **y2** is specified, the other defaults to **y**, which defaults to zero.\n\nIf an **interval** is specified, **x** values are binned accordingly, allowing zeroes for empty bins instead of interpolating across gaps. This is recommended to “regularize” sampled data; for example, if your data represents timestamped observations and you expect one observation per day, use *day* as the **interval**.\n\nVariable aesthetic channels are supported: if the **fill** is defined as a channel, the area will be broken into contiguous overlapping sections when the fill color changes; the fill color will apply to the interval spanning the current data point and the following data point. This behavior also applies to the **fillOpacity**, **stroke**, **strokeOpacity**,\n**strokeWidth**, **opacity**, **href**, **title**, and **ariaLabel** channels. When any of these channels are used, setting an explicit **z** channel (possibly to null) is strongly recommended.", + "type": "string" + }, + "mixBlendMode": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [mix-blend-mode][1]; a constant string specifying how to blend content such as *multiply*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode" + }, + "offset": { + "anyOf": [ + { + "$ref": "#/definitions/StackOffset" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "After stacking, an optional **offset** can be applied to translate and scale stacks, say to produce a streamgraph; defaults to null for a zero baseline (**y** = 0 for stackY, and **x** = 0 for stackX). If the *wiggle* offset is used, the default **order** changes to *inside-out*." + }, + "opacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally. For faster rendering, prefer the **strokeOpacity** or **fillOpacity** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/opacity" + }, + "order": { + "anyOf": [ + { + "$ref": "#/definitions/StackOrder" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The order in which stacks are layered; one of:\n\n- null (default) for input order\n- a named stack order method such as *inside-out* or *sum*\n- a field name, for natural order of the corresponding values\n- a function of data, for natural order of the corresponding values\n- an array of explicit **z** values in the desired order\n\nIf the *wiggle* **offset** is used, as for a streamgraph, the default changes to *inside-out*." + }, + "paintOrder": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [paint-order][1]; a constant string specifying the order in which the\n**fill**, **stroke**, and any markers are drawn; defaults to *normal*, which draws the fill, then stroke, then markers; defaults to *stroke* for the text mark to create a “halo” around text to improve legibility.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/paint-order" + }, + "pointerEvents": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [pointer-events][1] property; a constant string such as *none*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/pointer-events" + }, + "reverse": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Applies a transform to reverse the order of the mark’s index, say for reverse input order." + }, + "select": { + "$ref": "#/definitions/SelectFilter", + "description": "Applies a filter transform after data is loaded to highlight selected values only. For example, `first` and `last` select the first or last values of series only (using the *z* channel to separate series). Meanwhile, `nearestX` and `nearestY` select the point nearest to the pointer along the *x* or *y* channel dimension. Unlike Mosaic selections, a mark level *select* is internal to the mark only, and does not populate a param or selection value to be shared across clients.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "shapeRendering": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [shape-rendering][1]; a constant string such as *crispEdges*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/shape-rendering" + }, + "sort": { + "anyOf": [ + { + "$ref": "#/definitions/SortOrder" + }, + { + "$ref": "#/definitions/ChannelDomainSort" + } + ], + "description": "Either applies a transform to sort the mark’s index by the specified channel values, or imputes ordinal scale domains from this mark’s channels.\n\nWhen imputing ordinal scale domains from channel values, the **sort** option is an object whose keys are ordinal scale names such as *x* or *fx*, and whose values are channel names such as *y*, *y1*, or *y2*. For example, to impute the *y* scale’s domain from the associated *x* channel values in ascending order:\n\n```js sort: {y: \"x\"} ```\n\nFor different sort options for different scales, replace the channel name with a *value* object and per-scale options:\n\n```js sort: {y: {value: \"-x\"}} ```\n\nWhen sorting the mark’s index, the **sort** option is instead one of:\n\n- a channel value definition for sorting given values in ascending order\n- a {value, order} object for sorting given values\n- a {channel, order} object for sorting the named channel’s values" + }, + "stroke": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke" + }, + "strokeDasharray": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dasharray][1]; a constant number indicating the length in pixels of alternating dashes and gaps, or a constant string of numbers separated by spaces or commas (_e.g._, *10 2* for dashes of 10 pixels separated by gaps of 2 pixels), or *none* (the default) for no dashing\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dasharray" + }, + "strokeDashoffset": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dashoffset][1]; a constant indicating the offset in pixels of the first dash along the stroke; defaults to zero.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dashoffset" + }, + "strokeLinecap": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linecap][1]; a constant specifying how to cap stroked paths, such as *butt*, *round*, or *square*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linecap" + }, + "strokeLinejoin": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linejoin][1]; a constant specifying how to join stroked paths, such as *bevel*, *miter*, *miter-clip*, or *round*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linejoin" + }, + "strokeMiterlimit": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-miterlimit][1]; a constant number specifying how to limit the length of *miter* joins on stroked paths.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-miterlimit" + }, + "strokeOpacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-opacity" + }, + "strokeWidth": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-width][1]; a constant number in pixels, or a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-width" + }, + "target": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [target][1]; a constant string specifying the target window (_e.g._,\n*_blank*) for clickable links; used in conjunction with the **href** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/target" + }, + "tension": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The tension option only has an effect on bundle, cardinal and Catmull–Rom splines (*bundle*, *cardinal*, *cardinal-open*, *cardinal-closed*,\n*catmull-rom*, *catmull-rom-open*, and *catmull-rom-closed*). For bundle splines, it corresponds to [beta][1]; for cardinal splines, [tension][2]; for Catmull–Rom splines, [alpha][3].\n\n[1]: https://d3js.org/d3-shape/curve#curveBundle_beta [2]: https://d3js.org/d3-shape/curve#curveCardinal_tension [3]: https://d3js.org/d3-shape/curve#curveCatmullRom_alpha" + }, + "tip": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/TipPointer" + }, + { + "properties": { + "anchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The tip anchor specifies how to orient the tip box relative to its anchor position; it refers to the part of the tip box that is attached to the anchor point. For example, the *top-left* anchor places the top-left corner of tip box near the anchor position, hence placing the tip box below and to the right of the anchor position." + }, + "fontFamily": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font-family][1]; a constant; defaults to the plot’s font family, which is typically [*system-ui*][2].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-family [2]: https://drafts.csswg.org/css-fonts-4/#valdef-font-family-system-ui" + }, + "fontSize": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font size][1] in pixels; either a constant or a channel; defaults to the plot’s font size, which is typically 10. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-size" + }, + "fontStyle": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font style][1]; a constant; defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-style" + }, + "fontVariant": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font variant][1]; a constant; if the **text** channel contains numbers or dates, defaults to *tabular-nums* to facilitate comparing numbers; otherwise defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant" + }, + "fontWeight": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font weight][1]; a constant; defaults to the plot’s font weight, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight" + }, + "format": { + "additionalProperties": false, + "description": "How channel values are formatted for display. If a format is a string, it is interpreted as a (UTC) time format for temporal channels, and otherwise a number format.", + "properties": { + "ariaLabel": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fill": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fillOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fontSize": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fx": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fy": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "geometry": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "height": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "href": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "length": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "opacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "path": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "r": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "rotate": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "src": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "stroke": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeWidth": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "symbol": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "text": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "title": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "weight": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "width": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "z": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + } + }, + "type": "object" + }, + "frameAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The frame anchor specifies defaults for **x** and **y** based on the plot’s frame; it may be one of the four sides (*top*, *right*, *bottom*, *left*), one of the four corners (*top-left*, *top-right*, *bottom-right*,\n*bottom-left*), or the *middle* of the frame. For example, for tips distributed horizontally at the top of the frame:\n\n```js Plot.tip(data, {x: \"date\", frameAnchor: \"top\"}) ```" + }, + "lineHeight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line height in ems; defaults to 1. The line height affects the (typically vertical) separation between adjacent baselines of text, as well as the separation between the text and its anchor point." + }, + "lineWidth": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line width in ems (e.g., 10 for about 20 characters); defaults to infinity, disabling wrapping and clipping.\n\nIf **textOverflow** is null, lines will be wrapped at the specified length. If a line is split at a soft hyphen (\\xad), a hyphen (-) will be displayed at the end of the line. If **textOverflow** is not null, lines will be clipped according to the given strategy." + }, + "monospace": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, changes the default **fontFamily** to *monospace*, and uses simplified monospaced text metrics calculations." + }, + "pathFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The image filter for the tip’s box; defaults to a drop shadow." + }, + "pointer": { + "$ref": "#/definitions/TipPointer" + }, + "pointerSize": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The size of the tip’s pointer in pixels; defaults to 12." + }, + "preferredAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If an explicit tip anchor is not specified, an anchor is chosen automatically such that the tip fits within the plot’s frame; if the preferred anchor fits, it is chosen." + }, + "textAnchor": { + "anyOf": [ + { + "const": "start", + "type": "string" + }, + { + "const": "middle", + "type": "string" + }, + { + "const": "end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [text anchor][1] controls how text is aligned (typically horizontally) relative to its anchor point; it is one of *start*, *end*, or *middle*. If the frame anchor is *left*, *top-left*, or *bottom-left*, the default text anchor is *start*; if the frame anchor is *right*, *top-right*, or\n*bottom-right*, the default is *end*; otherwise it is *middle*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/text-anchor" + }, + "textOverflow": { + "anyOf": [ + { + "type": "null" + }, + { + "const": "clip", + "type": "string" + }, + { + "const": "ellipsis", + "type": "string" + }, + { + "const": "clip-start", + "type": "string" + }, + { + "const": "clip-end", + "type": "string" + }, + { + "const": "ellipsis-start", + "type": "string" + }, + { + "const": "ellipsis-middle", + "type": "string" + }, + { + "const": "ellipsis-end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How truncate (or wrap) lines of text longer than the given **lineWidth**; one of:\n\n- null (default) - preserve overflowing characters (and wrap if needed)\n- *clip* or *clip-end* - remove characters from the end\n- *clip-start* - remove characters from the start\n- *ellipsis* or *ellipsis-end* - replace characters from the end with an ellipsis (…)\n- *ellipsis-start* - replace characters from the start with an ellipsis (…)\n- *ellipsis-middle* - replace characters from the middle with an ellipsis (…)\n\nIf no **title** was specified, if text requires truncation, a title containing the non-truncated text will be implicitly added." + }, + "textPadding": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The padding around the text in pixels; defaults to 8." + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + } + }, + "type": "object" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to generate a tooltip for this mark, and any tip options." + }, + "title": { + "$ref": "#/definitions/ChannelValue", + "description": "The title; a channel specifying accessible, short textual descriptions as strings (possibly with newlines). If the tip option is specified, the title will be displayed with an interactive tooltip instead of using the SVG [title element][1].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/title" + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel, typically bound to the *x* scale; defaults to the zero-based index of the data [0, 1, 2, …]." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position (or length) channel, typically bound to the *y* scale.\n\nIf neither **y1** nor **y2** is specified, an implicit stackY transform is applied and **y** defaults to the identity function, assuming that *data* = [*y₀*, *y₁*, *y₂*, …]. Otherwise, if only one of **y1** or **y2** is specified, the other defaults to **y**, which defaults to zero." + }, + "y1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The required primary (starting, often bottom) vertical position channel, representing the area’s baseline, typically bound to the *y* scale. For areaY, setting this option disables the implicit stackY transform." + }, + "y2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The optional secondary (ending, often top) vertical position channel, representing the area’s topline, typically bound to the *y* scale; if not specified, **y1** is used. For areaY, setting this option disables the implicit stackY transform." + }, + "z": { + "$ref": "#/definitions/ChannelValue", + "description": "An optional ordinal channel for grouping data into (possibly stacked) series to be drawn as separate areas; defaults to **fill** if a channel, or\n**stroke** if a channel." + } + }, + "required": [ + "data", + "mark" + ], + "type": "object" + }, + "Argmax": { + "additionalProperties": false, + "properties": { + "argmax": { + "description": "Find a value of the first column that maximizes the second column.", + "items": { + "description": "A transform argument.", + "type": [ + "string", + "number", + "boolean" + ] + }, + "maxItems": 2, + "minItems": 2, + "type": "array" + }, + "distinct": { + "type": "boolean" + }, + "orderby": { + "anyOf": [ + { + "$ref": "#/definitions/TransformField" + }, + { + "items": { + "$ref": "#/definitions/TransformField" + }, + "type": "array" + } + ] + }, + "partitionby": { + "anyOf": [ + { + "$ref": "#/definitions/TransformField" + }, + { + "items": { + "$ref": "#/definitions/TransformField" + }, + "type": "array" + } + ] + }, + "range": { + "anyOf": [ + { + "items": { + "type": [ + "number", + "null" + ] + }, + "type": "array" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "rows": { + "anyOf": [ + { + "items": { + "type": [ + "number", + "null" + ] + }, + "type": "array" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + } + }, + "required": [ + "argmax" + ], + "type": "object" + }, + "Argmin": { + "additionalProperties": false, + "properties": { + "argmin": { + "description": "Find a value of the first column that minimizes the second column.", + "items": { + "description": "A transform argument.", + "type": [ + "string", + "number", + "boolean" + ] + }, + "maxItems": 2, + "minItems": 2, + "type": "array" + }, + "distinct": { + "type": "boolean" + }, + "orderby": { + "anyOf": [ + { + "$ref": "#/definitions/TransformField" + }, + { + "items": { + "$ref": "#/definitions/TransformField" + }, + "type": "array" + } + ] + }, + "partitionby": { + "anyOf": [ + { + "$ref": "#/definitions/TransformField" + }, + { + "items": { + "$ref": "#/definitions/TransformField" + }, + "type": "array" + } + ] + }, + "range": { + "anyOf": [ + { + "items": { + "type": [ + "number", + "null" + ] + }, + "type": "array" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "rows": { + "anyOf": [ + { + "items": { + "type": [ + "number", + "null" + ] + }, + "type": "array" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + } + }, + "required": [ + "argmin" + ], + "type": "object" + }, + "Arrow": { + "additionalProperties": false, + "description": "The arrow mark.", + "properties": { + "ariaDescription": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-description][1]; a constant textual description.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-description" + }, + "ariaHidden": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-hidden][1] state; a constant indicating whether the element is exposed to an accessibility API.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-hidden" + }, + "ariaLabel": { + "$ref": "#/definitions/ChannelValue", + "description": "The [aria-label][1]; a channel specifying short textual labels representing the value in the accessibility tree.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-label" + }, + "bend": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The angle, a constant in degrees, between the straight line intersecting the arrow’s two control points and the outgoing tangent direction of the arrow from the start point. The angle must be within ±90°; a positive angle will produce a clockwise curve, while a negative angle will produce a counterclockwise curve; zero (the default) will produce a straight line. Use true for 22.5°." + }, + "clip": { + "anyOf": [ + { + "const": "frame", + "type": "string" + }, + { + "const": "sphere", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to clip the mark; one of:\n\n- *frame* or true - clip to the plot’s frame (inner area)\n- *sphere* - clip to the projected sphere (*e.g.*, front hemisphere)\n- null or false - do not clip\n\nThe *sphere* clip option requires a geographic projection." + }, + "data": { + "$ref": "#/definitions/PlotMarkData", + "description": "The data source for the mark." + }, + "dx": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The horizontal offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "dy": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The vertical offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "facet": { + "anyOf": [ + { + "const": "auto", + "type": "string" + }, + { + "const": "include", + "type": "string" + }, + { + "const": "exclude", + "type": "string" + }, + { + "const": "super", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to enable or disable faceting; one of:\n\n- *auto* (default) - automatically determine if this mark should be faceted\n- *include* (or true) - draw the subset of the mark’s data in the current facet\n- *exclude* - draw the subset of the mark’s data *not* in the current facet\n- *super* - draw this mark in a single frame that covers all facets\n- null (or false) - repeat this mark’s data across all facets (*i.e.*, no faceting)\n\nWhen a mark uses *super* faceting, it is not allowed to use position scales (*x*, *y*, *fx*, or *fy*); *super* faceting is intended for decorations, such as labels and legends.\n\nWhen top-level faceting is used, the default *auto* setting is equivalent to *include* when the mark data is strictly equal to the top-level facet data; otherwise it is equivalent to null. When the *include* or *exclude* facet mode is chosen, the mark data must be parallel to the top-level facet data: the data must have the same length and order. If the data are not parallel, then the wrong data may be shown in each facet. The default\n*auto* therefore requires strict equality (`===`) for safety, and using the facet data as mark data is recommended when using the *exclude* facet mode. (To construct parallel data safely, consider using [*array*.map][1] on the facet data.)\n\nWhen mark-level faceting is used, the default *auto* setting is equivalent to *include*: the mark will be faceted if either the **fx** or **fy** channel option (or both) is specified. The null or false option will disable faceting, while *exclude* draws the subset of the mark’s data *not* in the current facet.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map" + }, + "facetAnchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "right", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "const": "left", + "type": "string" + }, + { + "const": "top-left", + "type": "string" + }, + { + "const": "top-right", + "type": "string" + }, + { + "const": "bottom-left", + "type": "string" + }, + { + "const": "bottom-right", + "type": "string" + }, + { + "const": "top-empty", + "type": "string" + }, + { + "const": "right-empty", + "type": "string" + }, + { + "const": "bottom-empty", + "type": "string" + }, + { + "const": "left-empty", + "type": "string" + }, + { + "const": "empty", + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to place the mark with respect to facets; one of:\n\n- null (default for most marks) - display the mark in each non-empty facet\n- *top*, *right*, *bottom*, or *left* - display the mark only in facets on the given side\n- *top-empty*, *right-empty*, *bottom-empty*, or *left-empty* (default for axis marks) - display the mark only in facets that have empty space on the given side: either the margin, or an empty facet\n- *empty* - display the mark in empty facets only" + }, + "fill": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill" + }, + "fillOpacity": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill-opacity][1]; a constant number between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill-opacity" + }, + "filter": { + "$ref": "#/definitions/ChannelValue", + "description": "Applies a transform to filter the mark’s index according to the given channel values; only truthy values are retained.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "fx": { + "$ref": "#/definitions/ChannelValue", + "description": "The horizontal facet position channel, for mark-level faceting, bound to the *fx* scale." + }, + "fy": { + "$ref": "#/definitions/ChannelValue", + "description": "The vertical facet position channel, for mark-level faceting, bound to the\n*fy* scale." + }, + "headAngle": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How pointy the arrowhead is, in degrees; a constant typically between 0° and 180°, and defaults to 60°." + }, + "headLength": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The size of the arrowhead relative to the **strokeWidth**; a constant. Assuming the default of stroke width 1.5px, this is the length of the arrowhead’s side in pixels." + }, + "href": { + "$ref": "#/definitions/ChannelValue", + "description": "The [href][1]; a channel specifying URLs for clickable links. May be used in conjunction with the **target** option to open links in another window.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/href" + }, + "imageFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A CSS [filter][1]; a constant string used to adjust the rendering of images, such as *blur(5px)*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/filter" + }, + "inset": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for **insetStart** and **insetEnd**." + }, + "insetEnd": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The ending inset, a constant in pixels; defaults to 0. A positive inset shortens the arrow by moving the ending point towards the starting point, while a negative inset extends it by moving the ending point in the opposite direction. A positive ending inset may be useful if the arrow points to a dot." + }, + "insetStart": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The starting inset, a constant in pixels; defaults to 0. A positive inset shortens the arrow by moving the starting point towards the endpoint point, while a negative inset extends it by moving the starting point in the opposite direction. A positive starting inset may be useful if the arrow emerges from a dot." + }, + "margin": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four mark margins: **marginTop**,\n**marginRight**, **marginBottom**, and **marginLeft**; typically defaults to 0, except for axis marks." + }, + "marginBottom": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s bottom margin; the minimum distance in pixels between the bottom edges of the inner and outer plot area." + }, + "marginLeft": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s left margin; the minimum distance in pixels between the left edges of the inner and outer plot area." + }, + "marginRight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s right margin; the minimum distance in pixels between the right edges of the mark’s inner and outer plot area." + }, + "marginTop": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s top margin; the minimum distance in pixels between the top edges of the inner and outer plot area." + }, + "mark": { + "const": "arrow", + "description": "An arrow mark, drawing (possibly swoopy) arrows connecting pairs of points.", + "type": "string" + }, + "mixBlendMode": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [mix-blend-mode][1]; a constant string specifying how to blend content such as *multiply*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode" + }, + "opacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally. For faster rendering, prefer the **strokeOpacity** or **fillOpacity** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/opacity" + }, + "paintOrder": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [paint-order][1]; a constant string specifying the order in which the\n**fill**, **stroke**, and any markers are drawn; defaults to *normal*, which draws the fill, then stroke, then markers; defaults to *stroke* for the text mark to create a “halo” around text to improve legibility.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/paint-order" + }, + "pointerEvents": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [pointer-events][1] property; a constant string such as *none*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/pointer-events" + }, + "reverse": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Applies a transform to reverse the order of the mark’s index, say for reverse input order." + }, + "select": { + "$ref": "#/definitions/SelectFilter", + "description": "Applies a filter transform after data is loaded to highlight selected values only. For example, `first` and `last` select the first or last values of series only (using the *z* channel to separate series). Meanwhile, `nearestX` and `nearestY` select the point nearest to the pointer along the *x* or *y* channel dimension. Unlike Mosaic selections, a mark level *select* is internal to the mark only, and does not populate a param or selection value to be shared across clients.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "shapeRendering": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [shape-rendering][1]; a constant string such as *crispEdges*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/shape-rendering" + }, + "sort": { + "anyOf": [ + { + "$ref": "#/definitions/SortOrder" + }, + { + "$ref": "#/definitions/ChannelDomainSort" + } + ], + "description": "Either applies a transform to sort the mark’s index by the specified channel values, or imputes ordinal scale domains from this mark’s channels.\n\nWhen imputing ordinal scale domains from channel values, the **sort** option is an object whose keys are ordinal scale names such as *x* or *fx*, and whose values are channel names such as *y*, *y1*, or *y2*. For example, to impute the *y* scale’s domain from the associated *x* channel values in ascending order:\n\n```js sort: {y: \"x\"} ```\n\nFor different sort options for different scales, replace the channel name with a *value* object and per-scale options:\n\n```js sort: {y: {value: \"-x\"}} ```\n\nWhen sorting the mark’s index, the **sort** option is instead one of:\n\n- a channel value definition for sorting given values in ascending order\n- a {value, order} object for sorting given values\n- a {channel, order} object for sorting the named channel’s values" + }, + "stroke": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke" + }, + "strokeDasharray": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dasharray][1]; a constant number indicating the length in pixels of alternating dashes and gaps, or a constant string of numbers separated by spaces or commas (_e.g._, *10 2* for dashes of 10 pixels separated by gaps of 2 pixels), or *none* (the default) for no dashing\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dasharray" + }, + "strokeDashoffset": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dashoffset][1]; a constant indicating the offset in pixels of the first dash along the stroke; defaults to zero.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dashoffset" + }, + "strokeLinecap": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linecap][1]; a constant specifying how to cap stroked paths, such as *butt*, *round*, or *square*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linecap" + }, + "strokeLinejoin": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linejoin][1]; a constant specifying how to join stroked paths, such as *bevel*, *miter*, *miter-clip*, or *round*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linejoin" + }, + "strokeMiterlimit": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-miterlimit][1]; a constant number specifying how to limit the length of *miter* joins on stroked paths.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-miterlimit" + }, + "strokeOpacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-opacity" + }, + "strokeWidth": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-width][1]; a constant number in pixels, or a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-width" + }, + "sweep": { + "anyOf": [ + { + "type": "number" + }, + { + "const": "+x", + "type": "string" + }, + { + "const": "-x", + "type": "string" + }, + { + "const": "+y", + "type": "string" + }, + { + "const": "-y", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The sweep order; defaults to 1 indicating a positive (clockwise) bend angle; -1 indicates a negative (anticlockwise) bend angle; 0 effectively clears the bend angle. If set to *-x*, the bend angle is flipped when the ending point is to the left of the starting point — ensuring all arrows bulge up (down if bend is negative); if set to *-y*, the bend angle is flipped when the ending point is above the starting point — ensuring all arrows bulge right (left if bend is negative); the sign is negated for\n*+x* and *+y*." + }, + "target": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [target][1]; a constant string specifying the target window (_e.g._,\n*_blank*) for clickable links; used in conjunction with the **href** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/target" + }, + "tip": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/TipPointer" + }, + { + "properties": { + "anchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The tip anchor specifies how to orient the tip box relative to its anchor position; it refers to the part of the tip box that is attached to the anchor point. For example, the *top-left* anchor places the top-left corner of tip box near the anchor position, hence placing the tip box below and to the right of the anchor position." + }, + "fontFamily": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font-family][1]; a constant; defaults to the plot’s font family, which is typically [*system-ui*][2].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-family [2]: https://drafts.csswg.org/css-fonts-4/#valdef-font-family-system-ui" + }, + "fontSize": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font size][1] in pixels; either a constant or a channel; defaults to the plot’s font size, which is typically 10. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-size" + }, + "fontStyle": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font style][1]; a constant; defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-style" + }, + "fontVariant": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font variant][1]; a constant; if the **text** channel contains numbers or dates, defaults to *tabular-nums* to facilitate comparing numbers; otherwise defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant" + }, + "fontWeight": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font weight][1]; a constant; defaults to the plot’s font weight, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight" + }, + "format": { + "additionalProperties": false, + "description": "How channel values are formatted for display. If a format is a string, it is interpreted as a (UTC) time format for temporal channels, and otherwise a number format.", + "properties": { + "ariaLabel": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fill": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fillOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fontSize": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fx": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fy": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "geometry": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "height": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "href": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "length": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "opacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "path": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "r": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "rotate": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "src": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "stroke": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeWidth": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "symbol": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "text": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "title": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "weight": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "width": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "z": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + } + }, + "type": "object" + }, + "frameAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The frame anchor specifies defaults for **x** and **y** based on the plot’s frame; it may be one of the four sides (*top*, *right*, *bottom*, *left*), one of the four corners (*top-left*, *top-right*, *bottom-right*,\n*bottom-left*), or the *middle* of the frame. For example, for tips distributed horizontally at the top of the frame:\n\n```js Plot.tip(data, {x: \"date\", frameAnchor: \"top\"}) ```" + }, + "lineHeight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line height in ems; defaults to 1. The line height affects the (typically vertical) separation between adjacent baselines of text, as well as the separation between the text and its anchor point." + }, + "lineWidth": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line width in ems (e.g., 10 for about 20 characters); defaults to infinity, disabling wrapping and clipping.\n\nIf **textOverflow** is null, lines will be wrapped at the specified length. If a line is split at a soft hyphen (\\xad), a hyphen (-) will be displayed at the end of the line. If **textOverflow** is not null, lines will be clipped according to the given strategy." + }, + "monospace": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, changes the default **fontFamily** to *monospace*, and uses simplified monospaced text metrics calculations." + }, + "pathFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The image filter for the tip’s box; defaults to a drop shadow." + }, + "pointer": { + "$ref": "#/definitions/TipPointer" + }, + "pointerSize": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The size of the tip’s pointer in pixels; defaults to 12." + }, + "preferredAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If an explicit tip anchor is not specified, an anchor is chosen automatically such that the tip fits within the plot’s frame; if the preferred anchor fits, it is chosen." + }, + "textAnchor": { + "anyOf": [ + { + "const": "start", + "type": "string" + }, + { + "const": "middle", + "type": "string" + }, + { + "const": "end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [text anchor][1] controls how text is aligned (typically horizontally) relative to its anchor point; it is one of *start*, *end*, or *middle*. If the frame anchor is *left*, *top-left*, or *bottom-left*, the default text anchor is *start*; if the frame anchor is *right*, *top-right*, or\n*bottom-right*, the default is *end*; otherwise it is *middle*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/text-anchor" + }, + "textOverflow": { + "anyOf": [ + { + "type": "null" + }, + { + "const": "clip", + "type": "string" + }, + { + "const": "ellipsis", + "type": "string" + }, + { + "const": "clip-start", + "type": "string" + }, + { + "const": "clip-end", + "type": "string" + }, + { + "const": "ellipsis-start", + "type": "string" + }, + { + "const": "ellipsis-middle", + "type": "string" + }, + { + "const": "ellipsis-end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How truncate (or wrap) lines of text longer than the given **lineWidth**; one of:\n\n- null (default) - preserve overflowing characters (and wrap if needed)\n- *clip* or *clip-end* - remove characters from the end\n- *clip-start* - remove characters from the start\n- *ellipsis* or *ellipsis-end* - replace characters from the end with an ellipsis (…)\n- *ellipsis-start* - replace characters from the start with an ellipsis (…)\n- *ellipsis-middle* - replace characters from the middle with an ellipsis (…)\n\nIf no **title** was specified, if text requires truncation, a title containing the non-truncated text will be implicitly added." + }, + "textPadding": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The padding around the text in pixels; defaults to 8." + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + } + }, + "type": "object" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to generate a tooltip for this mark, and any tip options." + }, + "title": { + "$ref": "#/definitions/ChannelValue", + "description": "The title; a channel specifying accessible, short textual descriptions as strings (possibly with newlines). If the tip option is specified, the title will be displayed with an interactive tooltip instead of using the SVG [title element][1].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/title" + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position, for vertical arrows; typically bound to the *x* scale; shorthand for setting defaults for both **x1** and **x2**." + }, + "x1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting horizontal position; typically bound to the *x* scale; also sets a default for **x2**." + }, + "x2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending horizontal position; typically bound to the *x* scale; also sets a default for **x1**." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position, for horizontal arrows; typically bound to the *y* scale; shorthand for setting defaults for both **y1** and **y2**." + }, + "y1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting vertical position; typically bound to the *y* scale; also sets a default for **y2**." + }, + "y2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending vertical position; typically bound to the *y* scale; also sets a default for **y1**." + } + }, + "required": [ + "data", + "mark" + ], + "type": "object" + }, + "Avg": { + "additionalProperties": false, + "properties": { + "avg": { + "anyOf": [ + { + "description": "A transform argument.", + "type": [ + "string", + "number", + "boolean" + ] + }, + { + "items": { + "description": "A transform argument.", + "type": [ + "string", + "number", + "boolean" + ] + }, + "maxItems": 1, + "minItems": 1, + "type": "array" + } + ], + "description": "Compute the average (mean) value of the given column." + }, + "distinct": { + "type": "boolean" + }, + "orderby": { + "anyOf": [ + { + "$ref": "#/definitions/TransformField" + }, + { + "items": { + "$ref": "#/definitions/TransformField" + }, + "type": "array" + } + ] + }, + "partitionby": { + "anyOf": [ + { + "$ref": "#/definitions/TransformField" + }, + { + "items": { + "$ref": "#/definitions/TransformField" + }, + "type": "array" + } + ] + }, + "range": { + "anyOf": [ + { + "items": { + "type": [ + "number", + "null" + ] + }, + "type": "array" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "rows": { + "anyOf": [ + { + "items": { + "type": [ + "number", + "null" + ] + }, + "type": "array" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + } + }, + "required": [ + "avg" + ], + "type": "object" + }, + "AxisFx": { + "additionalProperties": false, + "description": "The axisFx mark.", + "properties": { + "anchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "right", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "const": "left", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The side of the frame on which to place the axis: *top* or *bottom* for horizontal axes (axisX and axisFx) and their associated vertical grids (gridX and gridFx), or *left* or *right* for vertical axes (axisY and axisFY) and their associated horizontal grids (gridY and gridFy).\n\nThe default **anchor** depends on the associated scale:\n\n- *x* - *bottom*\n- *y* - *left*\n- *fx* - *top* if there is a *bottom* *x* axis, and otherwise *bottom*\n- *fy* - *right* if there is a *left* *y* axis, and otherwise *right*\n\nFor grids, the **anchor** also affects the extent of grid lines when the opposite dimension is specified (**x** for gridY and **y** for gridX)." + }, + "ariaDescription": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-description][1]; a constant textual description.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-description" + }, + "ariaHidden": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-hidden][1] state; a constant indicating whether the element is exposed to an accessibility API.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-hidden" + }, + "ariaLabel": { + "$ref": "#/definitions/ChannelValue", + "description": "The [aria-label][1]; a channel specifying short textual labels representing the value in the accessibility tree.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-label" + }, + "clip": { + "anyOf": [ + { + "const": "frame", + "type": "string" + }, + { + "const": "sphere", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to clip the mark; one of:\n\n- *frame* or true - clip to the plot’s frame (inner area)\n- *sphere* - clip to the projected sphere (*e.g.*, front hemisphere)\n- null or false - do not clip\n\nThe *sphere* clip option requires a geographic projection." + }, + "color": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A shorthand for setting both **fill** and **stroke**; affects the stroke of tick vectors and grid rules, and the fill of tick texts and axis label texts; defaults to *currentColor*." + }, + "dx": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The horizontal offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "dy": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The vertical offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "facet": { + "anyOf": [ + { + "const": "auto", + "type": "string" + }, + { + "const": "include", + "type": "string" + }, + { + "const": "exclude", + "type": "string" + }, + { + "const": "super", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to enable or disable faceting; one of:\n\n- *auto* (default) - automatically determine if this mark should be faceted\n- *include* (or true) - draw the subset of the mark’s data in the current facet\n- *exclude* - draw the subset of the mark’s data *not* in the current facet\n- *super* - draw this mark in a single frame that covers all facets\n- null (or false) - repeat this mark’s data across all facets (*i.e.*, no faceting)\n\nWhen a mark uses *super* faceting, it is not allowed to use position scales (*x*, *y*, *fx*, or *fy*); *super* faceting is intended for decorations, such as labels and legends.\n\nWhen top-level faceting is used, the default *auto* setting is equivalent to *include* when the mark data is strictly equal to the top-level facet data; otherwise it is equivalent to null. When the *include* or *exclude* facet mode is chosen, the mark data must be parallel to the top-level facet data: the data must have the same length and order. If the data are not parallel, then the wrong data may be shown in each facet. The default\n*auto* therefore requires strict equality (`===`) for safety, and using the facet data as mark data is recommended when using the *exclude* facet mode. (To construct parallel data safely, consider using [*array*.map][1] on the facet data.)\n\nWhen mark-level faceting is used, the default *auto* setting is equivalent to *include*: the mark will be faceted if either the **fx** or **fy** channel option (or both) is specified. The null or false option will disable faceting, while *exclude* draws the subset of the mark’s data *not* in the current facet.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map" + }, + "facetAnchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "right", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "const": "left", + "type": "string" + }, + { + "const": "top-left", + "type": "string" + }, + { + "const": "top-right", + "type": "string" + }, + { + "const": "bottom-left", + "type": "string" + }, + { + "const": "bottom-right", + "type": "string" + }, + { + "const": "top-empty", + "type": "string" + }, + { + "const": "right-empty", + "type": "string" + }, + { + "const": "bottom-empty", + "type": "string" + }, + { + "const": "left-empty", + "type": "string" + }, + { + "const": "empty", + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to place the mark with respect to facets; one of:\n\n- null (default for most marks) - display the mark in each non-empty facet\n- *top*, *right*, *bottom*, or *left* - display the mark only in facets on the given side\n- *top-empty*, *right-empty*, *bottom-empty*, or *left-empty* (default for axis marks) - display the mark only in facets that have empty space on the given side: either the margin, or an empty facet\n- *empty* - display the mark in empty facets only" + }, + "fill": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill" + }, + "fillOpacity": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill-opacity][1]; a constant number between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill-opacity" + }, + "filter": { + "$ref": "#/definitions/ChannelValue", + "description": "Applies a transform to filter the mark’s index according to the given channel values; only truthy values are retained.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "fontFamily": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font-family][1]; a constant; defaults to the plot’s font family, which is typically [*system-ui*][2].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-family [2]: https://drafts.csswg.org/css-fonts-4/#valdef-font-family-system-ui" + }, + "fontSize": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font size][1] in pixels; either a constant or a channel; defaults to the plot’s font size, which is typically 10. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-size" + }, + "fontStyle": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font style][1]; a constant; defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-style" + }, + "fontVariant": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font variant][1]; a constant; if the **text** channel contains numbers or dates, defaults to *tabular-nums* to facilitate comparing numbers; otherwise defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant" + }, + "fontWeight": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font weight][1]; a constant; defaults to the plot’s font weight, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight" + }, + "frameAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The frame anchor specifies defaults for **x** and **y**, along with\n**textAnchor** and **lineAnchor**, based on the plot’s frame; it may be one of the four sides (*top*, *right*, *bottom*, *left*), one of the four corners (*top-left*, *top-right*, *bottom-right*, *bottom-left*), or the\n*middle* of the frame." + }, + "fx": { + "$ref": "#/definitions/ChannelValue", + "description": "The horizontal facet position channel, for mark-level faceting, bound to the *fx* scale." + }, + "fy": { + "$ref": "#/definitions/ChannelValue", + "description": "The vertical facet position channel, for mark-level faceting, bound to the\n*fy* scale." + }, + "href": { + "$ref": "#/definitions/ChannelValue", + "description": "The [href][1]; a channel specifying URLs for clickable links. May be used in conjunction with the **target** option to open links in another window.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/href" + }, + "imageFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A CSS [filter][1]; a constant string used to adjust the rendering of images, such as *blur(5px)*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/filter" + }, + "inset": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four insets: **insetTop**,\n**insetRight**, **insetBottom**, and **insetLeft**. All insets typically default to zero, though not always (say when using bin transform). A positive inset reduces effective area, while a negative inset increases it." + }, + "insetBottom": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Insets the bottom edge by the specified number of pixels. A positive value insets towards the top edge (reducing effective area), while a negative value insets away from the top edge (increasing it)." + }, + "insetTop": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Insets the top edge by the specified number of pixels. A positive value insets towards the bottom edge (reducing effective area), while a negative value insets away from the bottom edge (increasing it)." + }, + "interval": { + "anyOf": [ + { + "$ref": "#/definitions/Interval" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Enforces uniformity for data at regular intervals, such as integer values or daily samples. The interval may be one of:\n\n- a named time interval such as *day* (for date intervals)\n- a number (for number intervals), defining intervals at integer multiples of *n*\n\nThis option sets the internal transform to the given interval’s\n*interval*.floor function. In addition, the default **domain** will align with interval boundaries." + }, + "label": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A textual label to show on the axis or legend; if null, show no label. By default the scale label is inferred from channel definitions, possibly with an arrow (↑, →, ↓, or ←) to indicate the direction of increasing value.\n\nFor axes and legends only." + }, + "labelAnchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "right", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "const": "left", + "type": "string" + }, + { + "const": "center", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Where to place the axis **label** relative to the plot’s frame. For vertical position scales (*y* and *fy*), may be *top*, *bottom*, or\n*center*; for horizontal position scales (*x* and *fx*), may be *left*,\n*right*, or *center*. Defaults to *center* for ordinal scales (including\n*fx* and *fy*), and otherwise *top* for *y*, and *right* for *x*." + }, + "labelArrow": { + "anyOf": [ + { + "const": "auto", + "type": "string" + }, + { + "const": "up", + "type": "string" + }, + { + "const": "right", + "type": "string" + }, + { + "const": "down", + "type": "string" + }, + { + "const": "left", + "type": "string" + }, + { + "const": "none", + "type": "string" + }, + { + "const": true, + "type": "boolean" + }, + { + "const": false, + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to apply a directional arrow such as → or ↑ to the scale label. If\n*auto* (the default), the presence of the arrow depends on whether the scale is ordinal." + }, + "labelOffset": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The axis **label** position offset (in pixels); default depends on margins and orientation." + }, + "lineAnchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "middle", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line anchor controls how text is aligned (typically vertically) relative to its anchor point; it is one of *top*, *bottom*, or *middle*. If the frame anchor is *top*, *top-left*, or *top-right*, the default line anchor is *top*; if the frame anchor is *bottom*, *bottom-right*, or\n*bottom-left*, the default is *bottom*; otherwise it is *middle*." + }, + "lineHeight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line height in ems; defaults to 1. The line height affects the (typically vertical) separation between adjacent baselines of text, as well as the separation between the text and its anchor point." + }, + "lineWidth": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line width in ems (e.g., 10 for about 20 characters); defaults to infinity, disabling wrapping and clipping.\n\nIf **textOverflow** is null, lines will be wrapped at the specified length. If a line is split at a soft hyphen (\\xad), a hyphen (-) will be displayed at the end of the line. If **textOverflow** is not null, lines will be clipped according to the given strategy." + }, + "margin": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four mark margins: **marginTop**,\n**marginRight**, **marginBottom**, and **marginLeft**; typically defaults to 0, except for axis marks." + }, + "marginBottom": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s bottom margin; the minimum distance in pixels between the bottom edges of the inner and outer plot area." + }, + "marginLeft": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s left margin; the minimum distance in pixels between the left edges of the inner and outer plot area." + }, + "marginRight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s right margin; the minimum distance in pixels between the right edges of the mark’s inner and outer plot area." + }, + "marginTop": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s top margin; the minimum distance in pixels between the top edges of the inner and outer plot area." + }, + "mark": { + "const": "axisFx", + "description": "An axis mark to document the visual encoding of the horizontal facet position *fx* scale, comprised of (up to) three marks: a vector for ticks, a text for tick labels, and another text for an axis label. The data defaults to the *fx* scale’s domain; if desired, use one of the **ticks**,\n**tickSpacing**, or **interval** options.\n\nThe **facetAnchor** and **frameAnchor** options defaults to **anchor**. The default margins likewise depend on **anchor** as follows; in order of\n**marginTop**, **marginRight**, **marginBottom**, and **marginLeft**, in pixels:\n\n- *top* - 30, 20, 0, 20\n- *bottom* - 0, 20, 30, 20\n\nFor simplicity, and for consistent layout across plots, default axis margins are not affected by tick labels. If tick labels are too long, either increase the margin or shorten the labels: use the *k* SI-prefix tick format; use the\n**transform** *y*-scale option to show thousands or millions; or use the\n**textOverflow** and **lineWidth** options to clip.", + "type": "string" + }, + "marker": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for markerStart, markerMid, and markerEnd; one of:\n\n- a marker name such as *arrow* or *circle*\n- *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*" + }, + "markerEnd": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The marker for the ending point of a line segment; one of:\n\n- a marker name such as *arrow* or *circle*\n* *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*" + }, + "markerMid": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The marker for any middle (interior) points of a line segment. If the line segment only has a start and end point, this option has no effect. One of:\n\n- a marker name such as *arrow* or *circle*\n* *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*\n* a function - a custom marker function; see below" + }, + "markerStart": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The marker for the starting point of a line segment; one of:\n\n- a marker name such as *arrow* or *circle*\n* *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*" + }, + "mixBlendMode": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [mix-blend-mode][1]; a constant string specifying how to blend content such as *multiply*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode" + }, + "monospace": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, changes the default **fontFamily** to *monospace*, and uses simplified monospaced text metrics calculations." + }, + "opacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "A shorthand for setting both **fillOpacity** and **strokeOpacity**; affects the stroke opacity of tick vectors and grid rules, and the fill opacity of tick texts and axis label texts; defaults to 1 for axes and 0.1 for grids." + }, + "paintOrder": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [paint-order][1]; a constant string specifying the order in which the\n**fill**, **stroke**, and any markers are drawn; defaults to *normal*, which draws the fill, then stroke, then markers; defaults to *stroke* for the text mark to create a “halo” around text to improve legibility.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/paint-order" + }, + "pointerEvents": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [pointer-events][1] property; a constant string such as *none*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/pointer-events" + }, + "reverse": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Applies a transform to reverse the order of the mark’s index, say for reverse input order." + }, + "rotate": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The rotation angle in degrees clockwise; a constant or a channel; defaults to 0°. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel." + }, + "select": { + "$ref": "#/definitions/SelectFilter", + "description": "Applies a filter transform after data is loaded to highlight selected values only. For example, `first` and `last` select the first or last values of series only (using the *z* channel to separate series). Meanwhile, `nearestX` and `nearestY` select the point nearest to the pointer along the *x* or *y* channel dimension. Unlike Mosaic selections, a mark level *select* is internal to the mark only, and does not populate a param or selection value to be shared across clients.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "shapeRendering": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [shape-rendering][1]; a constant string such as *crispEdges*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/shape-rendering" + }, + "sort": { + "anyOf": [ + { + "$ref": "#/definitions/SortOrder" + }, + { + "$ref": "#/definitions/ChannelDomainSort" + } + ], + "description": "Either applies a transform to sort the mark’s index by the specified channel values, or imputes ordinal scale domains from this mark’s channels.\n\nWhen imputing ordinal scale domains from channel values, the **sort** option is an object whose keys are ordinal scale names such as *x* or *fx*, and whose values are channel names such as *y*, *y1*, or *y2*. For example, to impute the *y* scale’s domain from the associated *x* channel values in ascending order:\n\n```js sort: {y: \"x\"} ```\n\nFor different sort options for different scales, replace the channel name with a *value* object and per-scale options:\n\n```js sort: {y: {value: \"-x\"}} ```\n\nWhen sorting the mark’s index, the **sort** option is instead one of:\n\n- a channel value definition for sorting given values in ascending order\n- a {value, order} object for sorting given values\n- a {channel, order} object for sorting the named channel’s values" + }, + "stroke": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke" + }, + "strokeDasharray": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dasharray][1]; a constant number indicating the length in pixels of alternating dashes and gaps, or a constant string of numbers separated by spaces or commas (_e.g._, *10 2* for dashes of 10 pixels separated by gaps of 2 pixels), or *none* (the default) for no dashing\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dasharray" + }, + "strokeDashoffset": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dashoffset][1]; a constant indicating the offset in pixels of the first dash along the stroke; defaults to zero.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dashoffset" + }, + "strokeLinecap": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linecap][1]; a constant specifying how to cap stroked paths, such as *butt*, *round*, or *square*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linecap" + }, + "strokeLinejoin": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linejoin][1]; a constant specifying how to join stroked paths, such as *bevel*, *miter*, *miter-clip*, or *round*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linejoin" + }, + "strokeMiterlimit": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-miterlimit][1]; a constant number specifying how to limit the length of *miter* joins on stroked paths.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-miterlimit" + }, + "strokeOpacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-opacity" + }, + "strokeWidth": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-width][1]; a constant number in pixels, or a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-width" + }, + "target": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [target][1]; a constant string specifying the target window (_e.g._,\n*_blank*) for clickable links; used in conjunction with the **href** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/target" + }, + "text": { + "$ref": "#/definitions/ChannelValue", + "description": "The text contents channel, possibly with line breaks (\\n, \\r\\n, or \\r). If not specified, defaults to the zero-based index [0, 1, 2, …]." + }, + "textAnchor": { + "anyOf": [ + { + "const": "start", + "type": "string" + }, + { + "const": "middle", + "type": "string" + }, + { + "const": "end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [text anchor][1] controls how text is aligned (typically horizontally) relative to its anchor point; it is one of *start*, *end*, or *middle*. If the frame anchor is *left*, *top-left*, or *bottom-left*, the default text anchor is *start*; if the frame anchor is *right*, *top-right*, or\n*bottom-right*, the default is *end*; otherwise it is *middle*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/text-anchor" + }, + "textOverflow": { + "anyOf": [ + { + "type": "null" + }, + { + "const": "clip", + "type": "string" + }, + { + "const": "ellipsis", + "type": "string" + }, + { + "const": "clip-start", + "type": "string" + }, + { + "const": "clip-end", + "type": "string" + }, + { + "const": "ellipsis-start", + "type": "string" + }, + { + "const": "ellipsis-middle", + "type": "string" + }, + { + "const": "ellipsis-end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How truncate (or wrap) lines of text longer than the given **lineWidth**; one of:\n\n- null (default) - preserve overflowing characters (and wrap if needed)\n- *clip* or *clip-end* - remove characters from the end\n- *clip-start* - remove characters from the start\n- *ellipsis* or *ellipsis-end* - replace characters from the end with an ellipsis (…)\n- *ellipsis-start* - replace characters from the start with an ellipsis (…)\n- *ellipsis-middle* - replace characters from the middle with an ellipsis (…)\n\nIf no **title** was specified, if text requires truncation, a title containing the non-truncated text will be implicitly added." + }, + "textStroke": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The tick text **stroke**, say for a *white* outline to improve legibility; defaults to null." + }, + "textStrokeOpacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The tick text **strokeOpacity**; defaults to 1; has no effect unless **textStroke** is set." + }, + "textStrokeWidth": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The tick text **strokeWidth**; defaults to 4; has no effect unless **textStroke** is set." + }, + "tickFormat": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to format inputs (abstract values) for axis tick labels; one of:\n\n- a [d3-format][1] string for numeric scales\n- a [d3-time-format][2] string for temporal scales\n\n[1]: https://d3js.org/d3-time [2]: https://d3js.org/d3-time-format" + }, + "tickPadding": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The distance between an axis tick mark and its associated text label (in pixels); often defaults to 3, but may be affected by **xTickSize** and\n**xTickRotate**." + }, + "tickRotate": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The rotation angle of axis tick labels in degrees clocksize; defaults to 0." + }, + "tickSize": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The length of axis tick marks in pixels; negative values extend in the opposite direction. Defaults to 6 for *x* and *y* axes and *color* and\n*opacity* *ramp* legends, and 0 for *fx* and *fy* axes." + }, + "tickSpacing": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The desired approximate spacing between adjacent axis ticks, affecting the default **ticks**; defaults to 80 pixels for *x* and *fx*, and 35 pixels for *y* and *fy*." + }, + "ticks": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/Interval" + }, + { + "items": {}, + "type": "array" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The desired approximate number of axis ticks, or an explicit array of tick values, or an interval such as *day* or *month*." + }, + "tip": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/TipPointer" + }, + { + "properties": { + "anchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The tip anchor specifies how to orient the tip box relative to its anchor position; it refers to the part of the tip box that is attached to the anchor point. For example, the *top-left* anchor places the top-left corner of tip box near the anchor position, hence placing the tip box below and to the right of the anchor position." + }, + "fontFamily": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font-family][1]; a constant; defaults to the plot’s font family, which is typically [*system-ui*][2].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-family [2]: https://drafts.csswg.org/css-fonts-4/#valdef-font-family-system-ui" + }, + "fontSize": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font size][1] in pixels; either a constant or a channel; defaults to the plot’s font size, which is typically 10. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-size" + }, + "fontStyle": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font style][1]; a constant; defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-style" + }, + "fontVariant": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font variant][1]; a constant; if the **text** channel contains numbers or dates, defaults to *tabular-nums* to facilitate comparing numbers; otherwise defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant" + }, + "fontWeight": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font weight][1]; a constant; defaults to the plot’s font weight, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight" + }, + "format": { + "additionalProperties": false, + "description": "How channel values are formatted for display. If a format is a string, it is interpreted as a (UTC) time format for temporal channels, and otherwise a number format.", + "properties": { + "ariaLabel": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fill": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fillOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fontSize": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fx": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fy": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "geometry": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "height": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "href": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "length": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "opacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "path": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "r": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "rotate": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "src": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "stroke": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeWidth": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "symbol": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "text": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "title": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "weight": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "width": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "z": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + } + }, + "type": "object" + }, + "frameAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The frame anchor specifies defaults for **x** and **y** based on the plot’s frame; it may be one of the four sides (*top*, *right*, *bottom*, *left*), one of the four corners (*top-left*, *top-right*, *bottom-right*,\n*bottom-left*), or the *middle* of the frame. For example, for tips distributed horizontally at the top of the frame:\n\n```js Plot.tip(data, {x: \"date\", frameAnchor: \"top\"}) ```" + }, + "lineHeight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line height in ems; defaults to 1. The line height affects the (typically vertical) separation between adjacent baselines of text, as well as the separation between the text and its anchor point." + }, + "lineWidth": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line width in ems (e.g., 10 for about 20 characters); defaults to infinity, disabling wrapping and clipping.\n\nIf **textOverflow** is null, lines will be wrapped at the specified length. If a line is split at a soft hyphen (\\xad), a hyphen (-) will be displayed at the end of the line. If **textOverflow** is not null, lines will be clipped according to the given strategy." + }, + "monospace": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, changes the default **fontFamily** to *monospace*, and uses simplified monospaced text metrics calculations." + }, + "pathFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The image filter for the tip’s box; defaults to a drop shadow." + }, + "pointer": { + "$ref": "#/definitions/TipPointer" + }, + "pointerSize": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The size of the tip’s pointer in pixels; defaults to 12." + }, + "preferredAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If an explicit tip anchor is not specified, an anchor is chosen automatically such that the tip fits within the plot’s frame; if the preferred anchor fits, it is chosen." + }, + "textAnchor": { + "anyOf": [ + { + "const": "start", + "type": "string" + }, + { + "const": "middle", + "type": "string" + }, + { + "const": "end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [text anchor][1] controls how text is aligned (typically horizontally) relative to its anchor point; it is one of *start*, *end*, or *middle*. If the frame anchor is *left*, *top-left*, or *bottom-left*, the default text anchor is *start*; if the frame anchor is *right*, *top-right*, or\n*bottom-right*, the default is *end*; otherwise it is *middle*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/text-anchor" + }, + "textOverflow": { + "anyOf": [ + { + "type": "null" + }, + { + "const": "clip", + "type": "string" + }, + { + "const": "ellipsis", + "type": "string" + }, + { + "const": "clip-start", + "type": "string" + }, + { + "const": "clip-end", + "type": "string" + }, + { + "const": "ellipsis-start", + "type": "string" + }, + { + "const": "ellipsis-middle", + "type": "string" + }, + { + "const": "ellipsis-end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How truncate (or wrap) lines of text longer than the given **lineWidth**; one of:\n\n- null (default) - preserve overflowing characters (and wrap if needed)\n- *clip* or *clip-end* - remove characters from the end\n- *clip-start* - remove characters from the start\n- *ellipsis* or *ellipsis-end* - replace characters from the end with an ellipsis (…)\n- *ellipsis-start* - replace characters from the start with an ellipsis (…)\n- *ellipsis-middle* - replace characters from the middle with an ellipsis (…)\n\nIf no **title** was specified, if text requires truncation, a title containing the non-truncated text will be implicitly added." + }, + "textPadding": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The padding around the text in pixels; defaults to 8." + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + } + }, + "type": "object" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to generate a tooltip for this mark, and any tip options." + }, + "title": { + "$ref": "#/definitions/ChannelValue", + "description": "The title; a channel specifying accessible, short textual descriptions as strings (possibly with newlines). If the tip option is specified, the title will be displayed with an interactive tooltip instead of using the SVG [title element][1].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/title" + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel specifying the text’s anchor point, typically bound to the *x* scale." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel specifying the text’s anchor point, typically bound to the *y* scale." + }, + "z": { + "$ref": "#/definitions/ChannelValue", + "description": "An optional ordinal channel for grouping data into series." + } + }, + "required": [ + "mark" + ], + "type": "object" + }, + "AxisFy": { + "additionalProperties": false, + "description": "The axisFy mark.", + "properties": { + "anchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "right", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "const": "left", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The side of the frame on which to place the axis: *top* or *bottom* for horizontal axes (axisX and axisFx) and their associated vertical grids (gridX and gridFx), or *left* or *right* for vertical axes (axisY and axisFY) and their associated horizontal grids (gridY and gridFy).\n\nThe default **anchor** depends on the associated scale:\n\n- *x* - *bottom*\n- *y* - *left*\n- *fx* - *top* if there is a *bottom* *x* axis, and otherwise *bottom*\n- *fy* - *right* if there is a *left* *y* axis, and otherwise *right*\n\nFor grids, the **anchor** also affects the extent of grid lines when the opposite dimension is specified (**x** for gridY and **y** for gridX)." + }, + "ariaDescription": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-description][1]; a constant textual description.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-description" + }, + "ariaHidden": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-hidden][1] state; a constant indicating whether the element is exposed to an accessibility API.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-hidden" + }, + "ariaLabel": { + "$ref": "#/definitions/ChannelValue", + "description": "The [aria-label][1]; a channel specifying short textual labels representing the value in the accessibility tree.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-label" + }, + "clip": { + "anyOf": [ + { + "const": "frame", + "type": "string" + }, + { + "const": "sphere", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to clip the mark; one of:\n\n- *frame* or true - clip to the plot’s frame (inner area)\n- *sphere* - clip to the projected sphere (*e.g.*, front hemisphere)\n- null or false - do not clip\n\nThe *sphere* clip option requires a geographic projection." + }, + "color": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A shorthand for setting both **fill** and **stroke**; affects the stroke of tick vectors and grid rules, and the fill of tick texts and axis label texts; defaults to *currentColor*." + }, + "dx": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The horizontal offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "dy": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The vertical offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "facet": { + "anyOf": [ + { + "const": "auto", + "type": "string" + }, + { + "const": "include", + "type": "string" + }, + { + "const": "exclude", + "type": "string" + }, + { + "const": "super", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to enable or disable faceting; one of:\n\n- *auto* (default) - automatically determine if this mark should be faceted\n- *include* (or true) - draw the subset of the mark’s data in the current facet\n- *exclude* - draw the subset of the mark’s data *not* in the current facet\n- *super* - draw this mark in a single frame that covers all facets\n- null (or false) - repeat this mark’s data across all facets (*i.e.*, no faceting)\n\nWhen a mark uses *super* faceting, it is not allowed to use position scales (*x*, *y*, *fx*, or *fy*); *super* faceting is intended for decorations, such as labels and legends.\n\nWhen top-level faceting is used, the default *auto* setting is equivalent to *include* when the mark data is strictly equal to the top-level facet data; otherwise it is equivalent to null. When the *include* or *exclude* facet mode is chosen, the mark data must be parallel to the top-level facet data: the data must have the same length and order. If the data are not parallel, then the wrong data may be shown in each facet. The default\n*auto* therefore requires strict equality (`===`) for safety, and using the facet data as mark data is recommended when using the *exclude* facet mode. (To construct parallel data safely, consider using [*array*.map][1] on the facet data.)\n\nWhen mark-level faceting is used, the default *auto* setting is equivalent to *include*: the mark will be faceted if either the **fx** or **fy** channel option (or both) is specified. The null or false option will disable faceting, while *exclude* draws the subset of the mark’s data *not* in the current facet.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map" + }, + "facetAnchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "right", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "const": "left", + "type": "string" + }, + { + "const": "top-left", + "type": "string" + }, + { + "const": "top-right", + "type": "string" + }, + { + "const": "bottom-left", + "type": "string" + }, + { + "const": "bottom-right", + "type": "string" + }, + { + "const": "top-empty", + "type": "string" + }, + { + "const": "right-empty", + "type": "string" + }, + { + "const": "bottom-empty", + "type": "string" + }, + { + "const": "left-empty", + "type": "string" + }, + { + "const": "empty", + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to place the mark with respect to facets; one of:\n\n- null (default for most marks) - display the mark in each non-empty facet\n- *top*, *right*, *bottom*, or *left* - display the mark only in facets on the given side\n- *top-empty*, *right-empty*, *bottom-empty*, or *left-empty* (default for axis marks) - display the mark only in facets that have empty space on the given side: either the margin, or an empty facet\n- *empty* - display the mark in empty facets only" + }, + "fill": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill" + }, + "fillOpacity": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill-opacity][1]; a constant number between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill-opacity" + }, + "filter": { + "$ref": "#/definitions/ChannelValue", + "description": "Applies a transform to filter the mark’s index according to the given channel values; only truthy values are retained.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "fontFamily": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font-family][1]; a constant; defaults to the plot’s font family, which is typically [*system-ui*][2].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-family [2]: https://drafts.csswg.org/css-fonts-4/#valdef-font-family-system-ui" + }, + "fontSize": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font size][1] in pixels; either a constant or a channel; defaults to the plot’s font size, which is typically 10. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-size" + }, + "fontStyle": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font style][1]; a constant; defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-style" + }, + "fontVariant": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font variant][1]; a constant; if the **text** channel contains numbers or dates, defaults to *tabular-nums* to facilitate comparing numbers; otherwise defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant" + }, + "fontWeight": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font weight][1]; a constant; defaults to the plot’s font weight, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight" + }, + "frameAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The frame anchor specifies defaults for **x** and **y**, along with\n**textAnchor** and **lineAnchor**, based on the plot’s frame; it may be one of the four sides (*top*, *right*, *bottom*, *left*), one of the four corners (*top-left*, *top-right*, *bottom-right*, *bottom-left*), or the\n*middle* of the frame." + }, + "fx": { + "$ref": "#/definitions/ChannelValue", + "description": "The horizontal facet position channel, for mark-level faceting, bound to the *fx* scale." + }, + "fy": { + "$ref": "#/definitions/ChannelValue", + "description": "The vertical facet position channel, for mark-level faceting, bound to the\n*fy* scale." + }, + "href": { + "$ref": "#/definitions/ChannelValue", + "description": "The [href][1]; a channel specifying URLs for clickable links. May be used in conjunction with the **target** option to open links in another window.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/href" + }, + "imageFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A CSS [filter][1]; a constant string used to adjust the rendering of images, such as *blur(5px)*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/filter" + }, + "inset": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four insets: **insetTop**,\n**insetRight**, **insetBottom**, and **insetLeft**. All insets typically default to zero, though not always (say when using bin transform). A positive inset reduces effective area, while a negative inset increases it." + }, + "insetLeft": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Insets the left edge by the specified number of pixels. A positive value insets towards the right edge (reducing effective area), while a negative value insets away from the right edge (increasing it)." + }, + "insetRight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Insets the right edge by the specified number of pixels. A positive value insets towards the left edge (reducing effective area), while a negative value insets away from the left edge (increasing it)." + }, + "interval": { + "anyOf": [ + { + "$ref": "#/definitions/Interval" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Enforces uniformity for data at regular intervals, such as integer values or daily samples. The interval may be one of:\n\n- a named time interval such as *day* (for date intervals)\n- a number (for number intervals), defining intervals at integer multiples of *n*\n\nThis option sets the internal transform to the given interval’s\n*interval*.floor function. In addition, the default **domain** will align with interval boundaries." + }, + "label": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A textual label to show on the axis or legend; if null, show no label. By default the scale label is inferred from channel definitions, possibly with an arrow (↑, →, ↓, or ←) to indicate the direction of increasing value.\n\nFor axes and legends only." + }, + "labelAnchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "right", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "const": "left", + "type": "string" + }, + { + "const": "center", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Where to place the axis **label** relative to the plot’s frame. For vertical position scales (*y* and *fy*), may be *top*, *bottom*, or\n*center*; for horizontal position scales (*x* and *fx*), may be *left*,\n*right*, or *center*. Defaults to *center* for ordinal scales (including\n*fx* and *fy*), and otherwise *top* for *y*, and *right* for *x*." + }, + "labelArrow": { + "anyOf": [ + { + "const": "auto", + "type": "string" + }, + { + "const": "up", + "type": "string" + }, + { + "const": "right", + "type": "string" + }, + { + "const": "down", + "type": "string" + }, + { + "const": "left", + "type": "string" + }, + { + "const": "none", + "type": "string" + }, + { + "const": true, + "type": "boolean" + }, + { + "const": false, + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to apply a directional arrow such as → or ↑ to the scale label. If\n*auto* (the default), the presence of the arrow depends on whether the scale is ordinal." + }, + "labelOffset": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The axis **label** position offset (in pixels); default depends on margins and orientation." + }, + "lineAnchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "middle", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line anchor controls how text is aligned (typically vertically) relative to its anchor point; it is one of *top*, *bottom*, or *middle*. If the frame anchor is *top*, *top-left*, or *top-right*, the default line anchor is *top*; if the frame anchor is *bottom*, *bottom-right*, or\n*bottom-left*, the default is *bottom*; otherwise it is *middle*." + }, + "lineHeight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line height in ems; defaults to 1. The line height affects the (typically vertical) separation between adjacent baselines of text, as well as the separation between the text and its anchor point." + }, + "lineWidth": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line width in ems (e.g., 10 for about 20 characters); defaults to infinity, disabling wrapping and clipping.\n\nIf **textOverflow** is null, lines will be wrapped at the specified length. If a line is split at a soft hyphen (\\xad), a hyphen (-) will be displayed at the end of the line. If **textOverflow** is not null, lines will be clipped according to the given strategy." + }, + "margin": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four mark margins: **marginTop**,\n**marginRight**, **marginBottom**, and **marginLeft**; typically defaults to 0, except for axis marks." + }, + "marginBottom": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s bottom margin; the minimum distance in pixels between the bottom edges of the inner and outer plot area." + }, + "marginLeft": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s left margin; the minimum distance in pixels between the left edges of the inner and outer plot area." + }, + "marginRight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s right margin; the minimum distance in pixels between the right edges of the mark’s inner and outer plot area." + }, + "marginTop": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s top margin; the minimum distance in pixels between the top edges of the inner and outer plot area." + }, + "mark": { + "const": "axisFy", + "description": "An axis mark to document the visual encoding of the vertical facet position *fy* scale, comprised of (up to) three marks: a vector for ticks, a text for tick labels, and another text for an axis label. The data defaults to the *fy* scale’s domain; if desired, use one of the **ticks**,\n**tickSpacing**, or **interval** options.\n\nThe **facetAnchor** option defaults to *right-empty* if **anchor** is\n*right*, and *left-empty* if **anchor** is *left*. The default margins likewise depend on **anchor** as follows; in order of **marginTop**,\n**marginRight**, **marginBottom**, and **marginLeft**, in pixels:\n\n- *right* - 20, 40, 20, 0\n- *left* - 20, 0, 20, 40\n\nFor simplicity, and for consistent layout across plots, default axis margins are not affected by tick labels. If tick labels are too long, either increase the margin or shorten the labels: use the *k* SI-prefix tick format; or use the **textOverflow** and **lineWidth** options to clip.", + "type": "string" + }, + "marker": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for markerStart, markerMid, and markerEnd; one of:\n\n- a marker name such as *arrow* or *circle*\n- *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*" + }, + "markerEnd": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The marker for the ending point of a line segment; one of:\n\n- a marker name such as *arrow* or *circle*\n* *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*" + }, + "markerMid": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The marker for any middle (interior) points of a line segment. If the line segment only has a start and end point, this option has no effect. One of:\n\n- a marker name such as *arrow* or *circle*\n* *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*\n* a function - a custom marker function; see below" + }, + "markerStart": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The marker for the starting point of a line segment; one of:\n\n- a marker name such as *arrow* or *circle*\n* *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*" + }, + "mixBlendMode": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [mix-blend-mode][1]; a constant string specifying how to blend content such as *multiply*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode" + }, + "monospace": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, changes the default **fontFamily** to *monospace*, and uses simplified monospaced text metrics calculations." + }, + "opacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "A shorthand for setting both **fillOpacity** and **strokeOpacity**; affects the stroke opacity of tick vectors and grid rules, and the fill opacity of tick texts and axis label texts; defaults to 1 for axes and 0.1 for grids." + }, + "paintOrder": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [paint-order][1]; a constant string specifying the order in which the\n**fill**, **stroke**, and any markers are drawn; defaults to *normal*, which draws the fill, then stroke, then markers; defaults to *stroke* for the text mark to create a “halo” around text to improve legibility.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/paint-order" + }, + "pointerEvents": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [pointer-events][1] property; a constant string such as *none*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/pointer-events" + }, + "reverse": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Applies a transform to reverse the order of the mark’s index, say for reverse input order." + }, + "rotate": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The rotation angle in degrees clockwise; a constant or a channel; defaults to 0°. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel." + }, + "select": { + "$ref": "#/definitions/SelectFilter", + "description": "Applies a filter transform after data is loaded to highlight selected values only. For example, `first` and `last` select the first or last values of series only (using the *z* channel to separate series). Meanwhile, `nearestX` and `nearestY` select the point nearest to the pointer along the *x* or *y* channel dimension. Unlike Mosaic selections, a mark level *select* is internal to the mark only, and does not populate a param or selection value to be shared across clients.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "shapeRendering": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [shape-rendering][1]; a constant string such as *crispEdges*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/shape-rendering" + }, + "sort": { + "anyOf": [ + { + "$ref": "#/definitions/SortOrder" + }, + { + "$ref": "#/definitions/ChannelDomainSort" + } + ], + "description": "Either applies a transform to sort the mark’s index by the specified channel values, or imputes ordinal scale domains from this mark’s channels.\n\nWhen imputing ordinal scale domains from channel values, the **sort** option is an object whose keys are ordinal scale names such as *x* or *fx*, and whose values are channel names such as *y*, *y1*, or *y2*. For example, to impute the *y* scale’s domain from the associated *x* channel values in ascending order:\n\n```js sort: {y: \"x\"} ```\n\nFor different sort options for different scales, replace the channel name with a *value* object and per-scale options:\n\n```js sort: {y: {value: \"-x\"}} ```\n\nWhen sorting the mark’s index, the **sort** option is instead one of:\n\n- a channel value definition for sorting given values in ascending order\n- a {value, order} object for sorting given values\n- a {channel, order} object for sorting the named channel’s values" + }, + "stroke": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke" + }, + "strokeDasharray": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dasharray][1]; a constant number indicating the length in pixels of alternating dashes and gaps, or a constant string of numbers separated by spaces or commas (_e.g._, *10 2* for dashes of 10 pixels separated by gaps of 2 pixels), or *none* (the default) for no dashing\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dasharray" + }, + "strokeDashoffset": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dashoffset][1]; a constant indicating the offset in pixels of the first dash along the stroke; defaults to zero.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dashoffset" + }, + "strokeLinecap": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linecap][1]; a constant specifying how to cap stroked paths, such as *butt*, *round*, or *square*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linecap" + }, + "strokeLinejoin": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linejoin][1]; a constant specifying how to join stroked paths, such as *bevel*, *miter*, *miter-clip*, or *round*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linejoin" + }, + "strokeMiterlimit": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-miterlimit][1]; a constant number specifying how to limit the length of *miter* joins on stroked paths.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-miterlimit" + }, + "strokeOpacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-opacity" + }, + "strokeWidth": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-width][1]; a constant number in pixels, or a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-width" + }, + "target": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [target][1]; a constant string specifying the target window (_e.g._,\n*_blank*) for clickable links; used in conjunction with the **href** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/target" + }, + "text": { + "$ref": "#/definitions/ChannelValue", + "description": "The text contents channel, possibly with line breaks (\\n, \\r\\n, or \\r). If not specified, defaults to the zero-based index [0, 1, 2, …]." + }, + "textAnchor": { + "anyOf": [ + { + "const": "start", + "type": "string" + }, + { + "const": "middle", + "type": "string" + }, + { + "const": "end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [text anchor][1] controls how text is aligned (typically horizontally) relative to its anchor point; it is one of *start*, *end*, or *middle*. If the frame anchor is *left*, *top-left*, or *bottom-left*, the default text anchor is *start*; if the frame anchor is *right*, *top-right*, or\n*bottom-right*, the default is *end*; otherwise it is *middle*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/text-anchor" + }, + "textOverflow": { + "anyOf": [ + { + "type": "null" + }, + { + "const": "clip", + "type": "string" + }, + { + "const": "ellipsis", + "type": "string" + }, + { + "const": "clip-start", + "type": "string" + }, + { + "const": "clip-end", + "type": "string" + }, + { + "const": "ellipsis-start", + "type": "string" + }, + { + "const": "ellipsis-middle", + "type": "string" + }, + { + "const": "ellipsis-end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How truncate (or wrap) lines of text longer than the given **lineWidth**; one of:\n\n- null (default) - preserve overflowing characters (and wrap if needed)\n- *clip* or *clip-end* - remove characters from the end\n- *clip-start* - remove characters from the start\n- *ellipsis* or *ellipsis-end* - replace characters from the end with an ellipsis (…)\n- *ellipsis-start* - replace characters from the start with an ellipsis (…)\n- *ellipsis-middle* - replace characters from the middle with an ellipsis (…)\n\nIf no **title** was specified, if text requires truncation, a title containing the non-truncated text will be implicitly added." + }, + "textStroke": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The tick text **stroke**, say for a *white* outline to improve legibility; defaults to null." + }, + "textStrokeOpacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The tick text **strokeOpacity**; defaults to 1; has no effect unless **textStroke** is set." + }, + "textStrokeWidth": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The tick text **strokeWidth**; defaults to 4; has no effect unless **textStroke** is set." + }, + "tickFormat": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to format inputs (abstract values) for axis tick labels; one of:\n\n- a [d3-format][1] string for numeric scales\n- a [d3-time-format][2] string for temporal scales\n\n[1]: https://d3js.org/d3-time [2]: https://d3js.org/d3-time-format" + }, + "tickPadding": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The distance between an axis tick mark and its associated text label (in pixels); often defaults to 3, but may be affected by **xTickSize** and\n**xTickRotate**." + }, + "tickRotate": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The rotation angle of axis tick labels in degrees clocksize; defaults to 0." + }, + "tickSize": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The length of axis tick marks in pixels; negative values extend in the opposite direction. Defaults to 6 for *x* and *y* axes and *color* and\n*opacity* *ramp* legends, and 0 for *fx* and *fy* axes." + }, + "tickSpacing": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The desired approximate spacing between adjacent axis ticks, affecting the default **ticks**; defaults to 80 pixels for *x* and *fx*, and 35 pixels for *y* and *fy*." + }, + "ticks": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/Interval" + }, + { + "items": {}, + "type": "array" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The desired approximate number of axis ticks, or an explicit array of tick values, or an interval such as *day* or *month*." + }, + "tip": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/TipPointer" + }, + { + "properties": { + "anchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The tip anchor specifies how to orient the tip box relative to its anchor position; it refers to the part of the tip box that is attached to the anchor point. For example, the *top-left* anchor places the top-left corner of tip box near the anchor position, hence placing the tip box below and to the right of the anchor position." + }, + "fontFamily": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font-family][1]; a constant; defaults to the plot’s font family, which is typically [*system-ui*][2].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-family [2]: https://drafts.csswg.org/css-fonts-4/#valdef-font-family-system-ui" + }, + "fontSize": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font size][1] in pixels; either a constant or a channel; defaults to the plot’s font size, which is typically 10. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-size" + }, + "fontStyle": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font style][1]; a constant; defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-style" + }, + "fontVariant": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font variant][1]; a constant; if the **text** channel contains numbers or dates, defaults to *tabular-nums* to facilitate comparing numbers; otherwise defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant" + }, + "fontWeight": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font weight][1]; a constant; defaults to the plot’s font weight, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight" + }, + "format": { + "additionalProperties": false, + "description": "How channel values are formatted for display. If a format is a string, it is interpreted as a (UTC) time format for temporal channels, and otherwise a number format.", + "properties": { + "ariaLabel": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fill": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fillOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fontSize": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fx": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fy": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "geometry": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "height": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "href": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "length": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "opacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "path": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "r": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "rotate": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "src": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "stroke": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeWidth": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "symbol": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "text": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "title": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "weight": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "width": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "z": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + } + }, + "type": "object" + }, + "frameAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The frame anchor specifies defaults for **x** and **y** based on the plot’s frame; it may be one of the four sides (*top*, *right*, *bottom*, *left*), one of the four corners (*top-left*, *top-right*, *bottom-right*,\n*bottom-left*), or the *middle* of the frame. For example, for tips distributed horizontally at the top of the frame:\n\n```js Plot.tip(data, {x: \"date\", frameAnchor: \"top\"}) ```" + }, + "lineHeight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line height in ems; defaults to 1. The line height affects the (typically vertical) separation between adjacent baselines of text, as well as the separation between the text and its anchor point." + }, + "lineWidth": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line width in ems (e.g., 10 for about 20 characters); defaults to infinity, disabling wrapping and clipping.\n\nIf **textOverflow** is null, lines will be wrapped at the specified length. If a line is split at a soft hyphen (\\xad), a hyphen (-) will be displayed at the end of the line. If **textOverflow** is not null, lines will be clipped according to the given strategy." + }, + "monospace": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, changes the default **fontFamily** to *monospace*, and uses simplified monospaced text metrics calculations." + }, + "pathFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The image filter for the tip’s box; defaults to a drop shadow." + }, + "pointer": { + "$ref": "#/definitions/TipPointer" + }, + "pointerSize": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The size of the tip’s pointer in pixels; defaults to 12." + }, + "preferredAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If an explicit tip anchor is not specified, an anchor is chosen automatically such that the tip fits within the plot’s frame; if the preferred anchor fits, it is chosen." + }, + "textAnchor": { + "anyOf": [ + { + "const": "start", + "type": "string" + }, + { + "const": "middle", + "type": "string" + }, + { + "const": "end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [text anchor][1] controls how text is aligned (typically horizontally) relative to its anchor point; it is one of *start*, *end*, or *middle*. If the frame anchor is *left*, *top-left*, or *bottom-left*, the default text anchor is *start*; if the frame anchor is *right*, *top-right*, or\n*bottom-right*, the default is *end*; otherwise it is *middle*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/text-anchor" + }, + "textOverflow": { + "anyOf": [ + { + "type": "null" + }, + { + "const": "clip", + "type": "string" + }, + { + "const": "ellipsis", + "type": "string" + }, + { + "const": "clip-start", + "type": "string" + }, + { + "const": "clip-end", + "type": "string" + }, + { + "const": "ellipsis-start", + "type": "string" + }, + { + "const": "ellipsis-middle", + "type": "string" + }, + { + "const": "ellipsis-end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How truncate (or wrap) lines of text longer than the given **lineWidth**; one of:\n\n- null (default) - preserve overflowing characters (and wrap if needed)\n- *clip* or *clip-end* - remove characters from the end\n- *clip-start* - remove characters from the start\n- *ellipsis* or *ellipsis-end* - replace characters from the end with an ellipsis (…)\n- *ellipsis-start* - replace characters from the start with an ellipsis (…)\n- *ellipsis-middle* - replace characters from the middle with an ellipsis (…)\n\nIf no **title** was specified, if text requires truncation, a title containing the non-truncated text will be implicitly added." + }, + "textPadding": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The padding around the text in pixels; defaults to 8." + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + } + }, + "type": "object" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to generate a tooltip for this mark, and any tip options." + }, + "title": { + "$ref": "#/definitions/ChannelValue", + "description": "The title; a channel specifying accessible, short textual descriptions as strings (possibly with newlines). If the tip option is specified, the title will be displayed with an interactive tooltip instead of using the SVG [title element][1].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/title" + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel specifying the text’s anchor point, typically bound to the *x* scale." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel specifying the text’s anchor point, typically bound to the *y* scale." + }, + "z": { + "$ref": "#/definitions/ChannelValue", + "description": "An optional ordinal channel for grouping data into series." + } + }, + "required": [ + "mark" + ], + "type": "object" + }, + "AxisX": { + "additionalProperties": false, + "description": "The axisX mark.", + "properties": { + "anchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "right", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "const": "left", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The side of the frame on which to place the axis: *top* or *bottom* for horizontal axes (axisX and axisFx) and their associated vertical grids (gridX and gridFx), or *left* or *right* for vertical axes (axisY and axisFY) and their associated horizontal grids (gridY and gridFy).\n\nThe default **anchor** depends on the associated scale:\n\n- *x* - *bottom*\n- *y* - *left*\n- *fx* - *top* if there is a *bottom* *x* axis, and otherwise *bottom*\n- *fy* - *right* if there is a *left* *y* axis, and otherwise *right*\n\nFor grids, the **anchor** also affects the extent of grid lines when the opposite dimension is specified (**x** for gridY and **y** for gridX)." + }, + "ariaDescription": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-description][1]; a constant textual description.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-description" + }, + "ariaHidden": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-hidden][1] state; a constant indicating whether the element is exposed to an accessibility API.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-hidden" + }, + "ariaLabel": { + "$ref": "#/definitions/ChannelValue", + "description": "The [aria-label][1]; a channel specifying short textual labels representing the value in the accessibility tree.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-label" + }, + "clip": { + "anyOf": [ + { + "const": "frame", + "type": "string" + }, + { + "const": "sphere", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to clip the mark; one of:\n\n- *frame* or true - clip to the plot’s frame (inner area)\n- *sphere* - clip to the projected sphere (*e.g.*, front hemisphere)\n- null or false - do not clip\n\nThe *sphere* clip option requires a geographic projection." + }, + "color": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A shorthand for setting both **fill** and **stroke**; affects the stroke of tick vectors and grid rules, and the fill of tick texts and axis label texts; defaults to *currentColor*." + }, + "dx": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The horizontal offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "dy": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The vertical offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "facet": { + "anyOf": [ + { + "const": "auto", + "type": "string" + }, + { + "const": "include", + "type": "string" + }, + { + "const": "exclude", + "type": "string" + }, + { + "const": "super", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to enable or disable faceting; one of:\n\n- *auto* (default) - automatically determine if this mark should be faceted\n- *include* (or true) - draw the subset of the mark’s data in the current facet\n- *exclude* - draw the subset of the mark’s data *not* in the current facet\n- *super* - draw this mark in a single frame that covers all facets\n- null (or false) - repeat this mark’s data across all facets (*i.e.*, no faceting)\n\nWhen a mark uses *super* faceting, it is not allowed to use position scales (*x*, *y*, *fx*, or *fy*); *super* faceting is intended for decorations, such as labels and legends.\n\nWhen top-level faceting is used, the default *auto* setting is equivalent to *include* when the mark data is strictly equal to the top-level facet data; otherwise it is equivalent to null. When the *include* or *exclude* facet mode is chosen, the mark data must be parallel to the top-level facet data: the data must have the same length and order. If the data are not parallel, then the wrong data may be shown in each facet. The default\n*auto* therefore requires strict equality (`===`) for safety, and using the facet data as mark data is recommended when using the *exclude* facet mode. (To construct parallel data safely, consider using [*array*.map][1] on the facet data.)\n\nWhen mark-level faceting is used, the default *auto* setting is equivalent to *include*: the mark will be faceted if either the **fx** or **fy** channel option (or both) is specified. The null or false option will disable faceting, while *exclude* draws the subset of the mark’s data *not* in the current facet.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map" + }, + "facetAnchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "right", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "const": "left", + "type": "string" + }, + { + "const": "top-left", + "type": "string" + }, + { + "const": "top-right", + "type": "string" + }, + { + "const": "bottom-left", + "type": "string" + }, + { + "const": "bottom-right", + "type": "string" + }, + { + "const": "top-empty", + "type": "string" + }, + { + "const": "right-empty", + "type": "string" + }, + { + "const": "bottom-empty", + "type": "string" + }, + { + "const": "left-empty", + "type": "string" + }, + { + "const": "empty", + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to place the mark with respect to facets; one of:\n\n- null (default for most marks) - display the mark in each non-empty facet\n- *top*, *right*, *bottom*, or *left* - display the mark only in facets on the given side\n- *top-empty*, *right-empty*, *bottom-empty*, or *left-empty* (default for axis marks) - display the mark only in facets that have empty space on the given side: either the margin, or an empty facet\n- *empty* - display the mark in empty facets only" + }, + "fill": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill" + }, + "fillOpacity": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill-opacity][1]; a constant number between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill-opacity" + }, + "filter": { + "$ref": "#/definitions/ChannelValue", + "description": "Applies a transform to filter the mark’s index according to the given channel values; only truthy values are retained.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "fontFamily": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font-family][1]; a constant; defaults to the plot’s font family, which is typically [*system-ui*][2].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-family [2]: https://drafts.csswg.org/css-fonts-4/#valdef-font-family-system-ui" + }, + "fontSize": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font size][1] in pixels; either a constant or a channel; defaults to the plot’s font size, which is typically 10. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-size" + }, + "fontStyle": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font style][1]; a constant; defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-style" + }, + "fontVariant": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font variant][1]; a constant; if the **text** channel contains numbers or dates, defaults to *tabular-nums* to facilitate comparing numbers; otherwise defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant" + }, + "fontWeight": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font weight][1]; a constant; defaults to the plot’s font weight, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight" + }, + "frameAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The frame anchor specifies defaults for **x** and **y**, along with\n**textAnchor** and **lineAnchor**, based on the plot’s frame; it may be one of the four sides (*top*, *right*, *bottom*, *left*), one of the four corners (*top-left*, *top-right*, *bottom-right*, *bottom-left*), or the\n*middle* of the frame." + }, + "fx": { + "$ref": "#/definitions/ChannelValue", + "description": "The horizontal facet position channel, for mark-level faceting, bound to the *fx* scale." + }, + "fy": { + "$ref": "#/definitions/ChannelValue", + "description": "The vertical facet position channel, for mark-level faceting, bound to the\n*fy* scale." + }, + "href": { + "$ref": "#/definitions/ChannelValue", + "description": "The [href][1]; a channel specifying URLs for clickable links. May be used in conjunction with the **target** option to open links in another window.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/href" + }, + "imageFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A CSS [filter][1]; a constant string used to adjust the rendering of images, such as *blur(5px)*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/filter" + }, + "inset": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four insets: **insetTop**,\n**insetRight**, **insetBottom**, and **insetLeft**. All insets typically default to zero, though not always (say when using bin transform). A positive inset reduces effective area, while a negative inset increases it." + }, + "insetBottom": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Insets the bottom edge by the specified number of pixels. A positive value insets towards the top edge (reducing effective area), while a negative value insets away from the top edge (increasing it)." + }, + "insetTop": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Insets the top edge by the specified number of pixels. A positive value insets towards the bottom edge (reducing effective area), while a negative value insets away from the bottom edge (increasing it)." + }, + "interval": { + "anyOf": [ + { + "$ref": "#/definitions/Interval" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Enforces uniformity for data at regular intervals, such as integer values or daily samples. The interval may be one of:\n\n- a named time interval such as *day* (for date intervals)\n- a number (for number intervals), defining intervals at integer multiples of *n*\n\nThis option sets the internal transform to the given interval’s\n*interval*.floor function. In addition, the default **domain** will align with interval boundaries." + }, + "label": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A textual label to show on the axis or legend; if null, show no label. By default the scale label is inferred from channel definitions, possibly with an arrow (↑, →, ↓, or ←) to indicate the direction of increasing value.\n\nFor axes and legends only." + }, + "labelAnchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "right", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "const": "left", + "type": "string" + }, + { + "const": "center", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Where to place the axis **label** relative to the plot’s frame. For vertical position scales (*y* and *fy*), may be *top*, *bottom*, or\n*center*; for horizontal position scales (*x* and *fx*), may be *left*,\n*right*, or *center*. Defaults to *center* for ordinal scales (including\n*fx* and *fy*), and otherwise *top* for *y*, and *right* for *x*." + }, + "labelArrow": { + "anyOf": [ + { + "const": "auto", + "type": "string" + }, + { + "const": "up", + "type": "string" + }, + { + "const": "right", + "type": "string" + }, + { + "const": "down", + "type": "string" + }, + { + "const": "left", + "type": "string" + }, + { + "const": "none", + "type": "string" + }, + { + "const": true, + "type": "boolean" + }, + { + "const": false, + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to apply a directional arrow such as → or ↑ to the scale label. If\n*auto* (the default), the presence of the arrow depends on whether the scale is ordinal." + }, + "labelOffset": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The axis **label** position offset (in pixels); default depends on margins and orientation." + }, + "lineAnchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "middle", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line anchor controls how text is aligned (typically vertically) relative to its anchor point; it is one of *top*, *bottom*, or *middle*. If the frame anchor is *top*, *top-left*, or *top-right*, the default line anchor is *top*; if the frame anchor is *bottom*, *bottom-right*, or\n*bottom-left*, the default is *bottom*; otherwise it is *middle*." + }, + "lineHeight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line height in ems; defaults to 1. The line height affects the (typically vertical) separation between adjacent baselines of text, as well as the separation between the text and its anchor point." + }, + "lineWidth": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line width in ems (e.g., 10 for about 20 characters); defaults to infinity, disabling wrapping and clipping.\n\nIf **textOverflow** is null, lines will be wrapped at the specified length. If a line is split at a soft hyphen (\\xad), a hyphen (-) will be displayed at the end of the line. If **textOverflow** is not null, lines will be clipped according to the given strategy." + }, + "margin": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four mark margins: **marginTop**,\n**marginRight**, **marginBottom**, and **marginLeft**; typically defaults to 0, except for axis marks." + }, + "marginBottom": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s bottom margin; the minimum distance in pixels between the bottom edges of the inner and outer plot area." + }, + "marginLeft": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s left margin; the minimum distance in pixels between the left edges of the inner and outer plot area." + }, + "marginRight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s right margin; the minimum distance in pixels between the right edges of the mark’s inner and outer plot area." + }, + "marginTop": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s top margin; the minimum distance in pixels between the top edges of the inner and outer plot area." + }, + "mark": { + "const": "axisX", + "description": "An axis mark to document the visual encoding of the horizontal position\n*x* scale, comprised of (up to) three marks: a vector for ticks, a text for tick labels, and another text for an axis label. The data defaults to tick values sampled from the *x* scale’s domain; if desired, use one of the **ticks**, **tickSpacing**, or **interval** options.\n\nThe **facetAnchor** option defaults to *bottom-empty* if **anchor** is\n*bottom*, and *top-empty* if **anchor** is *top*. The default margins likewise depend on **anchor** as follows; in order of **marginTop**,\n**marginRight**, **marginBottom**, and **marginLeft**, in pixels:\n\n- *top* - 30, 20, 0, 20\n- *bottom* - 0, 20, 30, 20\n\nFor simplicity, and for consistent layout across plots, default axis margins are not affected by tick labels. If tick labels are too long, either increase the margin or shorten the labels: use the *k* SI-prefix tick format; use the\n**transform** *y*-scale option to show thousands or millions; or use the\n**textOverflow** and **lineWidth** options to clip.", + "type": "string" + }, + "marker": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for markerStart, markerMid, and markerEnd; one of:\n\n- a marker name such as *arrow* or *circle*\n- *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*" + }, + "markerEnd": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The marker for the ending point of a line segment; one of:\n\n- a marker name such as *arrow* or *circle*\n* *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*" + }, + "markerMid": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The marker for any middle (interior) points of a line segment. If the line segment only has a start and end point, this option has no effect. One of:\n\n- a marker name such as *arrow* or *circle*\n* *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*\n* a function - a custom marker function; see below" + }, + "markerStart": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The marker for the starting point of a line segment; one of:\n\n- a marker name such as *arrow* or *circle*\n* *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*" + }, + "mixBlendMode": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [mix-blend-mode][1]; a constant string specifying how to blend content such as *multiply*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode" + }, + "monospace": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, changes the default **fontFamily** to *monospace*, and uses simplified monospaced text metrics calculations." + }, + "opacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "A shorthand for setting both **fillOpacity** and **strokeOpacity**; affects the stroke opacity of tick vectors and grid rules, and the fill opacity of tick texts and axis label texts; defaults to 1 for axes and 0.1 for grids." + }, + "paintOrder": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [paint-order][1]; a constant string specifying the order in which the\n**fill**, **stroke**, and any markers are drawn; defaults to *normal*, which draws the fill, then stroke, then markers; defaults to *stroke* for the text mark to create a “halo” around text to improve legibility.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/paint-order" + }, + "pointerEvents": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [pointer-events][1] property; a constant string such as *none*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/pointer-events" + }, + "reverse": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Applies a transform to reverse the order of the mark’s index, say for reverse input order." + }, + "rotate": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The rotation angle in degrees clockwise; a constant or a channel; defaults to 0°. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel." + }, + "select": { + "$ref": "#/definitions/SelectFilter", + "description": "Applies a filter transform after data is loaded to highlight selected values only. For example, `first` and `last` select the first or last values of series only (using the *z* channel to separate series). Meanwhile, `nearestX` and `nearestY` select the point nearest to the pointer along the *x* or *y* channel dimension. Unlike Mosaic selections, a mark level *select* is internal to the mark only, and does not populate a param or selection value to be shared across clients.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "shapeRendering": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [shape-rendering][1]; a constant string such as *crispEdges*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/shape-rendering" + }, + "sort": { + "anyOf": [ + { + "$ref": "#/definitions/SortOrder" + }, + { + "$ref": "#/definitions/ChannelDomainSort" + } + ], + "description": "Either applies a transform to sort the mark’s index by the specified channel values, or imputes ordinal scale domains from this mark’s channels.\n\nWhen imputing ordinal scale domains from channel values, the **sort** option is an object whose keys are ordinal scale names such as *x* or *fx*, and whose values are channel names such as *y*, *y1*, or *y2*. For example, to impute the *y* scale’s domain from the associated *x* channel values in ascending order:\n\n```js sort: {y: \"x\"} ```\n\nFor different sort options for different scales, replace the channel name with a *value* object and per-scale options:\n\n```js sort: {y: {value: \"-x\"}} ```\n\nWhen sorting the mark’s index, the **sort** option is instead one of:\n\n- a channel value definition for sorting given values in ascending order\n- a {value, order} object for sorting given values\n- a {channel, order} object for sorting the named channel’s values" + }, + "stroke": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke" + }, + "strokeDasharray": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dasharray][1]; a constant number indicating the length in pixels of alternating dashes and gaps, or a constant string of numbers separated by spaces or commas (_e.g._, *10 2* for dashes of 10 pixels separated by gaps of 2 pixels), or *none* (the default) for no dashing\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dasharray" + }, + "strokeDashoffset": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dashoffset][1]; a constant indicating the offset in pixels of the first dash along the stroke; defaults to zero.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dashoffset" + }, + "strokeLinecap": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linecap][1]; a constant specifying how to cap stroked paths, such as *butt*, *round*, or *square*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linecap" + }, + "strokeLinejoin": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linejoin][1]; a constant specifying how to join stroked paths, such as *bevel*, *miter*, *miter-clip*, or *round*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linejoin" + }, + "strokeMiterlimit": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-miterlimit][1]; a constant number specifying how to limit the length of *miter* joins on stroked paths.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-miterlimit" + }, + "strokeOpacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-opacity" + }, + "strokeWidth": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-width][1]; a constant number in pixels, or a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-width" + }, + "target": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [target][1]; a constant string specifying the target window (_e.g._,\n*_blank*) for clickable links; used in conjunction with the **href** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/target" + }, + "text": { + "$ref": "#/definitions/ChannelValue", + "description": "The text contents channel, possibly with line breaks (\\n, \\r\\n, or \\r). If not specified, defaults to the zero-based index [0, 1, 2, …]." + }, + "textAnchor": { + "anyOf": [ + { + "const": "start", + "type": "string" + }, + { + "const": "middle", + "type": "string" + }, + { + "const": "end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [text anchor][1] controls how text is aligned (typically horizontally) relative to its anchor point; it is one of *start*, *end*, or *middle*. If the frame anchor is *left*, *top-left*, or *bottom-left*, the default text anchor is *start*; if the frame anchor is *right*, *top-right*, or\n*bottom-right*, the default is *end*; otherwise it is *middle*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/text-anchor" + }, + "textOverflow": { + "anyOf": [ + { + "type": "null" + }, + { + "const": "clip", + "type": "string" + }, + { + "const": "ellipsis", + "type": "string" + }, + { + "const": "clip-start", + "type": "string" + }, + { + "const": "clip-end", + "type": "string" + }, + { + "const": "ellipsis-start", + "type": "string" + }, + { + "const": "ellipsis-middle", + "type": "string" + }, + { + "const": "ellipsis-end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How truncate (or wrap) lines of text longer than the given **lineWidth**; one of:\n\n- null (default) - preserve overflowing characters (and wrap if needed)\n- *clip* or *clip-end* - remove characters from the end\n- *clip-start* - remove characters from the start\n- *ellipsis* or *ellipsis-end* - replace characters from the end with an ellipsis (…)\n- *ellipsis-start* - replace characters from the start with an ellipsis (…)\n- *ellipsis-middle* - replace characters from the middle with an ellipsis (…)\n\nIf no **title** was specified, if text requires truncation, a title containing the non-truncated text will be implicitly added." + }, + "textStroke": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The tick text **stroke**, say for a *white* outline to improve legibility; defaults to null." + }, + "textStrokeOpacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The tick text **strokeOpacity**; defaults to 1; has no effect unless **textStroke** is set." + }, + "textStrokeWidth": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The tick text **strokeWidth**; defaults to 4; has no effect unless **textStroke** is set." + }, + "tickFormat": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to format inputs (abstract values) for axis tick labels; one of:\n\n- a [d3-format][1] string for numeric scales\n- a [d3-time-format][2] string for temporal scales\n\n[1]: https://d3js.org/d3-time [2]: https://d3js.org/d3-time-format" + }, + "tickPadding": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The distance between an axis tick mark and its associated text label (in pixels); often defaults to 3, but may be affected by **xTickSize** and\n**xTickRotate**." + }, + "tickRotate": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The rotation angle of axis tick labels in degrees clocksize; defaults to 0." + }, + "tickSize": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The length of axis tick marks in pixels; negative values extend in the opposite direction. Defaults to 6 for *x* and *y* axes and *color* and\n*opacity* *ramp* legends, and 0 for *fx* and *fy* axes." + }, + "tickSpacing": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The desired approximate spacing between adjacent axis ticks, affecting the default **ticks**; defaults to 80 pixels for *x* and *fx*, and 35 pixels for *y* and *fy*." + }, + "ticks": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/Interval" + }, + { + "items": {}, + "type": "array" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The desired approximate number of axis ticks, or an explicit array of tick values, or an interval such as *day* or *month*." + }, + "tip": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/TipPointer" + }, + { + "properties": { + "anchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The tip anchor specifies how to orient the tip box relative to its anchor position; it refers to the part of the tip box that is attached to the anchor point. For example, the *top-left* anchor places the top-left corner of tip box near the anchor position, hence placing the tip box below and to the right of the anchor position." + }, + "fontFamily": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font-family][1]; a constant; defaults to the plot’s font family, which is typically [*system-ui*][2].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-family [2]: https://drafts.csswg.org/css-fonts-4/#valdef-font-family-system-ui" + }, + "fontSize": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font size][1] in pixels; either a constant or a channel; defaults to the plot’s font size, which is typically 10. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-size" + }, + "fontStyle": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font style][1]; a constant; defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-style" + }, + "fontVariant": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font variant][1]; a constant; if the **text** channel contains numbers or dates, defaults to *tabular-nums* to facilitate comparing numbers; otherwise defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant" + }, + "fontWeight": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font weight][1]; a constant; defaults to the plot’s font weight, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight" + }, + "format": { + "additionalProperties": false, + "description": "How channel values are formatted for display. If a format is a string, it is interpreted as a (UTC) time format for temporal channels, and otherwise a number format.", + "properties": { + "ariaLabel": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fill": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fillOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fontSize": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fx": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fy": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "geometry": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "height": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "href": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "length": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "opacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "path": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "r": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "rotate": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "src": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "stroke": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeWidth": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "symbol": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "text": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "title": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "weight": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "width": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "z": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + } + }, + "type": "object" + }, + "frameAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The frame anchor specifies defaults for **x** and **y** based on the plot’s frame; it may be one of the four sides (*top*, *right*, *bottom*, *left*), one of the four corners (*top-left*, *top-right*, *bottom-right*,\n*bottom-left*), or the *middle* of the frame. For example, for tips distributed horizontally at the top of the frame:\n\n```js Plot.tip(data, {x: \"date\", frameAnchor: \"top\"}) ```" + }, + "lineHeight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line height in ems; defaults to 1. The line height affects the (typically vertical) separation between adjacent baselines of text, as well as the separation between the text and its anchor point." + }, + "lineWidth": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line width in ems (e.g., 10 for about 20 characters); defaults to infinity, disabling wrapping and clipping.\n\nIf **textOverflow** is null, lines will be wrapped at the specified length. If a line is split at a soft hyphen (\\xad), a hyphen (-) will be displayed at the end of the line. If **textOverflow** is not null, lines will be clipped according to the given strategy." + }, + "monospace": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, changes the default **fontFamily** to *monospace*, and uses simplified monospaced text metrics calculations." + }, + "pathFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The image filter for the tip’s box; defaults to a drop shadow." + }, + "pointer": { + "$ref": "#/definitions/TipPointer" + }, + "pointerSize": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The size of the tip’s pointer in pixels; defaults to 12." + }, + "preferredAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If an explicit tip anchor is not specified, an anchor is chosen automatically such that the tip fits within the plot’s frame; if the preferred anchor fits, it is chosen." + }, + "textAnchor": { + "anyOf": [ + { + "const": "start", + "type": "string" + }, + { + "const": "middle", + "type": "string" + }, + { + "const": "end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [text anchor][1] controls how text is aligned (typically horizontally) relative to its anchor point; it is one of *start*, *end*, or *middle*. If the frame anchor is *left*, *top-left*, or *bottom-left*, the default text anchor is *start*; if the frame anchor is *right*, *top-right*, or\n*bottom-right*, the default is *end*; otherwise it is *middle*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/text-anchor" + }, + "textOverflow": { + "anyOf": [ + { + "type": "null" + }, + { + "const": "clip", + "type": "string" + }, + { + "const": "ellipsis", + "type": "string" + }, + { + "const": "clip-start", + "type": "string" + }, + { + "const": "clip-end", + "type": "string" + }, + { + "const": "ellipsis-start", + "type": "string" + }, + { + "const": "ellipsis-middle", + "type": "string" + }, + { + "const": "ellipsis-end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How truncate (or wrap) lines of text longer than the given **lineWidth**; one of:\n\n- null (default) - preserve overflowing characters (and wrap if needed)\n- *clip* or *clip-end* - remove characters from the end\n- *clip-start* - remove characters from the start\n- *ellipsis* or *ellipsis-end* - replace characters from the end with an ellipsis (…)\n- *ellipsis-start* - replace characters from the start with an ellipsis (…)\n- *ellipsis-middle* - replace characters from the middle with an ellipsis (…)\n\nIf no **title** was specified, if text requires truncation, a title containing the non-truncated text will be implicitly added." + }, + "textPadding": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The padding around the text in pixels; defaults to 8." + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + } + }, + "type": "object" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to generate a tooltip for this mark, and any tip options." + }, + "title": { + "$ref": "#/definitions/ChannelValue", + "description": "The title; a channel specifying accessible, short textual descriptions as strings (possibly with newlines). If the tip option is specified, the title will be displayed with an interactive tooltip instead of using the SVG [title element][1].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/title" + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel specifying the text’s anchor point, typically bound to the *x* scale." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel specifying the text’s anchor point, typically bound to the *y* scale." + }, + "z": { + "$ref": "#/definitions/ChannelValue", + "description": "An optional ordinal channel for grouping data into series." + } + }, + "required": [ + "mark" + ], + "type": "object" + }, + "AxisY": { + "additionalProperties": false, + "description": "The axisY mark.", + "properties": { + "anchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "right", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "const": "left", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The side of the frame on which to place the axis: *top* or *bottom* for horizontal axes (axisX and axisFx) and their associated vertical grids (gridX and gridFx), or *left* or *right* for vertical axes (axisY and axisFY) and their associated horizontal grids (gridY and gridFy).\n\nThe default **anchor** depends on the associated scale:\n\n- *x* - *bottom*\n- *y* - *left*\n- *fx* - *top* if there is a *bottom* *x* axis, and otherwise *bottom*\n- *fy* - *right* if there is a *left* *y* axis, and otherwise *right*\n\nFor grids, the **anchor** also affects the extent of grid lines when the opposite dimension is specified (**x** for gridY and **y** for gridX)." + }, + "ariaDescription": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-description][1]; a constant textual description.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-description" + }, + "ariaHidden": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-hidden][1] state; a constant indicating whether the element is exposed to an accessibility API.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-hidden" + }, + "ariaLabel": { + "$ref": "#/definitions/ChannelValue", + "description": "The [aria-label][1]; a channel specifying short textual labels representing the value in the accessibility tree.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-label" + }, + "clip": { + "anyOf": [ + { + "const": "frame", + "type": "string" + }, + { + "const": "sphere", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to clip the mark; one of:\n\n- *frame* or true - clip to the plot’s frame (inner area)\n- *sphere* - clip to the projected sphere (*e.g.*, front hemisphere)\n- null or false - do not clip\n\nThe *sphere* clip option requires a geographic projection." + }, + "color": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A shorthand for setting both **fill** and **stroke**; affects the stroke of tick vectors and grid rules, and the fill of tick texts and axis label texts; defaults to *currentColor*." + }, + "dx": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The horizontal offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "dy": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The vertical offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "facet": { + "anyOf": [ + { + "const": "auto", + "type": "string" + }, + { + "const": "include", + "type": "string" + }, + { + "const": "exclude", + "type": "string" + }, + { + "const": "super", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to enable or disable faceting; one of:\n\n- *auto* (default) - automatically determine if this mark should be faceted\n- *include* (or true) - draw the subset of the mark’s data in the current facet\n- *exclude* - draw the subset of the mark’s data *not* in the current facet\n- *super* - draw this mark in a single frame that covers all facets\n- null (or false) - repeat this mark’s data across all facets (*i.e.*, no faceting)\n\nWhen a mark uses *super* faceting, it is not allowed to use position scales (*x*, *y*, *fx*, or *fy*); *super* faceting is intended for decorations, such as labels and legends.\n\nWhen top-level faceting is used, the default *auto* setting is equivalent to *include* when the mark data is strictly equal to the top-level facet data; otherwise it is equivalent to null. When the *include* or *exclude* facet mode is chosen, the mark data must be parallel to the top-level facet data: the data must have the same length and order. If the data are not parallel, then the wrong data may be shown in each facet. The default\n*auto* therefore requires strict equality (`===`) for safety, and using the facet data as mark data is recommended when using the *exclude* facet mode. (To construct parallel data safely, consider using [*array*.map][1] on the facet data.)\n\nWhen mark-level faceting is used, the default *auto* setting is equivalent to *include*: the mark will be faceted if either the **fx** or **fy** channel option (or both) is specified. The null or false option will disable faceting, while *exclude* draws the subset of the mark’s data *not* in the current facet.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map" + }, + "facetAnchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "right", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "const": "left", + "type": "string" + }, + { + "const": "top-left", + "type": "string" + }, + { + "const": "top-right", + "type": "string" + }, + { + "const": "bottom-left", + "type": "string" + }, + { + "const": "bottom-right", + "type": "string" + }, + { + "const": "top-empty", + "type": "string" + }, + { + "const": "right-empty", + "type": "string" + }, + { + "const": "bottom-empty", + "type": "string" + }, + { + "const": "left-empty", + "type": "string" + }, + { + "const": "empty", + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to place the mark with respect to facets; one of:\n\n- null (default for most marks) - display the mark in each non-empty facet\n- *top*, *right*, *bottom*, or *left* - display the mark only in facets on the given side\n- *top-empty*, *right-empty*, *bottom-empty*, or *left-empty* (default for axis marks) - display the mark only in facets that have empty space on the given side: either the margin, or an empty facet\n- *empty* - display the mark in empty facets only" + }, + "fill": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill" + }, + "fillOpacity": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill-opacity][1]; a constant number between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill-opacity" + }, + "filter": { + "$ref": "#/definitions/ChannelValue", + "description": "Applies a transform to filter the mark’s index according to the given channel values; only truthy values are retained.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "fontFamily": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font-family][1]; a constant; defaults to the plot’s font family, which is typically [*system-ui*][2].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-family [2]: https://drafts.csswg.org/css-fonts-4/#valdef-font-family-system-ui" + }, + "fontSize": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font size][1] in pixels; either a constant or a channel; defaults to the plot’s font size, which is typically 10. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-size" + }, + "fontStyle": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font style][1]; a constant; defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-style" + }, + "fontVariant": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font variant][1]; a constant; if the **text** channel contains numbers or dates, defaults to *tabular-nums* to facilitate comparing numbers; otherwise defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant" + }, + "fontWeight": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font weight][1]; a constant; defaults to the plot’s font weight, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight" + }, + "frameAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The frame anchor specifies defaults for **x** and **y**, along with\n**textAnchor** and **lineAnchor**, based on the plot’s frame; it may be one of the four sides (*top*, *right*, *bottom*, *left*), one of the four corners (*top-left*, *top-right*, *bottom-right*, *bottom-left*), or the\n*middle* of the frame." + }, + "fx": { + "$ref": "#/definitions/ChannelValue", + "description": "The horizontal facet position channel, for mark-level faceting, bound to the *fx* scale." + }, + "fy": { + "$ref": "#/definitions/ChannelValue", + "description": "The vertical facet position channel, for mark-level faceting, bound to the\n*fy* scale." + }, + "href": { + "$ref": "#/definitions/ChannelValue", + "description": "The [href][1]; a channel specifying URLs for clickable links. May be used in conjunction with the **target** option to open links in another window.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/href" + }, + "imageFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A CSS [filter][1]; a constant string used to adjust the rendering of images, such as *blur(5px)*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/filter" + }, + "inset": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four insets: **insetTop**,\n**insetRight**, **insetBottom**, and **insetLeft**. All insets typically default to zero, though not always (say when using bin transform). A positive inset reduces effective area, while a negative inset increases it." + }, + "insetLeft": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Insets the left edge by the specified number of pixels. A positive value insets towards the right edge (reducing effective area), while a negative value insets away from the right edge (increasing it)." + }, + "insetRight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Insets the right edge by the specified number of pixels. A positive value insets towards the left edge (reducing effective area), while a negative value insets away from the left edge (increasing it)." + }, + "interval": { + "anyOf": [ + { + "$ref": "#/definitions/Interval" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Enforces uniformity for data at regular intervals, such as integer values or daily samples. The interval may be one of:\n\n- a named time interval such as *day* (for date intervals)\n- a number (for number intervals), defining intervals at integer multiples of *n*\n\nThis option sets the internal transform to the given interval’s\n*interval*.floor function. In addition, the default **domain** will align with interval boundaries." + }, + "label": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A textual label to show on the axis or legend; if null, show no label. By default the scale label is inferred from channel definitions, possibly with an arrow (↑, →, ↓, or ←) to indicate the direction of increasing value.\n\nFor axes and legends only." + }, + "labelAnchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "right", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "const": "left", + "type": "string" + }, + { + "const": "center", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Where to place the axis **label** relative to the plot’s frame. For vertical position scales (*y* and *fy*), may be *top*, *bottom*, or\n*center*; for horizontal position scales (*x* and *fx*), may be *left*,\n*right*, or *center*. Defaults to *center* for ordinal scales (including\n*fx* and *fy*), and otherwise *top* for *y*, and *right* for *x*." + }, + "labelArrow": { + "anyOf": [ + { + "const": "auto", + "type": "string" + }, + { + "const": "up", + "type": "string" + }, + { + "const": "right", + "type": "string" + }, + { + "const": "down", + "type": "string" + }, + { + "const": "left", + "type": "string" + }, + { + "const": "none", + "type": "string" + }, + { + "const": true, + "type": "boolean" + }, + { + "const": false, + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to apply a directional arrow such as → or ↑ to the scale label. If\n*auto* (the default), the presence of the arrow depends on whether the scale is ordinal." + }, + "labelOffset": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The axis **label** position offset (in pixels); default depends on margins and orientation." + }, + "lineAnchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "middle", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line anchor controls how text is aligned (typically vertically) relative to its anchor point; it is one of *top*, *bottom*, or *middle*. If the frame anchor is *top*, *top-left*, or *top-right*, the default line anchor is *top*; if the frame anchor is *bottom*, *bottom-right*, or\n*bottom-left*, the default is *bottom*; otherwise it is *middle*." + }, + "lineHeight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line height in ems; defaults to 1. The line height affects the (typically vertical) separation between adjacent baselines of text, as well as the separation between the text and its anchor point." + }, + "lineWidth": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line width in ems (e.g., 10 for about 20 characters); defaults to infinity, disabling wrapping and clipping.\n\nIf **textOverflow** is null, lines will be wrapped at the specified length. If a line is split at a soft hyphen (\\xad), a hyphen (-) will be displayed at the end of the line. If **textOverflow** is not null, lines will be clipped according to the given strategy." + }, + "margin": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four mark margins: **marginTop**,\n**marginRight**, **marginBottom**, and **marginLeft**; typically defaults to 0, except for axis marks." + }, + "marginBottom": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s bottom margin; the minimum distance in pixels between the bottom edges of the inner and outer plot area." + }, + "marginLeft": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s left margin; the minimum distance in pixels between the left edges of the inner and outer plot area." + }, + "marginRight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s right margin; the minimum distance in pixels between the right edges of the mark’s inner and outer plot area." + }, + "marginTop": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s top margin; the minimum distance in pixels between the top edges of the inner and outer plot area." + }, + "mark": { + "const": "axisY", + "description": "An axis mark to document the visual encoding of the vertical position *y* scale, comprised of (up to) three marks: a vector for ticks, a text for tick labels, and another text for an axis label. The data defaults to tick values sampled from the *y* scale’s domain; if desired, use one of the\n**ticks**, **tickSpacing**, or **interval** options.\n\nThe **facetAnchor** option defaults to *right-empty* if **anchor** is\n*right*, and *left-empty* if **anchor** is *left*. The default margins likewise depend on **anchor** as follows; in order of **marginTop**,\n**marginRight**, **marginBottom**, and **marginLeft**, in pixels:\n\n- *right* - 20, 40, 20, 0\n- *left* - 20, 0, 20, 40\n\nFor simplicity, and for consistent layout across plots, default axis margins are not affected by tick labels. If tick labels are too long, either increase the margin or shorten the labels: use the *k* SI-prefix tick format; or use the **textOverflow** and **lineWidth** options to clip.", + "type": "string" + }, + "marker": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for markerStart, markerMid, and markerEnd; one of:\n\n- a marker name such as *arrow* or *circle*\n- *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*" + }, + "markerEnd": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The marker for the ending point of a line segment; one of:\n\n- a marker name such as *arrow* or *circle*\n* *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*" + }, + "markerMid": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The marker for any middle (interior) points of a line segment. If the line segment only has a start and end point, this option has no effect. One of:\n\n- a marker name such as *arrow* or *circle*\n* *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*\n* a function - a custom marker function; see below" + }, + "markerStart": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The marker for the starting point of a line segment; one of:\n\n- a marker name such as *arrow* or *circle*\n* *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*" + }, + "mixBlendMode": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [mix-blend-mode][1]; a constant string specifying how to blend content such as *multiply*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode" + }, + "monospace": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, changes the default **fontFamily** to *monospace*, and uses simplified monospaced text metrics calculations." + }, + "opacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "A shorthand for setting both **fillOpacity** and **strokeOpacity**; affects the stroke opacity of tick vectors and grid rules, and the fill opacity of tick texts and axis label texts; defaults to 1 for axes and 0.1 for grids." + }, + "paintOrder": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [paint-order][1]; a constant string specifying the order in which the\n**fill**, **stroke**, and any markers are drawn; defaults to *normal*, which draws the fill, then stroke, then markers; defaults to *stroke* for the text mark to create a “halo” around text to improve legibility.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/paint-order" + }, + "pointerEvents": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [pointer-events][1] property; a constant string such as *none*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/pointer-events" + }, + "reverse": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Applies a transform to reverse the order of the mark’s index, say for reverse input order." + }, + "rotate": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The rotation angle in degrees clockwise; a constant or a channel; defaults to 0°. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel." + }, + "select": { + "$ref": "#/definitions/SelectFilter", + "description": "Applies a filter transform after data is loaded to highlight selected values only. For example, `first` and `last` select the first or last values of series only (using the *z* channel to separate series). Meanwhile, `nearestX` and `nearestY` select the point nearest to the pointer along the *x* or *y* channel dimension. Unlike Mosaic selections, a mark level *select* is internal to the mark only, and does not populate a param or selection value to be shared across clients.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "shapeRendering": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [shape-rendering][1]; a constant string such as *crispEdges*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/shape-rendering" + }, + "sort": { + "anyOf": [ + { + "$ref": "#/definitions/SortOrder" + }, + { + "$ref": "#/definitions/ChannelDomainSort" + } + ], + "description": "Either applies a transform to sort the mark’s index by the specified channel values, or imputes ordinal scale domains from this mark’s channels.\n\nWhen imputing ordinal scale domains from channel values, the **sort** option is an object whose keys are ordinal scale names such as *x* or *fx*, and whose values are channel names such as *y*, *y1*, or *y2*. For example, to impute the *y* scale’s domain from the associated *x* channel values in ascending order:\n\n```js sort: {y: \"x\"} ```\n\nFor different sort options for different scales, replace the channel name with a *value* object and per-scale options:\n\n```js sort: {y: {value: \"-x\"}} ```\n\nWhen sorting the mark’s index, the **sort** option is instead one of:\n\n- a channel value definition for sorting given values in ascending order\n- a {value, order} object for sorting given values\n- a {channel, order} object for sorting the named channel’s values" + }, + "stroke": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke" + }, + "strokeDasharray": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dasharray][1]; a constant number indicating the length in pixels of alternating dashes and gaps, or a constant string of numbers separated by spaces or commas (_e.g._, *10 2* for dashes of 10 pixels separated by gaps of 2 pixels), or *none* (the default) for no dashing\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dasharray" + }, + "strokeDashoffset": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dashoffset][1]; a constant indicating the offset in pixels of the first dash along the stroke; defaults to zero.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dashoffset" + }, + "strokeLinecap": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linecap][1]; a constant specifying how to cap stroked paths, such as *butt*, *round*, or *square*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linecap" + }, + "strokeLinejoin": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linejoin][1]; a constant specifying how to join stroked paths, such as *bevel*, *miter*, *miter-clip*, or *round*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linejoin" + }, + "strokeMiterlimit": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-miterlimit][1]; a constant number specifying how to limit the length of *miter* joins on stroked paths.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-miterlimit" + }, + "strokeOpacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-opacity" + }, + "strokeWidth": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-width][1]; a constant number in pixels, or a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-width" + }, + "target": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [target][1]; a constant string specifying the target window (_e.g._,\n*_blank*) for clickable links; used in conjunction with the **href** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/target" + }, + "text": { + "$ref": "#/definitions/ChannelValue", + "description": "The text contents channel, possibly with line breaks (\\n, \\r\\n, or \\r). If not specified, defaults to the zero-based index [0, 1, 2, …]." + }, + "textAnchor": { + "anyOf": [ + { + "const": "start", + "type": "string" + }, + { + "const": "middle", + "type": "string" + }, + { + "const": "end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [text anchor][1] controls how text is aligned (typically horizontally) relative to its anchor point; it is one of *start*, *end*, or *middle*. If the frame anchor is *left*, *top-left*, or *bottom-left*, the default text anchor is *start*; if the frame anchor is *right*, *top-right*, or\n*bottom-right*, the default is *end*; otherwise it is *middle*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/text-anchor" + }, + "textOverflow": { + "anyOf": [ + { + "type": "null" + }, + { + "const": "clip", + "type": "string" + }, + { + "const": "ellipsis", + "type": "string" + }, + { + "const": "clip-start", + "type": "string" + }, + { + "const": "clip-end", + "type": "string" + }, + { + "const": "ellipsis-start", + "type": "string" + }, + { + "const": "ellipsis-middle", + "type": "string" + }, + { + "const": "ellipsis-end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How truncate (or wrap) lines of text longer than the given **lineWidth**; one of:\n\n- null (default) - preserve overflowing characters (and wrap if needed)\n- *clip* or *clip-end* - remove characters from the end\n- *clip-start* - remove characters from the start\n- *ellipsis* or *ellipsis-end* - replace characters from the end with an ellipsis (…)\n- *ellipsis-start* - replace characters from the start with an ellipsis (…)\n- *ellipsis-middle* - replace characters from the middle with an ellipsis (…)\n\nIf no **title** was specified, if text requires truncation, a title containing the non-truncated text will be implicitly added." + }, + "textStroke": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The tick text **stroke**, say for a *white* outline to improve legibility; defaults to null." + }, + "textStrokeOpacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The tick text **strokeOpacity**; defaults to 1; has no effect unless **textStroke** is set." + }, + "textStrokeWidth": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The tick text **strokeWidth**; defaults to 4; has no effect unless **textStroke** is set." + }, + "tickFormat": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to format inputs (abstract values) for axis tick labels; one of:\n\n- a [d3-format][1] string for numeric scales\n- a [d3-time-format][2] string for temporal scales\n\n[1]: https://d3js.org/d3-time [2]: https://d3js.org/d3-time-format" + }, + "tickPadding": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The distance between an axis tick mark and its associated text label (in pixels); often defaults to 3, but may be affected by **xTickSize** and\n**xTickRotate**." + }, + "tickRotate": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The rotation angle of axis tick labels in degrees clocksize; defaults to 0." + }, + "tickSize": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The length of axis tick marks in pixels; negative values extend in the opposite direction. Defaults to 6 for *x* and *y* axes and *color* and\n*opacity* *ramp* legends, and 0 for *fx* and *fy* axes." + }, + "tickSpacing": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The desired approximate spacing between adjacent axis ticks, affecting the default **ticks**; defaults to 80 pixels for *x* and *fx*, and 35 pixels for *y* and *fy*." + }, + "ticks": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/Interval" + }, + { + "items": {}, + "type": "array" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The desired approximate number of axis ticks, or an explicit array of tick values, or an interval such as *day* or *month*." + }, + "tip": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/TipPointer" + }, + { + "properties": { + "anchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The tip anchor specifies how to orient the tip box relative to its anchor position; it refers to the part of the tip box that is attached to the anchor point. For example, the *top-left* anchor places the top-left corner of tip box near the anchor position, hence placing the tip box below and to the right of the anchor position." + }, + "fontFamily": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font-family][1]; a constant; defaults to the plot’s font family, which is typically [*system-ui*][2].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-family [2]: https://drafts.csswg.org/css-fonts-4/#valdef-font-family-system-ui" + }, + "fontSize": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font size][1] in pixels; either a constant or a channel; defaults to the plot’s font size, which is typically 10. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-size" + }, + "fontStyle": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font style][1]; a constant; defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-style" + }, + "fontVariant": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font variant][1]; a constant; if the **text** channel contains numbers or dates, defaults to *tabular-nums* to facilitate comparing numbers; otherwise defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant" + }, + "fontWeight": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font weight][1]; a constant; defaults to the plot’s font weight, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight" + }, + "format": { + "additionalProperties": false, + "description": "How channel values are formatted for display. If a format is a string, it is interpreted as a (UTC) time format for temporal channels, and otherwise a number format.", + "properties": { + "ariaLabel": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fill": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fillOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fontSize": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fx": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fy": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "geometry": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "height": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "href": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "length": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "opacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "path": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "r": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "rotate": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "src": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "stroke": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeWidth": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "symbol": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "text": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "title": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "weight": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "width": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "z": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + } + }, + "type": "object" + }, + "frameAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The frame anchor specifies defaults for **x** and **y** based on the plot’s frame; it may be one of the four sides (*top*, *right*, *bottom*, *left*), one of the four corners (*top-left*, *top-right*, *bottom-right*,\n*bottom-left*), or the *middle* of the frame. For example, for tips distributed horizontally at the top of the frame:\n\n```js Plot.tip(data, {x: \"date\", frameAnchor: \"top\"}) ```" + }, + "lineHeight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line height in ems; defaults to 1. The line height affects the (typically vertical) separation between adjacent baselines of text, as well as the separation between the text and its anchor point." + }, + "lineWidth": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line width in ems (e.g., 10 for about 20 characters); defaults to infinity, disabling wrapping and clipping.\n\nIf **textOverflow** is null, lines will be wrapped at the specified length. If a line is split at a soft hyphen (\\xad), a hyphen (-) will be displayed at the end of the line. If **textOverflow** is not null, lines will be clipped according to the given strategy." + }, + "monospace": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, changes the default **fontFamily** to *monospace*, and uses simplified monospaced text metrics calculations." + }, + "pathFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The image filter for the tip’s box; defaults to a drop shadow." + }, + "pointer": { + "$ref": "#/definitions/TipPointer" + }, + "pointerSize": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The size of the tip’s pointer in pixels; defaults to 12." + }, + "preferredAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If an explicit tip anchor is not specified, an anchor is chosen automatically such that the tip fits within the plot’s frame; if the preferred anchor fits, it is chosen." + }, + "textAnchor": { + "anyOf": [ + { + "const": "start", + "type": "string" + }, + { + "const": "middle", + "type": "string" + }, + { + "const": "end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [text anchor][1] controls how text is aligned (typically horizontally) relative to its anchor point; it is one of *start*, *end*, or *middle*. If the frame anchor is *left*, *top-left*, or *bottom-left*, the default text anchor is *start*; if the frame anchor is *right*, *top-right*, or\n*bottom-right*, the default is *end*; otherwise it is *middle*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/text-anchor" + }, + "textOverflow": { + "anyOf": [ + { + "type": "null" + }, + { + "const": "clip", + "type": "string" + }, + { + "const": "ellipsis", + "type": "string" + }, + { + "const": "clip-start", + "type": "string" + }, + { + "const": "clip-end", + "type": "string" + }, + { + "const": "ellipsis-start", + "type": "string" + }, + { + "const": "ellipsis-middle", + "type": "string" + }, + { + "const": "ellipsis-end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How truncate (or wrap) lines of text longer than the given **lineWidth**; one of:\n\n- null (default) - preserve overflowing characters (and wrap if needed)\n- *clip* or *clip-end* - remove characters from the end\n- *clip-start* - remove characters from the start\n- *ellipsis* or *ellipsis-end* - replace characters from the end with an ellipsis (…)\n- *ellipsis-start* - replace characters from the start with an ellipsis (…)\n- *ellipsis-middle* - replace characters from the middle with an ellipsis (…)\n\nIf no **title** was specified, if text requires truncation, a title containing the non-truncated text will be implicitly added." + }, + "textPadding": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The padding around the text in pixels; defaults to 8." + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + } + }, + "type": "object" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to generate a tooltip for this mark, and any tip options." + }, + "title": { + "$ref": "#/definitions/ChannelValue", + "description": "The title; a channel specifying accessible, short textual descriptions as strings (possibly with newlines). If the tip option is specified, the title will be displayed with an interactive tooltip instead of using the SVG [title element][1].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/title" + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel specifying the text’s anchor point, typically bound to the *x* scale." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel specifying the text’s anchor point, typically bound to the *y* scale." + }, + "z": { + "$ref": "#/definitions/ChannelValue", + "description": "An optional ordinal channel for grouping data into series." + } + }, + "required": [ + "mark" + ], + "type": "object" + }, + "BarX": { + "additionalProperties": false, + "description": "The barX mark.", + "properties": { + "ariaDescription": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-description][1]; a constant textual description.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-description" + }, + "ariaHidden": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-hidden][1] state; a constant indicating whether the element is exposed to an accessibility API.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-hidden" + }, + "ariaLabel": { + "$ref": "#/definitions/ChannelValue", + "description": "The [aria-label][1]; a channel specifying short textual labels representing the value in the accessibility tree.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-label" + }, + "clip": { + "anyOf": [ + { + "const": "frame", + "type": "string" + }, + { + "const": "sphere", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to clip the mark; one of:\n\n- *frame* or true - clip to the plot’s frame (inner area)\n- *sphere* - clip to the projected sphere (*e.g.*, front hemisphere)\n- null or false - do not clip\n\nThe *sphere* clip option requires a geographic projection." + }, + "data": { + "$ref": "#/definitions/PlotMarkData", + "description": "The data source for the mark." + }, + "dx": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The horizontal offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "dy": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The vertical offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "facet": { + "anyOf": [ + { + "const": "auto", + "type": "string" + }, + { + "const": "include", + "type": "string" + }, + { + "const": "exclude", + "type": "string" + }, + { + "const": "super", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to enable or disable faceting; one of:\n\n- *auto* (default) - automatically determine if this mark should be faceted\n- *include* (or true) - draw the subset of the mark’s data in the current facet\n- *exclude* - draw the subset of the mark’s data *not* in the current facet\n- *super* - draw this mark in a single frame that covers all facets\n- null (or false) - repeat this mark’s data across all facets (*i.e.*, no faceting)\n\nWhen a mark uses *super* faceting, it is not allowed to use position scales (*x*, *y*, *fx*, or *fy*); *super* faceting is intended for decorations, such as labels and legends.\n\nWhen top-level faceting is used, the default *auto* setting is equivalent to *include* when the mark data is strictly equal to the top-level facet data; otherwise it is equivalent to null. When the *include* or *exclude* facet mode is chosen, the mark data must be parallel to the top-level facet data: the data must have the same length and order. If the data are not parallel, then the wrong data may be shown in each facet. The default\n*auto* therefore requires strict equality (`===`) for safety, and using the facet data as mark data is recommended when using the *exclude* facet mode. (To construct parallel data safely, consider using [*array*.map][1] on the facet data.)\n\nWhen mark-level faceting is used, the default *auto* setting is equivalent to *include*: the mark will be faceted if either the **fx** or **fy** channel option (or both) is specified. The null or false option will disable faceting, while *exclude* draws the subset of the mark’s data *not* in the current facet.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map" + }, + "facetAnchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "right", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "const": "left", + "type": "string" + }, + { + "const": "top-left", + "type": "string" + }, + { + "const": "top-right", + "type": "string" + }, + { + "const": "bottom-left", + "type": "string" + }, + { + "const": "bottom-right", + "type": "string" + }, + { + "const": "top-empty", + "type": "string" + }, + { + "const": "right-empty", + "type": "string" + }, + { + "const": "bottom-empty", + "type": "string" + }, + { + "const": "left-empty", + "type": "string" + }, + { + "const": "empty", + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to place the mark with respect to facets; one of:\n\n- null (default for most marks) - display the mark in each non-empty facet\n- *top*, *right*, *bottom*, or *left* - display the mark only in facets on the given side\n- *top-empty*, *right-empty*, *bottom-empty*, or *left-empty* (default for axis marks) - display the mark only in facets that have empty space on the given side: either the margin, or an empty facet\n- *empty* - display the mark in empty facets only" + }, + "fill": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill" + }, + "fillOpacity": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill-opacity][1]; a constant number between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill-opacity" + }, + "filter": { + "$ref": "#/definitions/ChannelValue", + "description": "Applies a transform to filter the mark’s index according to the given channel values; only truthy values are retained.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "fx": { + "$ref": "#/definitions/ChannelValue", + "description": "The horizontal facet position channel, for mark-level faceting, bound to the *fx* scale." + }, + "fy": { + "$ref": "#/definitions/ChannelValue", + "description": "The vertical facet position channel, for mark-level faceting, bound to the\n*fy* scale." + }, + "href": { + "$ref": "#/definitions/ChannelValue", + "description": "The [href][1]; a channel specifying URLs for clickable links. May be used in conjunction with the **target** option to open links in another window.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/href" + }, + "imageFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A CSS [filter][1]; a constant string used to adjust the rendering of images, such as *blur(5px)*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/filter" + }, + "inset": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four insets: **insetTop**,\n**insetRight**, **insetBottom**, and **insetLeft**. All insets typically default to zero, though not always (say when using bin transform). A positive inset reduces effective area, while a negative inset increases it." + }, + "insetBottom": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Insets the bottom edge by the specified number of pixels. A positive value insets towards the top edge (reducing effective area), while a negative value insets away from the top edge (increasing it)." + }, + "insetLeft": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Insets the left edge by the specified number of pixels. A positive value insets towards the right edge (reducing effective area), while a negative value insets away from the right edge (increasing it)." + }, + "insetRight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Insets the right edge by the specified number of pixels. A positive value insets towards the left edge (reducing effective area), while a negative value insets away from the left edge (increasing it)." + }, + "insetTop": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Insets the top edge by the specified number of pixels. A positive value insets towards the bottom edge (reducing effective area), while a negative value insets away from the bottom edge (increasing it)." + }, + "interval": { + "anyOf": [ + { + "$ref": "#/definitions/Interval" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to convert a continuous value (**x** for barX, or **y** for barY) into an interval (**x1** and **x2** for barX, or **y1** and **y2** for barY); one of:\n\n- a named time interval such as *day* (for date intervals)\n- a number (for number intervals), defining intervals at integer multiples of *n*\n\nSetting this option disables the implicit stack transform (stackX for barX, or stackY for barY)." + }, + "margin": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four mark margins: **marginTop**,\n**marginRight**, **marginBottom**, and **marginLeft**; typically defaults to 0, except for axis marks." + }, + "marginBottom": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s bottom margin; the minimum distance in pixels between the bottom edges of the inner and outer plot area." + }, + "marginLeft": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s left margin; the minimum distance in pixels between the left edges of the inner and outer plot area." + }, + "marginRight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s right margin; the minimum distance in pixels between the right edges of the mark’s inner and outer plot area." + }, + "marginTop": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s top margin; the minimum distance in pixels between the top edges of the inner and outer plot area." + }, + "mark": { + "const": "barX", + "description": "A horizontal bar mark. The required *x* values should be quantitative or temporal, and the optional *y* values should be ordinal.\n\nIf neither **x1** nor **x2** nor **interval** is specified, an implicit stackX transform is applied and **x** defaults to the identity function, assuming that *data* = [*x₀*, *x₁*, *x₂*, …]. Otherwise if an **interval** is specified, then **x1** and **x2** are derived from **x**, representing the lower and upper bound of the containing interval, respectively. Otherwise, if only one of **x1** or **x2** is specified, the other defaults to **x**, which defaults to zero.\n\nThe optional **y** ordinal channel specifies the vertical position; it is typically bound to the *y* scale, which must be a *band* scale. If the\n**y** channel is not specified, the bar will span the vertical extent of the plot’s frame.\n\nIf *y* is quantitative, use the rectX mark instead. If *x* is ordinal, use the cell mark instead.", + "type": "string" + }, + "mixBlendMode": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [mix-blend-mode][1]; a constant string specifying how to blend content such as *multiply*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode" + }, + "offset": { + "anyOf": [ + { + "$ref": "#/definitions/StackOffset" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "After stacking, an optional **offset** can be applied to translate and scale stacks, say to produce a streamgraph; defaults to null for a zero baseline (**y** = 0 for stackY, and **x** = 0 for stackX). If the *wiggle* offset is used, the default **order** changes to *inside-out*." + }, + "opacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally. For faster rendering, prefer the **strokeOpacity** or **fillOpacity** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/opacity" + }, + "order": { + "anyOf": [ + { + "$ref": "#/definitions/StackOrder" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The order in which stacks are layered; one of:\n\n- null (default) for input order\n- a named stack order method such as *inside-out* or *sum*\n- a field name, for natural order of the corresponding values\n- a function of data, for natural order of the corresponding values\n- an array of explicit **z** values in the desired order\n\nIf the *wiggle* **offset** is used, as for a streamgraph, the default changes to *inside-out*." + }, + "paintOrder": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [paint-order][1]; a constant string specifying the order in which the\n**fill**, **stroke**, and any markers are drawn; defaults to *normal*, which draws the fill, then stroke, then markers; defaults to *stroke* for the text mark to create a “halo” around text to improve legibility.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/paint-order" + }, + "pointerEvents": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [pointer-events][1] property; a constant string such as *none*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/pointer-events" + }, + "reverse": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Applies a transform to reverse the order of the mark’s index, say for reverse input order." + }, + "rx": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The rounded corner [*x*-radius][1], either in pixels or as a percentage of the rect width. If **rx** is not specified, it defaults to **ry** if present, and otherwise draws square corners.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/rx" + }, + "ry": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The rounded corner [*y*-radius][1], either in pixels or as a percentage of the rect height. If **ry** is not specified, it defaults to **rx** if present, and otherwise draws square corners.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/ry" + }, + "select": { + "$ref": "#/definitions/SelectFilter", + "description": "Applies a filter transform after data is loaded to highlight selected values only. For example, `first` and `last` select the first or last values of series only (using the *z* channel to separate series). Meanwhile, `nearestX` and `nearestY` select the point nearest to the pointer along the *x* or *y* channel dimension. Unlike Mosaic selections, a mark level *select* is internal to the mark only, and does not populate a param or selection value to be shared across clients.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "shapeRendering": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [shape-rendering][1]; a constant string such as *crispEdges*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/shape-rendering" + }, + "sort": { + "anyOf": [ + { + "$ref": "#/definitions/SortOrder" + }, + { + "$ref": "#/definitions/ChannelDomainSort" + } + ], + "description": "Either applies a transform to sort the mark’s index by the specified channel values, or imputes ordinal scale domains from this mark’s channels.\n\nWhen imputing ordinal scale domains from channel values, the **sort** option is an object whose keys are ordinal scale names such as *x* or *fx*, and whose values are channel names such as *y*, *y1*, or *y2*. For example, to impute the *y* scale’s domain from the associated *x* channel values in ascending order:\n\n```js sort: {y: \"x\"} ```\n\nFor different sort options for different scales, replace the channel name with a *value* object and per-scale options:\n\n```js sort: {y: {value: \"-x\"}} ```\n\nWhen sorting the mark’s index, the **sort** option is instead one of:\n\n- a channel value definition for sorting given values in ascending order\n- a {value, order} object for sorting given values\n- a {channel, order} object for sorting the named channel’s values" + }, + "stroke": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke" + }, + "strokeDasharray": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dasharray][1]; a constant number indicating the length in pixels of alternating dashes and gaps, or a constant string of numbers separated by spaces or commas (_e.g._, *10 2* for dashes of 10 pixels separated by gaps of 2 pixels), or *none* (the default) for no dashing\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dasharray" + }, + "strokeDashoffset": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dashoffset][1]; a constant indicating the offset in pixels of the first dash along the stroke; defaults to zero.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dashoffset" + }, + "strokeLinecap": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linecap][1]; a constant specifying how to cap stroked paths, such as *butt*, *round*, or *square*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linecap" + }, + "strokeLinejoin": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linejoin][1]; a constant specifying how to join stroked paths, such as *bevel*, *miter*, *miter-clip*, or *round*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linejoin" + }, + "strokeMiterlimit": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-miterlimit][1]; a constant number specifying how to limit the length of *miter* joins on stroked paths.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-miterlimit" + }, + "strokeOpacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-opacity" + }, + "strokeWidth": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-width][1]; a constant number in pixels, or a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-width" + }, + "target": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [target][1]; a constant string specifying the target window (_e.g._,\n*_blank*) for clickable links; used in conjunction with the **href** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/target" + }, + "tip": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/TipPointer" + }, + { + "properties": { + "anchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The tip anchor specifies how to orient the tip box relative to its anchor position; it refers to the part of the tip box that is attached to the anchor point. For example, the *top-left* anchor places the top-left corner of tip box near the anchor position, hence placing the tip box below and to the right of the anchor position." + }, + "fontFamily": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font-family][1]; a constant; defaults to the plot’s font family, which is typically [*system-ui*][2].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-family [2]: https://drafts.csswg.org/css-fonts-4/#valdef-font-family-system-ui" + }, + "fontSize": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font size][1] in pixels; either a constant or a channel; defaults to the plot’s font size, which is typically 10. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-size" + }, + "fontStyle": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font style][1]; a constant; defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-style" + }, + "fontVariant": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font variant][1]; a constant; if the **text** channel contains numbers or dates, defaults to *tabular-nums* to facilitate comparing numbers; otherwise defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant" + }, + "fontWeight": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font weight][1]; a constant; defaults to the plot’s font weight, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight" + }, + "format": { + "additionalProperties": false, + "description": "How channel values are formatted for display. If a format is a string, it is interpreted as a (UTC) time format for temporal channels, and otherwise a number format.", + "properties": { + "ariaLabel": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fill": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fillOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fontSize": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fx": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fy": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "geometry": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "height": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "href": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "length": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "opacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "path": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "r": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "rotate": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "src": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "stroke": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeWidth": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "symbol": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "text": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "title": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "weight": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "width": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "z": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + } + }, + "type": "object" + }, + "frameAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The frame anchor specifies defaults for **x** and **y** based on the plot’s frame; it may be one of the four sides (*top*, *right*, *bottom*, *left*), one of the four corners (*top-left*, *top-right*, *bottom-right*,\n*bottom-left*), or the *middle* of the frame. For example, for tips distributed horizontally at the top of the frame:\n\n```js Plot.tip(data, {x: \"date\", frameAnchor: \"top\"}) ```" + }, + "lineHeight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line height in ems; defaults to 1. The line height affects the (typically vertical) separation between adjacent baselines of text, as well as the separation between the text and its anchor point." + }, + "lineWidth": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line width in ems (e.g., 10 for about 20 characters); defaults to infinity, disabling wrapping and clipping.\n\nIf **textOverflow** is null, lines will be wrapped at the specified length. If a line is split at a soft hyphen (\\xad), a hyphen (-) will be displayed at the end of the line. If **textOverflow** is not null, lines will be clipped according to the given strategy." + }, + "monospace": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, changes the default **fontFamily** to *monospace*, and uses simplified monospaced text metrics calculations." + }, + "pathFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The image filter for the tip’s box; defaults to a drop shadow." + }, + "pointer": { + "$ref": "#/definitions/TipPointer" + }, + "pointerSize": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The size of the tip’s pointer in pixels; defaults to 12." + }, + "preferredAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If an explicit tip anchor is not specified, an anchor is chosen automatically such that the tip fits within the plot’s frame; if the preferred anchor fits, it is chosen." + }, + "textAnchor": { + "anyOf": [ + { + "const": "start", + "type": "string" + }, + { + "const": "middle", + "type": "string" + }, + { + "const": "end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [text anchor][1] controls how text is aligned (typically horizontally) relative to its anchor point; it is one of *start*, *end*, or *middle*. If the frame anchor is *left*, *top-left*, or *bottom-left*, the default text anchor is *start*; if the frame anchor is *right*, *top-right*, or\n*bottom-right*, the default is *end*; otherwise it is *middle*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/text-anchor" + }, + "textOverflow": { + "anyOf": [ + { + "type": "null" + }, + { + "const": "clip", + "type": "string" + }, + { + "const": "ellipsis", + "type": "string" + }, + { + "const": "clip-start", + "type": "string" + }, + { + "const": "clip-end", + "type": "string" + }, + { + "const": "ellipsis-start", + "type": "string" + }, + { + "const": "ellipsis-middle", + "type": "string" + }, + { + "const": "ellipsis-end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How truncate (or wrap) lines of text longer than the given **lineWidth**; one of:\n\n- null (default) - preserve overflowing characters (and wrap if needed)\n- *clip* or *clip-end* - remove characters from the end\n- *clip-start* - remove characters from the start\n- *ellipsis* or *ellipsis-end* - replace characters from the end with an ellipsis (…)\n- *ellipsis-start* - replace characters from the start with an ellipsis (…)\n- *ellipsis-middle* - replace characters from the middle with an ellipsis (…)\n\nIf no **title** was specified, if text requires truncation, a title containing the non-truncated text will be implicitly added." + }, + "textPadding": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The padding around the text in pixels; defaults to 8." + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + } + }, + "type": "object" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to generate a tooltip for this mark, and any tip options." + }, + "title": { + "$ref": "#/definitions/ChannelValue", + "description": "The title; a channel specifying accessible, short textual descriptions as strings (possibly with newlines). If the tip option is specified, the title will be displayed with an interactive tooltip instead of using the SVG [title element][1].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/title" + }, + "x": { + "$ref": "#/definitions/ChannelValueIntervalSpec", + "description": "The horizontal position (or length/width) channel, typically bound to the\n*x* scale.\n\nIf neither **x1** nor **x2** nor **interval** is specified, an implicit stackX transform is applied and **x** defaults to the identity function, assuming that *data* = [*x₀*, *x₁*, *x₂*, …]. Otherwise if an **interval** is specified, then **x1** and **x2** are derived from **x**, representing the lower and upper bound of the containing interval, respectively. Otherwise, if only one of **x1** or **x2** is specified, the other defaults to **x**, which defaults to zero." + }, + "x1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The required primary (starting, often left) horizontal position channel, typically bound to the *x* scale. Setting this option disables the implicit stackX transform.\n\nIf *x* represents ordinal values, use a cell mark instead." + }, + "x2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The required secondary (ending, often right) horizontal position channel, typically bound to the *x* scale. Setting this option disables the implicit stackX transform.\n\nIf *x* represents ordinal values, use a cell mark instead." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The optional vertical position of the bar; a ordinal channel typically bound to the *y* scale. If not specified, the bar spans the vertical extent of the frame; otherwise the *y* scale must be a *band* scale.\n\nIf *y* represents quantitative or temporal values, use a rectX mark instead." + }, + "z": { + "$ref": "#/definitions/ChannelValue", + "description": "The **z** channel defines the series of each value in the stack. Used when the **order** is *sum*, *appearance*, *inside-out*, or an explicit array of\n**z** values." + } + }, + "required": [ + "data", + "mark" + ], + "type": "object" + }, + "BarY": { + "additionalProperties": false, + "description": "The barY mark.", + "properties": { + "ariaDescription": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-description][1]; a constant textual description.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-description" + }, + "ariaHidden": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-hidden][1] state; a constant indicating whether the element is exposed to an accessibility API.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-hidden" + }, + "ariaLabel": { + "$ref": "#/definitions/ChannelValue", + "description": "The [aria-label][1]; a channel specifying short textual labels representing the value in the accessibility tree.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-label" + }, + "clip": { + "anyOf": [ + { + "const": "frame", + "type": "string" + }, + { + "const": "sphere", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to clip the mark; one of:\n\n- *frame* or true - clip to the plot’s frame (inner area)\n- *sphere* - clip to the projected sphere (*e.g.*, front hemisphere)\n- null or false - do not clip\n\nThe *sphere* clip option requires a geographic projection." + }, + "data": { + "$ref": "#/definitions/PlotMarkData", + "description": "The data source for the mark." + }, + "dx": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The horizontal offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "dy": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The vertical offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "facet": { + "anyOf": [ + { + "const": "auto", + "type": "string" + }, + { + "const": "include", + "type": "string" + }, + { + "const": "exclude", + "type": "string" + }, + { + "const": "super", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to enable or disable faceting; one of:\n\n- *auto* (default) - automatically determine if this mark should be faceted\n- *include* (or true) - draw the subset of the mark’s data in the current facet\n- *exclude* - draw the subset of the mark’s data *not* in the current facet\n- *super* - draw this mark in a single frame that covers all facets\n- null (or false) - repeat this mark’s data across all facets (*i.e.*, no faceting)\n\nWhen a mark uses *super* faceting, it is not allowed to use position scales (*x*, *y*, *fx*, or *fy*); *super* faceting is intended for decorations, such as labels and legends.\n\nWhen top-level faceting is used, the default *auto* setting is equivalent to *include* when the mark data is strictly equal to the top-level facet data; otherwise it is equivalent to null. When the *include* or *exclude* facet mode is chosen, the mark data must be parallel to the top-level facet data: the data must have the same length and order. If the data are not parallel, then the wrong data may be shown in each facet. The default\n*auto* therefore requires strict equality (`===`) for safety, and using the facet data as mark data is recommended when using the *exclude* facet mode. (To construct parallel data safely, consider using [*array*.map][1] on the facet data.)\n\nWhen mark-level faceting is used, the default *auto* setting is equivalent to *include*: the mark will be faceted if either the **fx** or **fy** channel option (or both) is specified. The null or false option will disable faceting, while *exclude* draws the subset of the mark’s data *not* in the current facet.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map" + }, + "facetAnchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "right", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "const": "left", + "type": "string" + }, + { + "const": "top-left", + "type": "string" + }, + { + "const": "top-right", + "type": "string" + }, + { + "const": "bottom-left", + "type": "string" + }, + { + "const": "bottom-right", + "type": "string" + }, + { + "const": "top-empty", + "type": "string" + }, + { + "const": "right-empty", + "type": "string" + }, + { + "const": "bottom-empty", + "type": "string" + }, + { + "const": "left-empty", + "type": "string" + }, + { + "const": "empty", + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to place the mark with respect to facets; one of:\n\n- null (default for most marks) - display the mark in each non-empty facet\n- *top*, *right*, *bottom*, or *left* - display the mark only in facets on the given side\n- *top-empty*, *right-empty*, *bottom-empty*, or *left-empty* (default for axis marks) - display the mark only in facets that have empty space on the given side: either the margin, or an empty facet\n- *empty* - display the mark in empty facets only" + }, + "fill": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill" + }, + "fillOpacity": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill-opacity][1]; a constant number between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill-opacity" + }, + "filter": { + "$ref": "#/definitions/ChannelValue", + "description": "Applies a transform to filter the mark’s index according to the given channel values; only truthy values are retained.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "fx": { + "$ref": "#/definitions/ChannelValue", + "description": "The horizontal facet position channel, for mark-level faceting, bound to the *fx* scale." + }, + "fy": { + "$ref": "#/definitions/ChannelValue", + "description": "The vertical facet position channel, for mark-level faceting, bound to the\n*fy* scale." + }, + "href": { + "$ref": "#/definitions/ChannelValue", + "description": "The [href][1]; a channel specifying URLs for clickable links. May be used in conjunction with the **target** option to open links in another window.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/href" + }, + "imageFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A CSS [filter][1]; a constant string used to adjust the rendering of images, such as *blur(5px)*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/filter" + }, + "inset": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four insets: **insetTop**,\n**insetRight**, **insetBottom**, and **insetLeft**. All insets typically default to zero, though not always (say when using bin transform). A positive inset reduces effective area, while a negative inset increases it." + }, + "insetBottom": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Insets the bottom edge by the specified number of pixels. A positive value insets towards the top edge (reducing effective area), while a negative value insets away from the top edge (increasing it)." + }, + "insetLeft": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Insets the left edge by the specified number of pixels. A positive value insets towards the right edge (reducing effective area), while a negative value insets away from the right edge (increasing it)." + }, + "insetRight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Insets the right edge by the specified number of pixels. A positive value insets towards the left edge (reducing effective area), while a negative value insets away from the left edge (increasing it)." + }, + "insetTop": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Insets the top edge by the specified number of pixels. A positive value insets towards the bottom edge (reducing effective area), while a negative value insets away from the bottom edge (increasing it)." + }, + "interval": { + "anyOf": [ + { + "$ref": "#/definitions/Interval" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to convert a continuous value (**x** for barX, or **y** for barY) into an interval (**x1** and **x2** for barX, or **y1** and **y2** for barY); one of:\n\n- a named time interval such as *day* (for date intervals)\n- a number (for number intervals), defining intervals at integer multiples of *n*\n\nSetting this option disables the implicit stack transform (stackX for barX, or stackY for barY)." + }, + "margin": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four mark margins: **marginTop**,\n**marginRight**, **marginBottom**, and **marginLeft**; typically defaults to 0, except for axis marks." + }, + "marginBottom": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s bottom margin; the minimum distance in pixels between the bottom edges of the inner and outer plot area." + }, + "marginLeft": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s left margin; the minimum distance in pixels between the left edges of the inner and outer plot area." + }, + "marginRight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s right margin; the minimum distance in pixels between the right edges of the mark’s inner and outer plot area." + }, + "marginTop": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s top margin; the minimum distance in pixels between the top edges of the inner and outer plot area." + }, + "mark": { + "const": "barY", + "description": "A vertical bar mark. The required *y* values should be quantitative or temporal, and the optional *x* values should be ordinal.\n\nIf neither **y1** nor **y2** nor **interval** is specified, an implicit stackY transform is applied and **y** defaults to the identity function, assuming that *data* = [*y₀*, *y₁*, *y₂*, …]. Otherwise if an **interval** is specified, then **y1** and **y2** are derived from **y**, representing the lower and upper bound of the containing interval, respectively. Otherwise, if only one of **y1** or **y2** is specified, the other defaults to **y**, which defaults to zero.\n\nThe optional **x** ordinal channel specifies the horizontal position; it is typically bound to the *x* scale, which must be a *band* scale. If the\n**x** channel is not specified, the bar will span the horizontal extent of the plot’s frame.\n\nIf *x* is quantitative, use the rectY mark instead. If *y* is ordinal, use the cell mark instead.", + "type": "string" + }, + "mixBlendMode": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [mix-blend-mode][1]; a constant string specifying how to blend content such as *multiply*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode" + }, + "offset": { + "anyOf": [ + { + "$ref": "#/definitions/StackOffset" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "After stacking, an optional **offset** can be applied to translate and scale stacks, say to produce a streamgraph; defaults to null for a zero baseline (**y** = 0 for stackY, and **x** = 0 for stackX). If the *wiggle* offset is used, the default **order** changes to *inside-out*." + }, + "opacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally. For faster rendering, prefer the **strokeOpacity** or **fillOpacity** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/opacity" + }, + "order": { + "anyOf": [ + { + "$ref": "#/definitions/StackOrder" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The order in which stacks are layered; one of:\n\n- null (default) for input order\n- a named stack order method such as *inside-out* or *sum*\n- a field name, for natural order of the corresponding values\n- a function of data, for natural order of the corresponding values\n- an array of explicit **z** values in the desired order\n\nIf the *wiggle* **offset** is used, as for a streamgraph, the default changes to *inside-out*." + }, + "paintOrder": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [paint-order][1]; a constant string specifying the order in which the\n**fill**, **stroke**, and any markers are drawn; defaults to *normal*, which draws the fill, then stroke, then markers; defaults to *stroke* for the text mark to create a “halo” around text to improve legibility.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/paint-order" + }, + "pointerEvents": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [pointer-events][1] property; a constant string such as *none*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/pointer-events" + }, + "reverse": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Applies a transform to reverse the order of the mark’s index, say for reverse input order." + }, + "rx": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The rounded corner [*x*-radius][1], either in pixels or as a percentage of the rect width. If **rx** is not specified, it defaults to **ry** if present, and otherwise draws square corners.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/rx" + }, + "ry": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The rounded corner [*y*-radius][1], either in pixels or as a percentage of the rect height. If **ry** is not specified, it defaults to **rx** if present, and otherwise draws square corners.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/ry" + }, + "select": { + "$ref": "#/definitions/SelectFilter", + "description": "Applies a filter transform after data is loaded to highlight selected values only. For example, `first` and `last` select the first or last values of series only (using the *z* channel to separate series). Meanwhile, `nearestX` and `nearestY` select the point nearest to the pointer along the *x* or *y* channel dimension. Unlike Mosaic selections, a mark level *select* is internal to the mark only, and does not populate a param or selection value to be shared across clients.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "shapeRendering": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [shape-rendering][1]; a constant string such as *crispEdges*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/shape-rendering" + }, + "sort": { + "anyOf": [ + { + "$ref": "#/definitions/SortOrder" + }, + { + "$ref": "#/definitions/ChannelDomainSort" + } + ], + "description": "Either applies a transform to sort the mark’s index by the specified channel values, or imputes ordinal scale domains from this mark’s channels.\n\nWhen imputing ordinal scale domains from channel values, the **sort** option is an object whose keys are ordinal scale names such as *x* or *fx*, and whose values are channel names such as *y*, *y1*, or *y2*. For example, to impute the *y* scale’s domain from the associated *x* channel values in ascending order:\n\n```js sort: {y: \"x\"} ```\n\nFor different sort options for different scales, replace the channel name with a *value* object and per-scale options:\n\n```js sort: {y: {value: \"-x\"}} ```\n\nWhen sorting the mark’s index, the **sort** option is instead one of:\n\n- a channel value definition for sorting given values in ascending order\n- a {value, order} object for sorting given values\n- a {channel, order} object for sorting the named channel’s values" + }, + "stroke": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke" + }, + "strokeDasharray": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dasharray][1]; a constant number indicating the length in pixels of alternating dashes and gaps, or a constant string of numbers separated by spaces or commas (_e.g._, *10 2* for dashes of 10 pixels separated by gaps of 2 pixels), or *none* (the default) for no dashing\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dasharray" + }, + "strokeDashoffset": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dashoffset][1]; a constant indicating the offset in pixels of the first dash along the stroke; defaults to zero.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dashoffset" + }, + "strokeLinecap": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linecap][1]; a constant specifying how to cap stroked paths, such as *butt*, *round*, or *square*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linecap" + }, + "strokeLinejoin": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linejoin][1]; a constant specifying how to join stroked paths, such as *bevel*, *miter*, *miter-clip*, or *round*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linejoin" + }, + "strokeMiterlimit": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-miterlimit][1]; a constant number specifying how to limit the length of *miter* joins on stroked paths.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-miterlimit" + }, + "strokeOpacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-opacity" + }, + "strokeWidth": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-width][1]; a constant number in pixels, or a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-width" + }, + "target": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [target][1]; a constant string specifying the target window (_e.g._,\n*_blank*) for clickable links; used in conjunction with the **href** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/target" + }, + "tip": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/TipPointer" + }, + { + "properties": { + "anchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The tip anchor specifies how to orient the tip box relative to its anchor position; it refers to the part of the tip box that is attached to the anchor point. For example, the *top-left* anchor places the top-left corner of tip box near the anchor position, hence placing the tip box below and to the right of the anchor position." + }, + "fontFamily": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font-family][1]; a constant; defaults to the plot’s font family, which is typically [*system-ui*][2].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-family [2]: https://drafts.csswg.org/css-fonts-4/#valdef-font-family-system-ui" + }, + "fontSize": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font size][1] in pixels; either a constant or a channel; defaults to the plot’s font size, which is typically 10. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-size" + }, + "fontStyle": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font style][1]; a constant; defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-style" + }, + "fontVariant": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font variant][1]; a constant; if the **text** channel contains numbers or dates, defaults to *tabular-nums* to facilitate comparing numbers; otherwise defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant" + }, + "fontWeight": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font weight][1]; a constant; defaults to the plot’s font weight, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight" + }, + "format": { + "additionalProperties": false, + "description": "How channel values are formatted for display. If a format is a string, it is interpreted as a (UTC) time format for temporal channels, and otherwise a number format.", + "properties": { + "ariaLabel": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fill": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fillOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fontSize": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fx": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fy": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "geometry": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "height": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "href": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "length": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "opacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "path": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "r": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "rotate": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "src": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "stroke": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeWidth": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "symbol": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "text": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "title": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "weight": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "width": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "z": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + } + }, + "type": "object" + }, + "frameAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The frame anchor specifies defaults for **x** and **y** based on the plot’s frame; it may be one of the four sides (*top*, *right*, *bottom*, *left*), one of the four corners (*top-left*, *top-right*, *bottom-right*,\n*bottom-left*), or the *middle* of the frame. For example, for tips distributed horizontally at the top of the frame:\n\n```js Plot.tip(data, {x: \"date\", frameAnchor: \"top\"}) ```" + }, + "lineHeight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line height in ems; defaults to 1. The line height affects the (typically vertical) separation between adjacent baselines of text, as well as the separation between the text and its anchor point." + }, + "lineWidth": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line width in ems (e.g., 10 for about 20 characters); defaults to infinity, disabling wrapping and clipping.\n\nIf **textOverflow** is null, lines will be wrapped at the specified length. If a line is split at a soft hyphen (\\xad), a hyphen (-) will be displayed at the end of the line. If **textOverflow** is not null, lines will be clipped according to the given strategy." + }, + "monospace": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, changes the default **fontFamily** to *monospace*, and uses simplified monospaced text metrics calculations." + }, + "pathFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The image filter for the tip’s box; defaults to a drop shadow." + }, + "pointer": { + "$ref": "#/definitions/TipPointer" + }, + "pointerSize": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The size of the tip’s pointer in pixels; defaults to 12." + }, + "preferredAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If an explicit tip anchor is not specified, an anchor is chosen automatically such that the tip fits within the plot’s frame; if the preferred anchor fits, it is chosen." + }, + "textAnchor": { + "anyOf": [ + { + "const": "start", + "type": "string" + }, + { + "const": "middle", + "type": "string" + }, + { + "const": "end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [text anchor][1] controls how text is aligned (typically horizontally) relative to its anchor point; it is one of *start*, *end*, or *middle*. If the frame anchor is *left*, *top-left*, or *bottom-left*, the default text anchor is *start*; if the frame anchor is *right*, *top-right*, or\n*bottom-right*, the default is *end*; otherwise it is *middle*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/text-anchor" + }, + "textOverflow": { + "anyOf": [ + { + "type": "null" + }, + { + "const": "clip", + "type": "string" + }, + { + "const": "ellipsis", + "type": "string" + }, + { + "const": "clip-start", + "type": "string" + }, + { + "const": "clip-end", + "type": "string" + }, + { + "const": "ellipsis-start", + "type": "string" + }, + { + "const": "ellipsis-middle", + "type": "string" + }, + { + "const": "ellipsis-end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How truncate (or wrap) lines of text longer than the given **lineWidth**; one of:\n\n- null (default) - preserve overflowing characters (and wrap if needed)\n- *clip* or *clip-end* - remove characters from the end\n- *clip-start* - remove characters from the start\n- *ellipsis* or *ellipsis-end* - replace characters from the end with an ellipsis (…)\n- *ellipsis-start* - replace characters from the start with an ellipsis (…)\n- *ellipsis-middle* - replace characters from the middle with an ellipsis (…)\n\nIf no **title** was specified, if text requires truncation, a title containing the non-truncated text will be implicitly added." + }, + "textPadding": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The padding around the text in pixels; defaults to 8." + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + } + }, + "type": "object" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to generate a tooltip for this mark, and any tip options." + }, + "title": { + "$ref": "#/definitions/ChannelValue", + "description": "The title; a channel specifying accessible, short textual descriptions as strings (possibly with newlines). If the tip option is specified, the title will be displayed with an interactive tooltip instead of using the SVG [title element][1].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/title" + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The optional horizontal position of the bar; a ordinal channel typically bound to the *x* scale. If not specified, the bar spans the horizontal extent of the frame; otherwise the *x* scale must be a *band* scale.\n\nIf *x* represents quantitative or temporal values, use a rectY mark instead." + }, + "y": { + "$ref": "#/definitions/ChannelValueIntervalSpec", + "description": "The vertical position (or length/height) channel, typically bound to the\n*y* scale.\n\nIf neither **y1** nor **y2** nor **interval** is specified, an implicit stackY transform is applied and **y** defaults to the identity function, assuming that *data* = [*y₀*, *y₁*, *y₂*, …]. Otherwise if an **interval** is specified, then **y1** and **y2** are derived from **y**, representing the lower and upper bound of the containing interval, respectively. Otherwise, if only one of **y1** or **y2** is specified, the other defaults to **y**, which defaults to zero." + }, + "y1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The required primary (starting, often bottom) vertical position channel, typically bound to the *y* scale. Setting this option disables the implicit stackY transform.\n\nIf *y* represents ordinal values, use a cell mark instead." + }, + "y2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The required secondary (ending, often top) horizontal position channel, typically bound to the *y* scale. Setting this option disables the implicit stackY transform.\n\nIf *y* represents ordinal values, use a cell mark instead." + }, + "z": { + "$ref": "#/definitions/ChannelValue", + "description": "The **z** channel defines the series of each value in the stack. Used when the **order** is *sum*, *appearance*, *inside-out*, or an explicit array of\n**z** values." + } + }, + "required": [ + "data", + "mark" + ], + "type": "object" + }, + "Bin": { + "additionalProperties": false, + "properties": { + "bin": { + "anyOf": [ + { + "description": "A transform argument.", + "type": [ + "string", + "number", + "boolean" + ] + }, + { + "items": { + "description": "A transform argument.", + "type": [ + "string", + "number", + "boolean" + ] + }, + "maxItems": 1, + "minItems": 1, + "type": "array" + } + ], + "description": "Bin a continuous variable into discrete intervals. The bin argument specifies a data column or expression to bin. Both numerical and temporal (date/time) values are supported." + }, + "interval": { + "$ref": "#/definitions/BinInterval", + "description": "The interval bin unit to use, typically used to indicate a date/time unit for binning temporal values, such as `hour`, `day`, or `month`. If `date`, the extent of data values is used to automatically select an interval for temporal data. The value `number` enforces normal numerical binning, even over temporal data. If unspecified, defaults to `number` for numerical data and `date` for temporal data." + }, + "minstep": { + "description": "The minimum allowed bin step size (default `0`) when performing numerical binning. For example, a setting of `1` prevents step sizes less than 1. This option is ignored when **step** is specified.", + "type": "number" + }, + "nice": { + "const": true, + "description": "A flag (default `true`) requesting \"nice\" human-friendly end points and step sizes when performing numerical binning. When **step** is specified, this option affects the binning end points (e.g., origin) only.", + "type": "boolean" + }, + "offset": { + "description": "Offset for computed bins (default `0`). For example, a value of `1` will result in using the next consecutive bin boundary.", + "type": "number" + }, + "step": { + "description": "The step size to use between bins. When binning numerical values (or interval type `number`), this setting specifies the numerical step size. For data/time intervals, this indicates the number of steps of that unit, such as hours, days, or years.", + "type": "number" + }, + "steps": { + "description": "The target number of binning steps to use. To accommodate human-friendly (\"nice\") bin boundaries, the actual number of bins may diverge from this exact value. This option is ignored when **step** is specified.", + "type": "number" + } + }, + "required": [ + "bin" + ], + "type": "object" + }, + "BinInterval": { + "description": "Binning interval names.", + "enum": [ + "date", + "number", + "millisecond", + "second", + "minute", + "hour", + "day", + "month", + "year" + ], + "type": "string" + }, + "BrushStyles": { + "additionalProperties": false, + "description": "Styles for rectangular selection brushes.", + "properties": { + "fill": { + "description": "The fill color of the brush rectangle.", + "type": "string" + }, + "fillOpacity": { + "description": "The fill opacity of the brush rectangle.", + "type": "number" + }, + "opacity": { + "description": "The overall opacity of the brush rectangle.", + "type": "number" + }, + "stroke": { + "description": "The stroke color of the brush rectangle.", + "type": "string" + }, + "strokeOpacity": { + "description": "The stroke opacity of the brush rectangle.", + "type": "number" + } + }, + "type": "object" + }, + "CSSStyles": { + "additionalProperties": { + "type": "string" + }, + "properties": { + "accentColor": { + "type": "string" + }, + "alignContent": { + "type": "string" + }, + "alignItems": { + "type": "string" + }, + "alignSelf": { + "type": "string" + }, + "alignmentBaseline": { + "type": "string" + }, + "all": { + "type": "string" + }, + "animation": { + "type": "string" + }, + "animationComposition": { + "type": "string" + }, + "animationDelay": { + "type": "string" + }, + "animationDirection": { + "type": "string" + }, + "animationDuration": { + "type": "string" + }, + "animationFillMode": { + "type": "string" + }, + "animationIterationCount": { + "type": "string" + }, + "animationName": { + "type": "string" + }, + "animationPlayState": { + "type": "string" + }, + "animationTimingFunction": { + "type": "string" + }, + "appearance": { + "type": "string" + }, + "aspectRatio": { + "type": "string" + }, + "backdropFilter": { + "type": "string" + }, + "backfaceVisibility": { + "type": "string" + }, + "background": { + "type": "string" + }, + "backgroundAttachment": { + "type": "string" + }, + "backgroundBlendMode": { + "type": "string" + }, + "backgroundClip": { + "type": "string" + }, + "backgroundColor": { + "type": "string" + }, + "backgroundImage": { + "type": "string" + }, + "backgroundOrigin": { + "type": "string" + }, + "backgroundPosition": { + "type": "string" + }, + "backgroundPositionX": { + "type": "string" + }, + "backgroundPositionY": { + "type": "string" + }, + "backgroundRepeat": { + "type": "string" + }, + "backgroundSize": { + "type": "string" + }, + "baselineShift": { + "type": "string" + }, + "baselineSource": { + "type": "string" + }, + "blockSize": { + "type": "string" + }, + "border": { + "type": "string" + }, + "borderBlock": { + "type": "string" + }, + "borderBlockColor": { + "type": "string" + }, + "borderBlockEnd": { + "type": "string" + }, + "borderBlockEndColor": { + "type": "string" + }, + "borderBlockEndStyle": { + "type": "string" + }, + "borderBlockEndWidth": { + "type": "string" + }, + "borderBlockStart": { + "type": "string" + }, + "borderBlockStartColor": { + "type": "string" + }, + "borderBlockStartStyle": { + "type": "string" + }, + "borderBlockStartWidth": { + "type": "string" + }, + "borderBlockStyle": { + "type": "string" + }, + "borderBlockWidth": { + "type": "string" + }, + "borderBottom": { + "type": "string" + }, + "borderBottomColor": { + "type": "string" + }, + "borderBottomLeftRadius": { + "type": "string" + }, + "borderBottomRightRadius": { + "type": "string" + }, + "borderBottomStyle": { + "type": "string" + }, + "borderBottomWidth": { + "type": "string" + }, + "borderCollapse": { + "type": "string" + }, + "borderColor": { + "type": "string" + }, + "borderEndEndRadius": { + "type": "string" + }, + "borderEndStartRadius": { + "type": "string" + }, + "borderImage": { + "type": "string" + }, + "borderImageOutset": { + "type": "string" + }, + "borderImageRepeat": { + "type": "string" + }, + "borderImageSlice": { + "type": "string" + }, + "borderImageSource": { + "type": "string" + }, + "borderImageWidth": { + "type": "string" + }, + "borderInline": { + "type": "string" + }, + "borderInlineColor": { + "type": "string" + }, + "borderInlineEnd": { + "type": "string" + }, + "borderInlineEndColor": { + "type": "string" + }, + "borderInlineEndStyle": { + "type": "string" + }, + "borderInlineEndWidth": { + "type": "string" + }, + "borderInlineStart": { + "type": "string" + }, + "borderInlineStartColor": { + "type": "string" + }, + "borderInlineStartStyle": { + "type": "string" + }, + "borderInlineStartWidth": { + "type": "string" + }, + "borderInlineStyle": { + "type": "string" + }, + "borderInlineWidth": { + "type": "string" + }, + "borderLeft": { + "type": "string" + }, + "borderLeftColor": { + "type": "string" + }, + "borderLeftStyle": { + "type": "string" + }, + "borderLeftWidth": { + "type": "string" + }, + "borderRadius": { + "type": "string" + }, + "borderRight": { + "type": "string" + }, + "borderRightColor": { + "type": "string" + }, + "borderRightStyle": { + "type": "string" + }, + "borderRightWidth": { + "type": "string" + }, + "borderSpacing": { + "type": "string" + }, + "borderStartEndRadius": { + "type": "string" + }, + "borderStartStartRadius": { + "type": "string" + }, + "borderStyle": { + "type": "string" + }, + "borderTop": { + "type": "string" + }, + "borderTopColor": { + "type": "string" + }, + "borderTopLeftRadius": { + "type": "string" + }, + "borderTopRightRadius": { + "type": "string" + }, + "borderTopStyle": { + "type": "string" + }, + "borderTopWidth": { + "type": "string" + }, + "borderWidth": { + "type": "string" + }, + "bottom": { + "type": "string" + }, + "boxShadow": { + "type": "string" + }, + "boxSizing": { + "type": "string" + }, + "breakAfter": { + "type": "string" + }, + "breakBefore": { + "type": "string" + }, + "breakInside": { + "type": "string" + }, + "captionSide": { + "type": "string" + }, + "caretColor": { + "type": "string" + }, + "clear": { + "type": "string" + }, + "clip": { + "type": "string" + }, + "clipPath": { + "type": "string" + }, + "clipRule": { + "type": "string" + }, + "color": { + "type": "string" + }, + "colorInterpolation": { + "type": "string" + }, + "colorInterpolationFilters": { + "type": "string" + }, + "colorScheme": { + "type": "string" + }, + "columnCount": { + "type": "string" + }, + "columnFill": { + "type": "string" + }, + "columnGap": { + "type": "string" + }, + "columnRule": { + "type": "string" + }, + "columnRuleColor": { + "type": "string" + }, + "columnRuleStyle": { + "type": "string" + }, + "columnRuleWidth": { + "type": "string" + }, + "columnSpan": { + "type": "string" + }, + "columnWidth": { + "type": "string" + }, + "columns": { + "type": "string" + }, + "contain": { + "type": "string" + }, + "containIntrinsicBlockSize": { + "type": "string" + }, + "containIntrinsicHeight": { + "type": "string" + }, + "containIntrinsicInlineSize": { + "type": "string" + }, + "containIntrinsicSize": { + "type": "string" + }, + "containIntrinsicWidth": { + "type": "string" + }, + "container": { + "type": "string" + }, + "containerName": { + "type": "string" + }, + "containerType": { + "type": "string" + }, + "content": { + "type": "string" + }, + "contentVisibility": { + "type": "string" + }, + "counterIncrement": { + "type": "string" + }, + "counterReset": { + "type": "string" + }, + "counterSet": { + "type": "string" + }, + "cssFloat": { + "type": "string" + }, + "cssText": { + "type": "string" + }, + "cursor": { + "type": "string" + }, + "cx": { + "type": "string" + }, + "cy": { + "type": "string" + }, + "d": { + "type": "string" + }, + "direction": { + "type": "string" + }, + "display": { + "type": "string" + }, + "dominantBaseline": { + "type": "string" + }, + "emptyCells": { + "type": "string" + }, + "fill": { + "type": "string" + }, + "fillOpacity": { + "type": "string" + }, + "fillRule": { + "type": "string" + }, + "filter": { + "type": "string" + }, + "flex": { + "type": "string" + }, + "flexBasis": { + "type": "string" + }, + "flexDirection": { + "type": "string" + }, + "flexFlow": { + "type": "string" + }, + "flexGrow": { + "type": "string" + }, + "flexShrink": { + "type": "string" + }, + "flexWrap": { + "type": "string" + }, + "float": { + "type": "string" + }, + "floodColor": { + "type": "string" + }, + "floodOpacity": { + "type": "string" + }, + "font": { + "type": "string" + }, + "fontFamily": { + "type": "string" + }, + "fontFeatureSettings": { + "type": "string" + }, + "fontKerning": { + "type": "string" + }, + "fontOpticalSizing": { + "type": "string" + }, + "fontPalette": { + "type": "string" + }, + "fontSize": { + "type": "string" + }, + "fontSizeAdjust": { + "type": "string" + }, + "fontStretch": { + "type": "string" + }, + "fontStyle": { + "type": "string" + }, + "fontSynthesis": { + "type": "string" + }, + "fontSynthesisSmallCaps": { + "type": "string" + }, + "fontSynthesisStyle": { + "type": "string" + }, + "fontSynthesisWeight": { + "type": "string" + }, + "fontVariant": { + "type": "string" + }, + "fontVariantAlternates": { + "type": "string" + }, + "fontVariantCaps": { + "type": "string" + }, + "fontVariantEastAsian": { + "type": "string" + }, + "fontVariantLigatures": { + "type": "string" + }, + "fontVariantNumeric": { + "type": "string" + }, + "fontVariantPosition": { + "type": "string" + }, + "fontVariationSettings": { + "type": "string" + }, + "fontWeight": { + "type": "string" + }, + "forcedColorAdjust": { + "type": "string" + }, + "gap": { + "type": "string" + }, + "grid": { + "type": "string" + }, + "gridArea": { + "type": "string" + }, + "gridAutoColumns": { + "type": "string" + }, + "gridAutoFlow": { + "type": "string" + }, + "gridAutoRows": { + "type": "string" + }, + "gridColumn": { + "type": "string" + }, + "gridColumnEnd": { + "type": "string" + }, + "gridColumnGap": { + "type": "string" + }, + "gridColumnStart": { + "type": "string" + }, + "gridGap": { + "type": "string" + }, + "gridRow": { + "type": "string" + }, + "gridRowEnd": { + "type": "string" + }, + "gridRowGap": { + "type": "string" + }, + "gridRowStart": { + "type": "string" + }, + "gridTemplate": { + "type": "string" + }, + "gridTemplateAreas": { + "type": "string" + }, + "gridTemplateColumns": { + "type": "string" + }, + "gridTemplateRows": { + "type": "string" + }, + "height": { + "type": "string" + }, + "hyphenateCharacter": { + "type": "string" + }, + "hyphens": { + "type": "string" + }, + "imageOrientation": { + "type": "string" + }, + "imageRendering": { + "type": "string" + }, + "inlineSize": { + "type": "string" + }, + "inset": { + "type": "string" + }, + "insetBlock": { + "type": "string" + }, + "insetBlockEnd": { + "type": "string" + }, + "insetBlockStart": { + "type": "string" + }, + "insetInline": { + "type": "string" + }, + "insetInlineEnd": { + "type": "string" + }, + "insetInlineStart": { + "type": "string" + }, + "isolation": { + "type": "string" + }, + "justifyContent": { + "type": "string" + }, + "justifyItems": { + "type": "string" + }, + "justifySelf": { + "type": "string" + }, + "left": { + "type": "string" + }, + "length": { + "type": "number" + }, + "letterSpacing": { + "type": "string" + }, + "lightingColor": { + "type": "string" + }, + "lineBreak": { + "type": "string" + }, + "lineHeight": { + "type": "string" + }, + "listStyle": { + "type": "string" + }, + "listStyleImage": { + "type": "string" + }, + "listStylePosition": { + "type": "string" + }, + "listStyleType": { + "type": "string" + }, + "margin": { + "type": "string" + }, + "marginBlock": { + "type": "string" + }, + "marginBlockEnd": { + "type": "string" + }, + "marginBlockStart": { + "type": "string" + }, + "marginBottom": { + "type": "string" + }, + "marginInline": { + "type": "string" + }, + "marginInlineEnd": { + "type": "string" + }, + "marginInlineStart": { + "type": "string" + }, + "marginLeft": { + "type": "string" + }, + "marginRight": { + "type": "string" + }, + "marginTop": { + "type": "string" + }, + "marker": { + "type": "string" + }, + "markerEnd": { + "type": "string" + }, + "markerMid": { + "type": "string" + }, + "markerStart": { + "type": "string" + }, + "mask": { + "type": "string" + }, + "maskClip": { + "type": "string" + }, + "maskComposite": { + "type": "string" + }, + "maskImage": { + "type": "string" + }, + "maskMode": { + "type": "string" + }, + "maskOrigin": { + "type": "string" + }, + "maskPosition": { + "type": "string" + }, + "maskRepeat": { + "type": "string" + }, + "maskSize": { + "type": "string" + }, + "maskType": { + "type": "string" + }, + "mathDepth": { + "type": "string" + }, + "mathStyle": { + "type": "string" + }, + "maxBlockSize": { + "type": "string" + }, + "maxHeight": { + "type": "string" + }, + "maxInlineSize": { + "type": "string" + }, + "maxWidth": { + "type": "string" + }, + "minBlockSize": { + "type": "string" + }, + "minHeight": { + "type": "string" + }, + "minInlineSize": { + "type": "string" + }, + "minWidth": { + "type": "string" + }, + "mixBlendMode": { + "type": "string" + }, + "objectFit": { + "type": "string" + }, + "objectPosition": { + "type": "string" + }, + "offset": { + "type": "string" + }, + "offsetAnchor": { + "type": "string" + }, + "offsetDistance": { + "type": "string" + }, + "offsetPath": { + "type": "string" + }, + "offsetPosition": { + "type": "string" + }, + "offsetRotate": { + "type": "string" + }, + "opacity": { + "type": "string" + }, + "order": { + "type": "string" + }, + "orphans": { + "type": "string" + }, + "outline": { + "type": "string" + }, + "outlineColor": { + "type": "string" + }, + "outlineOffset": { + "type": "string" + }, + "outlineStyle": { + "type": "string" + }, + "outlineWidth": { + "type": "string" + }, + "overflow": { + "type": "string" + }, + "overflowAnchor": { + "type": "string" + }, + "overflowClipMargin": { + "type": "string" + }, + "overflowWrap": { + "type": "string" + }, + "overflowX": { + "type": "string" + }, + "overflowY": { + "type": "string" + }, + "overscrollBehavior": { + "type": "string" + }, + "overscrollBehaviorBlock": { + "type": "string" + }, + "overscrollBehaviorInline": { + "type": "string" + }, + "overscrollBehaviorX": { + "type": "string" + }, + "overscrollBehaviorY": { + "type": "string" + }, + "padding": { + "type": "string" + }, + "paddingBlock": { + "type": "string" + }, + "paddingBlockEnd": { + "type": "string" + }, + "paddingBlockStart": { + "type": "string" + }, + "paddingBottom": { + "type": "string" + }, + "paddingInline": { + "type": "string" + }, + "paddingInlineEnd": { + "type": "string" + }, + "paddingInlineStart": { + "type": "string" + }, + "paddingLeft": { + "type": "string" + }, + "paddingRight": { + "type": "string" + }, + "paddingTop": { + "type": "string" + }, + "page": { + "type": "string" + }, + "pageBreakAfter": { + "type": "string" + }, + "pageBreakBefore": { + "type": "string" + }, + "pageBreakInside": { + "type": "string" + }, + "paintOrder": { + "type": "string" + }, + "perspective": { + "type": "string" + }, + "perspectiveOrigin": { + "type": "string" + }, + "placeContent": { + "type": "string" + }, + "placeItems": { + "type": "string" + }, + "placeSelf": { + "type": "string" + }, + "pointerEvents": { + "type": "string" + }, + "position": { + "type": "string" + }, + "printColorAdjust": { + "type": "string" + }, + "quotes": { + "type": "string" + }, + "r": { + "type": "string" + }, + "resize": { + "type": "string" + }, + "right": { + "type": "string" + }, + "rotate": { + "type": "string" + }, + "rowGap": { + "type": "string" + }, + "rubyPosition": { + "type": "string" + }, + "rx": { + "type": "string" + }, + "ry": { + "type": "string" + }, + "scale": { + "type": "string" + }, + "scrollBehavior": { + "type": "string" + }, + "scrollMargin": { + "type": "string" + }, + "scrollMarginBlock": { + "type": "string" + }, + "scrollMarginBlockEnd": { + "type": "string" + }, + "scrollMarginBlockStart": { + "type": "string" + }, + "scrollMarginBottom": { + "type": "string" + }, + "scrollMarginInline": { + "type": "string" + }, + "scrollMarginInlineEnd": { + "type": "string" + }, + "scrollMarginInlineStart": { + "type": "string" + }, + "scrollMarginLeft": { + "type": "string" + }, + "scrollMarginRight": { + "type": "string" + }, + "scrollMarginTop": { + "type": "string" + }, + "scrollPadding": { + "type": "string" + }, + "scrollPaddingBlock": { + "type": "string" + }, + "scrollPaddingBlockEnd": { + "type": "string" + }, + "scrollPaddingBlockStart": { + "type": "string" + }, + "scrollPaddingBottom": { + "type": "string" + }, + "scrollPaddingInline": { + "type": "string" + }, + "scrollPaddingInlineEnd": { + "type": "string" + }, + "scrollPaddingInlineStart": { + "type": "string" + }, + "scrollPaddingLeft": { + "type": "string" + }, + "scrollPaddingRight": { + "type": "string" + }, + "scrollPaddingTop": { + "type": "string" + }, + "scrollSnapAlign": { + "type": "string" + }, + "scrollSnapStop": { + "type": "string" + }, + "scrollSnapType": { + "type": "string" + }, + "scrollbarColor": { + "type": "string" + }, + "scrollbarGutter": { + "type": "string" + }, + "scrollbarWidth": { + "type": "string" + }, + "shapeImageThreshold": { + "type": "string" + }, + "shapeMargin": { + "type": "string" + }, + "shapeOutside": { + "type": "string" + }, + "shapeRendering": { + "type": "string" + }, + "stopColor": { + "type": "string" + }, + "stopOpacity": { + "type": "string" + }, + "stroke": { + "type": "string" + }, + "strokeDasharray": { + "type": "string" + }, + "strokeDashoffset": { + "type": "string" + }, + "strokeLinecap": { + "type": "string" + }, + "strokeLinejoin": { + "type": "string" + }, + "strokeMiterlimit": { + "type": "string" + }, + "strokeOpacity": { + "type": "string" + }, + "strokeWidth": { + "type": "string" + }, + "tabSize": { + "type": "string" + }, + "tableLayout": { + "type": "string" + }, + "textAlign": { + "type": "string" + }, + "textAlignLast": { + "type": "string" + }, + "textAnchor": { + "type": "string" + }, + "textCombineUpright": { + "type": "string" + }, + "textDecoration": { + "type": "string" + }, + "textDecorationColor": { + "type": "string" + }, + "textDecorationLine": { + "type": "string" + }, + "textDecorationSkipInk": { + "type": "string" + }, + "textDecorationStyle": { + "type": "string" + }, + "textDecorationThickness": { + "type": "string" + }, + "textEmphasis": { + "type": "string" + }, + "textEmphasisColor": { + "type": "string" + }, + "textEmphasisPosition": { + "type": "string" + }, + "textEmphasisStyle": { + "type": "string" + }, + "textIndent": { + "type": "string" + }, + "textOrientation": { + "type": "string" + }, + "textOverflow": { + "type": "string" + }, + "textRendering": { + "type": "string" + }, + "textShadow": { + "type": "string" + }, + "textTransform": { + "type": "string" + }, + "textUnderlineOffset": { + "type": "string" + }, + "textUnderlinePosition": { + "type": "string" + }, + "textWrap": { + "type": "string" + }, + "textWrapMode": { + "type": "string" + }, + "textWrapStyle": { + "type": "string" + }, + "top": { + "type": "string" + }, + "touchAction": { + "type": "string" + }, + "transform": { + "type": "string" + }, + "transformBox": { + "type": "string" + }, + "transformOrigin": { + "type": "string" + }, + "transformStyle": { + "type": "string" + }, + "transition": { + "type": "string" + }, + "transitionBehavior": { + "type": "string" + }, + "transitionDelay": { + "type": "string" + }, + "transitionDuration": { + "type": "string" + }, + "transitionProperty": { + "type": "string" + }, + "transitionTimingFunction": { + "type": "string" + }, + "translate": { + "type": "string" + }, + "unicodeBidi": { + "type": "string" + }, + "userSelect": { + "type": "string" + }, + "vectorEffect": { + "type": "string" + }, + "verticalAlign": { + "type": "string" + }, + "visibility": { + "type": "string" + }, + "webkitAlignContent": { + "type": "string" + }, + "webkitAlignItems": { + "type": "string" + }, + "webkitAlignSelf": { + "type": "string" + }, + "webkitAnimation": { + "type": "string" + }, + "webkitAnimationDelay": { + "type": "string" + }, + "webkitAnimationDirection": { + "type": "string" + }, + "webkitAnimationDuration": { + "type": "string" + }, + "webkitAnimationFillMode": { + "type": "string" + }, + "webkitAnimationIterationCount": { + "type": "string" + }, + "webkitAnimationName": { + "type": "string" + }, + "webkitAnimationPlayState": { + "type": "string" + }, + "webkitAnimationTimingFunction": { + "type": "string" + }, + "webkitAppearance": { + "type": "string" + }, + "webkitBackfaceVisibility": { + "type": "string" + }, + "webkitBackgroundClip": { + "type": "string" + }, + "webkitBackgroundOrigin": { + "type": "string" + }, + "webkitBackgroundSize": { + "type": "string" + }, + "webkitBorderBottomLeftRadius": { + "type": "string" + }, + "webkitBorderBottomRightRadius": { + "type": "string" + }, + "webkitBorderRadius": { + "type": "string" + }, + "webkitBorderTopLeftRadius": { + "type": "string" + }, + "webkitBorderTopRightRadius": { + "type": "string" + }, + "webkitBoxAlign": { + "type": "string" + }, + "webkitBoxFlex": { + "type": "string" + }, + "webkitBoxOrdinalGroup": { + "type": "string" + }, + "webkitBoxOrient": { + "type": "string" + }, + "webkitBoxPack": { + "type": "string" + }, + "webkitBoxShadow": { + "type": "string" + }, + "webkitBoxSizing": { + "type": "string" + }, + "webkitFilter": { + "type": "string" + }, + "webkitFlex": { + "type": "string" + }, + "webkitFlexBasis": { + "type": "string" + }, + "webkitFlexDirection": { + "type": "string" + }, + "webkitFlexFlow": { + "type": "string" + }, + "webkitFlexGrow": { + "type": "string" + }, + "webkitFlexShrink": { + "type": "string" + }, + "webkitFlexWrap": { + "type": "string" + }, + "webkitJustifyContent": { + "type": "string" + }, + "webkitLineClamp": { + "type": "string" + }, + "webkitMask": { + "type": "string" + }, + "webkitMaskBoxImage": { + "type": "string" + }, + "webkitMaskBoxImageOutset": { + "type": "string" + }, + "webkitMaskBoxImageRepeat": { + "type": "string" + }, + "webkitMaskBoxImageSlice": { + "type": "string" + }, + "webkitMaskBoxImageSource": { + "type": "string" + }, + "webkitMaskBoxImageWidth": { + "type": "string" + }, + "webkitMaskClip": { + "type": "string" + }, + "webkitMaskComposite": { + "type": "string" + }, + "webkitMaskImage": { + "type": "string" + }, + "webkitMaskOrigin": { + "type": "string" + }, + "webkitMaskPosition": { + "type": "string" + }, + "webkitMaskRepeat": { + "type": "string" + }, + "webkitMaskSize": { + "type": "string" + }, + "webkitOrder": { + "type": "string" + }, + "webkitPerspective": { + "type": "string" + }, + "webkitPerspectiveOrigin": { + "type": "string" + }, + "webkitTextFillColor": { + "type": "string" + }, + "webkitTextSizeAdjust": { + "type": "string" + }, + "webkitTextStroke": { + "type": "string" + }, + "webkitTextStrokeColor": { + "type": "string" + }, + "webkitTextStrokeWidth": { + "type": "string" + }, + "webkitTransform": { + "type": "string" + }, + "webkitTransformOrigin": { + "type": "string" + }, + "webkitTransformStyle": { + "type": "string" + }, + "webkitTransition": { + "type": "string" + }, + "webkitTransitionDelay": { + "type": "string" + }, + "webkitTransitionDuration": { + "type": "string" + }, + "webkitTransitionProperty": { + "type": "string" + }, + "webkitTransitionTimingFunction": { + "type": "string" + }, + "webkitUserSelect": { + "type": "string" + }, + "whiteSpace": { + "type": "string" + }, + "whiteSpaceCollapse": { + "type": "string" + }, + "widows": { + "type": "string" + }, + "width": { + "type": "string" + }, + "willChange": { + "type": "string" + }, + "wordBreak": { + "type": "string" + }, + "wordSpacing": { + "type": "string" + }, + "wordWrap": { + "type": "string" + }, + "writingMode": { + "type": "string" + }, + "x": { + "type": "string" + }, + "y": { + "type": "string" + }, + "zIndex": { + "type": "string" + }, + "zoom": { + "type": "string" + } + }, + "type": "object" + }, + "Cell": { + "additionalProperties": false, + "description": "The cell mark.", + "properties": { + "ariaDescription": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-description][1]; a constant textual description.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-description" + }, + "ariaHidden": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-hidden][1] state; a constant indicating whether the element is exposed to an accessibility API.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-hidden" + }, + "ariaLabel": { + "$ref": "#/definitions/ChannelValue", + "description": "The [aria-label][1]; a channel specifying short textual labels representing the value in the accessibility tree.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-label" + }, + "clip": { + "anyOf": [ + { + "const": "frame", + "type": "string" + }, + { + "const": "sphere", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to clip the mark; one of:\n\n- *frame* or true - clip to the plot’s frame (inner area)\n- *sphere* - clip to the projected sphere (*e.g.*, front hemisphere)\n- null or false - do not clip\n\nThe *sphere* clip option requires a geographic projection." + }, + "data": { + "$ref": "#/definitions/PlotMarkData", + "description": "The data source for the mark." + }, + "dx": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The horizontal offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "dy": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The vertical offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "facet": { + "anyOf": [ + { + "const": "auto", + "type": "string" + }, + { + "const": "include", + "type": "string" + }, + { + "const": "exclude", + "type": "string" + }, + { + "const": "super", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to enable or disable faceting; one of:\n\n- *auto* (default) - automatically determine if this mark should be faceted\n- *include* (or true) - draw the subset of the mark’s data in the current facet\n- *exclude* - draw the subset of the mark’s data *not* in the current facet\n- *super* - draw this mark in a single frame that covers all facets\n- null (or false) - repeat this mark’s data across all facets (*i.e.*, no faceting)\n\nWhen a mark uses *super* faceting, it is not allowed to use position scales (*x*, *y*, *fx*, or *fy*); *super* faceting is intended for decorations, such as labels and legends.\n\nWhen top-level faceting is used, the default *auto* setting is equivalent to *include* when the mark data is strictly equal to the top-level facet data; otherwise it is equivalent to null. When the *include* or *exclude* facet mode is chosen, the mark data must be parallel to the top-level facet data: the data must have the same length and order. If the data are not parallel, then the wrong data may be shown in each facet. The default\n*auto* therefore requires strict equality (`===`) for safety, and using the facet data as mark data is recommended when using the *exclude* facet mode. (To construct parallel data safely, consider using [*array*.map][1] on the facet data.)\n\nWhen mark-level faceting is used, the default *auto* setting is equivalent to *include*: the mark will be faceted if either the **fx** or **fy** channel option (or both) is specified. The null or false option will disable faceting, while *exclude* draws the subset of the mark’s data *not* in the current facet.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map" + }, + "facetAnchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "right", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "const": "left", + "type": "string" + }, + { + "const": "top-left", + "type": "string" + }, + { + "const": "top-right", + "type": "string" + }, + { + "const": "bottom-left", + "type": "string" + }, + { + "const": "bottom-right", + "type": "string" + }, + { + "const": "top-empty", + "type": "string" + }, + { + "const": "right-empty", + "type": "string" + }, + { + "const": "bottom-empty", + "type": "string" + }, + { + "const": "left-empty", + "type": "string" + }, + { + "const": "empty", + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to place the mark with respect to facets; one of:\n\n- null (default for most marks) - display the mark in each non-empty facet\n- *top*, *right*, *bottom*, or *left* - display the mark only in facets on the given side\n- *top-empty*, *right-empty*, *bottom-empty*, or *left-empty* (default for axis marks) - display the mark only in facets that have empty space on the given side: either the margin, or an empty facet\n- *empty* - display the mark in empty facets only" + }, + "fill": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill" + }, + "fillOpacity": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill-opacity][1]; a constant number between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill-opacity" + }, + "filter": { + "$ref": "#/definitions/ChannelValue", + "description": "Applies a transform to filter the mark’s index according to the given channel values; only truthy values are retained.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "fx": { + "$ref": "#/definitions/ChannelValue", + "description": "The horizontal facet position channel, for mark-level faceting, bound to the *fx* scale." + }, + "fy": { + "$ref": "#/definitions/ChannelValue", + "description": "The vertical facet position channel, for mark-level faceting, bound to the\n*fy* scale." + }, + "href": { + "$ref": "#/definitions/ChannelValue", + "description": "The [href][1]; a channel specifying URLs for clickable links. May be used in conjunction with the **target** option to open links in another window.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/href" + }, + "imageFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A CSS [filter][1]; a constant string used to adjust the rendering of images, such as *blur(5px)*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/filter" + }, + "inset": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four insets: **insetTop**,\n**insetRight**, **insetBottom**, and **insetLeft**. All insets typically default to zero, though not always (say when using bin transform). A positive inset reduces effective area, while a negative inset increases it." + }, + "insetBottom": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Insets the bottom edge by the specified number of pixels. A positive value insets towards the top edge (reducing effective area), while a negative value insets away from the top edge (increasing it)." + }, + "insetLeft": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Insets the left edge by the specified number of pixels. A positive value insets towards the right edge (reducing effective area), while a negative value insets away from the right edge (increasing it)." + }, + "insetRight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Insets the right edge by the specified number of pixels. A positive value insets towards the left edge (reducing effective area), while a negative value insets away from the left edge (increasing it)." + }, + "insetTop": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Insets the top edge by the specified number of pixels. A positive value insets towards the bottom edge (reducing effective area), while a negative value insets away from the bottom edge (increasing it)." + }, + "margin": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four mark margins: **marginTop**,\n**marginRight**, **marginBottom**, and **marginLeft**; typically defaults to 0, except for axis marks." + }, + "marginBottom": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s bottom margin; the minimum distance in pixels between the bottom edges of the inner and outer plot area." + }, + "marginLeft": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s left margin; the minimum distance in pixels between the left edges of the inner and outer plot area." + }, + "marginRight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s right margin; the minimum distance in pixels between the right edges of the mark’s inner and outer plot area." + }, + "marginTop": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s top margin; the minimum distance in pixels between the top edges of the inner and outer plot area." + }, + "mark": { + "const": "cell", + "description": "A rectangular cell mark. Along with **x** and/or **y**, a **fill** channel is typically specified to encode value as color.\n\nIf neither **x** nor **y** are specified, *data* is assumed to be an array of pairs [[*x₀*, *y₀*], [*x₁*, *y₁*], [*x₂*, *y₂*], …] such that **x** = [*x₀*,\n*x₁*, *x₂*, …] and **y** = [*y₀*, *y₁*, *y₂*, …].\n\nBoth **x** and **y** should be ordinal; if only **x** is quantitative (or temporal), use a barX mark; if only **y** is quantitative, use a barY mark; if both are quantitative, use a rect mark.", + "type": "string" + }, + "mixBlendMode": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [mix-blend-mode][1]; a constant string specifying how to blend content such as *multiply*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode" + }, + "opacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally. For faster rendering, prefer the **strokeOpacity** or **fillOpacity** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/opacity" + }, + "paintOrder": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [paint-order][1]; a constant string specifying the order in which the\n**fill**, **stroke**, and any markers are drawn; defaults to *normal*, which draws the fill, then stroke, then markers; defaults to *stroke* for the text mark to create a “halo” around text to improve legibility.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/paint-order" + }, + "pointerEvents": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [pointer-events][1] property; a constant string such as *none*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/pointer-events" + }, + "reverse": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Applies a transform to reverse the order of the mark’s index, say for reverse input order." + }, + "rx": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The rounded corner [*x*-radius][1], either in pixels or as a percentage of the rect width. If **rx** is not specified, it defaults to **ry** if present, and otherwise draws square corners.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/rx" + }, + "ry": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The rounded corner [*y*-radius][1], either in pixels or as a percentage of the rect height. If **ry** is not specified, it defaults to **rx** if present, and otherwise draws square corners.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/ry" + }, + "select": { + "$ref": "#/definitions/SelectFilter", + "description": "Applies a filter transform after data is loaded to highlight selected values only. For example, `first` and `last` select the first or last values of series only (using the *z* channel to separate series). Meanwhile, `nearestX` and `nearestY` select the point nearest to the pointer along the *x* or *y* channel dimension. Unlike Mosaic selections, a mark level *select* is internal to the mark only, and does not populate a param or selection value to be shared across clients.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "shapeRendering": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [shape-rendering][1]; a constant string such as *crispEdges*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/shape-rendering" + }, + "sort": { + "anyOf": [ + { + "$ref": "#/definitions/SortOrder" + }, + { + "$ref": "#/definitions/ChannelDomainSort" + } + ], + "description": "Either applies a transform to sort the mark’s index by the specified channel values, or imputes ordinal scale domains from this mark’s channels.\n\nWhen imputing ordinal scale domains from channel values, the **sort** option is an object whose keys are ordinal scale names such as *x* or *fx*, and whose values are channel names such as *y*, *y1*, or *y2*. For example, to impute the *y* scale’s domain from the associated *x* channel values in ascending order:\n\n```js sort: {y: \"x\"} ```\n\nFor different sort options for different scales, replace the channel name with a *value* object and per-scale options:\n\n```js sort: {y: {value: \"-x\"}} ```\n\nWhen sorting the mark’s index, the **sort** option is instead one of:\n\n- a channel value definition for sorting given values in ascending order\n- a {value, order} object for sorting given values\n- a {channel, order} object for sorting the named channel’s values" + }, + "stroke": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke" + }, + "strokeDasharray": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dasharray][1]; a constant number indicating the length in pixels of alternating dashes and gaps, or a constant string of numbers separated by spaces or commas (_e.g._, *10 2* for dashes of 10 pixels separated by gaps of 2 pixels), or *none* (the default) for no dashing\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dasharray" + }, + "strokeDashoffset": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dashoffset][1]; a constant indicating the offset in pixels of the first dash along the stroke; defaults to zero.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dashoffset" + }, + "strokeLinecap": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linecap][1]; a constant specifying how to cap stroked paths, such as *butt*, *round*, or *square*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linecap" + }, + "strokeLinejoin": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linejoin][1]; a constant specifying how to join stroked paths, such as *bevel*, *miter*, *miter-clip*, or *round*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linejoin" + }, + "strokeMiterlimit": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-miterlimit][1]; a constant number specifying how to limit the length of *miter* joins on stroked paths.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-miterlimit" + }, + "strokeOpacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-opacity" + }, + "strokeWidth": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-width][1]; a constant number in pixels, or a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-width" + }, + "target": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [target][1]; a constant string specifying the target window (_e.g._,\n*_blank*) for clickable links; used in conjunction with the **href** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/target" + }, + "tip": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/TipPointer" + }, + { + "properties": { + "anchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The tip anchor specifies how to orient the tip box relative to its anchor position; it refers to the part of the tip box that is attached to the anchor point. For example, the *top-left* anchor places the top-left corner of tip box near the anchor position, hence placing the tip box below and to the right of the anchor position." + }, + "fontFamily": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font-family][1]; a constant; defaults to the plot’s font family, which is typically [*system-ui*][2].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-family [2]: https://drafts.csswg.org/css-fonts-4/#valdef-font-family-system-ui" + }, + "fontSize": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font size][1] in pixels; either a constant or a channel; defaults to the plot’s font size, which is typically 10. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-size" + }, + "fontStyle": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font style][1]; a constant; defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-style" + }, + "fontVariant": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font variant][1]; a constant; if the **text** channel contains numbers or dates, defaults to *tabular-nums* to facilitate comparing numbers; otherwise defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant" + }, + "fontWeight": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font weight][1]; a constant; defaults to the plot’s font weight, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight" + }, + "format": { + "additionalProperties": false, + "description": "How channel values are formatted for display. If a format is a string, it is interpreted as a (UTC) time format for temporal channels, and otherwise a number format.", + "properties": { + "ariaLabel": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fill": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fillOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fontSize": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fx": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fy": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "geometry": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "height": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "href": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "length": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "opacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "path": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "r": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "rotate": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "src": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "stroke": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeWidth": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "symbol": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "text": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "title": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "weight": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "width": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "z": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + } + }, + "type": "object" + }, + "frameAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The frame anchor specifies defaults for **x** and **y** based on the plot’s frame; it may be one of the four sides (*top*, *right*, *bottom*, *left*), one of the four corners (*top-left*, *top-right*, *bottom-right*,\n*bottom-left*), or the *middle* of the frame. For example, for tips distributed horizontally at the top of the frame:\n\n```js Plot.tip(data, {x: \"date\", frameAnchor: \"top\"}) ```" + }, + "lineHeight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line height in ems; defaults to 1. The line height affects the (typically vertical) separation between adjacent baselines of text, as well as the separation between the text and its anchor point." + }, + "lineWidth": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line width in ems (e.g., 10 for about 20 characters); defaults to infinity, disabling wrapping and clipping.\n\nIf **textOverflow** is null, lines will be wrapped at the specified length. If a line is split at a soft hyphen (\\xad), a hyphen (-) will be displayed at the end of the line. If **textOverflow** is not null, lines will be clipped according to the given strategy." + }, + "monospace": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, changes the default **fontFamily** to *monospace*, and uses simplified monospaced text metrics calculations." + }, + "pathFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The image filter for the tip’s box; defaults to a drop shadow." + }, + "pointer": { + "$ref": "#/definitions/TipPointer" + }, + "pointerSize": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The size of the tip’s pointer in pixels; defaults to 12." + }, + "preferredAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If an explicit tip anchor is not specified, an anchor is chosen automatically such that the tip fits within the plot’s frame; if the preferred anchor fits, it is chosen." + }, + "textAnchor": { + "anyOf": [ + { + "const": "start", + "type": "string" + }, + { + "const": "middle", + "type": "string" + }, + { + "const": "end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [text anchor][1] controls how text is aligned (typically horizontally) relative to its anchor point; it is one of *start*, *end*, or *middle*. If the frame anchor is *left*, *top-left*, or *bottom-left*, the default text anchor is *start*; if the frame anchor is *right*, *top-right*, or\n*bottom-right*, the default is *end*; otherwise it is *middle*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/text-anchor" + }, + "textOverflow": { + "anyOf": [ + { + "type": "null" + }, + { + "const": "clip", + "type": "string" + }, + { + "const": "ellipsis", + "type": "string" + }, + { + "const": "clip-start", + "type": "string" + }, + { + "const": "clip-end", + "type": "string" + }, + { + "const": "ellipsis-start", + "type": "string" + }, + { + "const": "ellipsis-middle", + "type": "string" + }, + { + "const": "ellipsis-end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How truncate (or wrap) lines of text longer than the given **lineWidth**; one of:\n\n- null (default) - preserve overflowing characters (and wrap if needed)\n- *clip* or *clip-end* - remove characters from the end\n- *clip-start* - remove characters from the start\n- *ellipsis* or *ellipsis-end* - replace characters from the end with an ellipsis (…)\n- *ellipsis-start* - replace characters from the start with an ellipsis (…)\n- *ellipsis-middle* - replace characters from the middle with an ellipsis (…)\n\nIf no **title** was specified, if text requires truncation, a title containing the non-truncated text will be implicitly added." + }, + "textPadding": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The padding around the text in pixels; defaults to 8." + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + } + }, + "type": "object" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to generate a tooltip for this mark, and any tip options." + }, + "title": { + "$ref": "#/definitions/ChannelValue", + "description": "The title; a channel specifying accessible, short textual descriptions as strings (possibly with newlines). If the tip option is specified, the title will be displayed with an interactive tooltip instead of using the SVG [title element][1].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/title" + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position of the cell; an optional ordinal channel typically bound to the *x* scale. If not specified, the cell spans the horizontal extent of the frame; otherwise the *x* scale must be a *band* scale.\n\nIf *x* represents quantitative or temporal values, use a barX mark instead; if *y* is also quantitative or temporal, use a rect mark." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position of the cell; an optional ordinal channel typically bound to the *y* scale. If not specified, the cell spans the vertical extent of the frame; otherwise the *y* scale must be a *band* scale.\n\nIf *y* represents quantitative or temporal values, use a barY mark instead; if *x* is also quantitative or temporal, use a rect mark." + } + }, + "required": [ + "data", + "mark" + ], + "type": "object" + }, + "CellX": { + "additionalProperties": false, + "description": "The cellX mark.", + "properties": { + "ariaDescription": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-description][1]; a constant textual description.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-description" + }, + "ariaHidden": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-hidden][1] state; a constant indicating whether the element is exposed to an accessibility API.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-hidden" + }, + "ariaLabel": { + "$ref": "#/definitions/ChannelValue", + "description": "The [aria-label][1]; a channel specifying short textual labels representing the value in the accessibility tree.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-label" + }, + "clip": { + "anyOf": [ + { + "const": "frame", + "type": "string" + }, + { + "const": "sphere", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to clip the mark; one of:\n\n- *frame* or true - clip to the plot’s frame (inner area)\n- *sphere* - clip to the projected sphere (*e.g.*, front hemisphere)\n- null or false - do not clip\n\nThe *sphere* clip option requires a geographic projection." + }, + "data": { + "$ref": "#/definitions/PlotMarkData", + "description": "The data source for the mark." + }, + "dx": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The horizontal offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "dy": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The vertical offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "facet": { + "anyOf": [ + { + "const": "auto", + "type": "string" + }, + { + "const": "include", + "type": "string" + }, + { + "const": "exclude", + "type": "string" + }, + { + "const": "super", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to enable or disable faceting; one of:\n\n- *auto* (default) - automatically determine if this mark should be faceted\n- *include* (or true) - draw the subset of the mark’s data in the current facet\n- *exclude* - draw the subset of the mark’s data *not* in the current facet\n- *super* - draw this mark in a single frame that covers all facets\n- null (or false) - repeat this mark’s data across all facets (*i.e.*, no faceting)\n\nWhen a mark uses *super* faceting, it is not allowed to use position scales (*x*, *y*, *fx*, or *fy*); *super* faceting is intended for decorations, such as labels and legends.\n\nWhen top-level faceting is used, the default *auto* setting is equivalent to *include* when the mark data is strictly equal to the top-level facet data; otherwise it is equivalent to null. When the *include* or *exclude* facet mode is chosen, the mark data must be parallel to the top-level facet data: the data must have the same length and order. If the data are not parallel, then the wrong data may be shown in each facet. The default\n*auto* therefore requires strict equality (`===`) for safety, and using the facet data as mark data is recommended when using the *exclude* facet mode. (To construct parallel data safely, consider using [*array*.map][1] on the facet data.)\n\nWhen mark-level faceting is used, the default *auto* setting is equivalent to *include*: the mark will be faceted if either the **fx** or **fy** channel option (or both) is specified. The null or false option will disable faceting, while *exclude* draws the subset of the mark’s data *not* in the current facet.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map" + }, + "facetAnchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "right", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "const": "left", + "type": "string" + }, + { + "const": "top-left", + "type": "string" + }, + { + "const": "top-right", + "type": "string" + }, + { + "const": "bottom-left", + "type": "string" + }, + { + "const": "bottom-right", + "type": "string" + }, + { + "const": "top-empty", + "type": "string" + }, + { + "const": "right-empty", + "type": "string" + }, + { + "const": "bottom-empty", + "type": "string" + }, + { + "const": "left-empty", + "type": "string" + }, + { + "const": "empty", + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to place the mark with respect to facets; one of:\n\n- null (default for most marks) - display the mark in each non-empty facet\n- *top*, *right*, *bottom*, or *left* - display the mark only in facets on the given side\n- *top-empty*, *right-empty*, *bottom-empty*, or *left-empty* (default for axis marks) - display the mark only in facets that have empty space on the given side: either the margin, or an empty facet\n- *empty* - display the mark in empty facets only" + }, + "fill": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill" + }, + "fillOpacity": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill-opacity][1]; a constant number between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill-opacity" + }, + "filter": { + "$ref": "#/definitions/ChannelValue", + "description": "Applies a transform to filter the mark’s index according to the given channel values; only truthy values are retained.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "fx": { + "$ref": "#/definitions/ChannelValue", + "description": "The horizontal facet position channel, for mark-level faceting, bound to the *fx* scale." + }, + "fy": { + "$ref": "#/definitions/ChannelValue", + "description": "The vertical facet position channel, for mark-level faceting, bound to the\n*fy* scale." + }, + "href": { + "$ref": "#/definitions/ChannelValue", + "description": "The [href][1]; a channel specifying URLs for clickable links. May be used in conjunction with the **target** option to open links in another window.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/href" + }, + "imageFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A CSS [filter][1]; a constant string used to adjust the rendering of images, such as *blur(5px)*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/filter" + }, + "inset": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four insets: **insetTop**,\n**insetRight**, **insetBottom**, and **insetLeft**. All insets typically default to zero, though not always (say when using bin transform). A positive inset reduces effective area, while a negative inset increases it." + }, + "insetBottom": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Insets the bottom edge by the specified number of pixels. A positive value insets towards the top edge (reducing effective area), while a negative value insets away from the top edge (increasing it)." + }, + "insetLeft": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Insets the left edge by the specified number of pixels. A positive value insets towards the right edge (reducing effective area), while a negative value insets away from the right edge (increasing it)." + }, + "insetRight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Insets the right edge by the specified number of pixels. A positive value insets towards the left edge (reducing effective area), while a negative value insets away from the left edge (increasing it)." + }, + "insetTop": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Insets the top edge by the specified number of pixels. A positive value insets towards the bottom edge (reducing effective area), while a negative value insets away from the bottom edge (increasing it)." + }, + "margin": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four mark margins: **marginTop**,\n**marginRight**, **marginBottom**, and **marginLeft**; typically defaults to 0, except for axis marks." + }, + "marginBottom": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s bottom margin; the minimum distance in pixels between the bottom edges of the inner and outer plot area." + }, + "marginLeft": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s left margin; the minimum distance in pixels between the left edges of the inner and outer plot area." + }, + "marginRight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s right margin; the minimum distance in pixels between the right edges of the mark’s inner and outer plot area." + }, + "marginTop": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s top margin; the minimum distance in pixels between the top edges of the inner and outer plot area." + }, + "mark": { + "const": "cellX", + "description": "Like cell, but **x** defaults to the zero-based index [0, 1, 2, …], and if\n**stroke** is not a channel, **fill** defaults to the identity function, assuming that *data* = [*x₀*, *x₁*, *x₂*, …].", + "type": "string" + }, + "mixBlendMode": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [mix-blend-mode][1]; a constant string specifying how to blend content such as *multiply*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode" + }, + "opacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally. For faster rendering, prefer the **strokeOpacity** or **fillOpacity** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/opacity" + }, + "paintOrder": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [paint-order][1]; a constant string specifying the order in which the\n**fill**, **stroke**, and any markers are drawn; defaults to *normal*, which draws the fill, then stroke, then markers; defaults to *stroke* for the text mark to create a “halo” around text to improve legibility.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/paint-order" + }, + "pointerEvents": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [pointer-events][1] property; a constant string such as *none*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/pointer-events" + }, + "reverse": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Applies a transform to reverse the order of the mark’s index, say for reverse input order." + }, + "rx": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The rounded corner [*x*-radius][1], either in pixels or as a percentage of the rect width. If **rx** is not specified, it defaults to **ry** if present, and otherwise draws square corners.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/rx" + }, + "ry": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The rounded corner [*y*-radius][1], either in pixels or as a percentage of the rect height. If **ry** is not specified, it defaults to **rx** if present, and otherwise draws square corners.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/ry" + }, + "select": { + "$ref": "#/definitions/SelectFilter", + "description": "Applies a filter transform after data is loaded to highlight selected values only. For example, `first` and `last` select the first or last values of series only (using the *z* channel to separate series). Meanwhile, `nearestX` and `nearestY` select the point nearest to the pointer along the *x* or *y* channel dimension. Unlike Mosaic selections, a mark level *select* is internal to the mark only, and does not populate a param or selection value to be shared across clients.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "shapeRendering": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [shape-rendering][1]; a constant string such as *crispEdges*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/shape-rendering" + }, + "sort": { + "anyOf": [ + { + "$ref": "#/definitions/SortOrder" + }, + { + "$ref": "#/definitions/ChannelDomainSort" + } + ], + "description": "Either applies a transform to sort the mark’s index by the specified channel values, or imputes ordinal scale domains from this mark’s channels.\n\nWhen imputing ordinal scale domains from channel values, the **sort** option is an object whose keys are ordinal scale names such as *x* or *fx*, and whose values are channel names such as *y*, *y1*, or *y2*. For example, to impute the *y* scale’s domain from the associated *x* channel values in ascending order:\n\n```js sort: {y: \"x\"} ```\n\nFor different sort options for different scales, replace the channel name with a *value* object and per-scale options:\n\n```js sort: {y: {value: \"-x\"}} ```\n\nWhen sorting the mark’s index, the **sort** option is instead one of:\n\n- a channel value definition for sorting given values in ascending order\n- a {value, order} object for sorting given values\n- a {channel, order} object for sorting the named channel’s values" + }, + "stroke": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke" + }, + "strokeDasharray": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dasharray][1]; a constant number indicating the length in pixels of alternating dashes and gaps, or a constant string of numbers separated by spaces or commas (_e.g._, *10 2* for dashes of 10 pixels separated by gaps of 2 pixels), or *none* (the default) for no dashing\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dasharray" + }, + "strokeDashoffset": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dashoffset][1]; a constant indicating the offset in pixels of the first dash along the stroke; defaults to zero.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dashoffset" + }, + "strokeLinecap": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linecap][1]; a constant specifying how to cap stroked paths, such as *butt*, *round*, or *square*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linecap" + }, + "strokeLinejoin": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linejoin][1]; a constant specifying how to join stroked paths, such as *bevel*, *miter*, *miter-clip*, or *round*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linejoin" + }, + "strokeMiterlimit": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-miterlimit][1]; a constant number specifying how to limit the length of *miter* joins on stroked paths.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-miterlimit" + }, + "strokeOpacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-opacity" + }, + "strokeWidth": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-width][1]; a constant number in pixels, or a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-width" + }, + "target": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [target][1]; a constant string specifying the target window (_e.g._,\n*_blank*) for clickable links; used in conjunction with the **href** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/target" + }, + "tip": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/TipPointer" + }, + { + "properties": { + "anchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The tip anchor specifies how to orient the tip box relative to its anchor position; it refers to the part of the tip box that is attached to the anchor point. For example, the *top-left* anchor places the top-left corner of tip box near the anchor position, hence placing the tip box below and to the right of the anchor position." + }, + "fontFamily": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font-family][1]; a constant; defaults to the plot’s font family, which is typically [*system-ui*][2].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-family [2]: https://drafts.csswg.org/css-fonts-4/#valdef-font-family-system-ui" + }, + "fontSize": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font size][1] in pixels; either a constant or a channel; defaults to the plot’s font size, which is typically 10. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-size" + }, + "fontStyle": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font style][1]; a constant; defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-style" + }, + "fontVariant": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font variant][1]; a constant; if the **text** channel contains numbers or dates, defaults to *tabular-nums* to facilitate comparing numbers; otherwise defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant" + }, + "fontWeight": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font weight][1]; a constant; defaults to the plot’s font weight, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight" + }, + "format": { + "additionalProperties": false, + "description": "How channel values are formatted for display. If a format is a string, it is interpreted as a (UTC) time format for temporal channels, and otherwise a number format.", + "properties": { + "ariaLabel": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fill": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fillOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fontSize": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fx": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fy": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "geometry": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "height": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "href": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "length": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "opacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "path": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "r": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "rotate": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "src": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "stroke": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeWidth": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "symbol": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "text": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "title": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "weight": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "width": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "z": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + } + }, + "type": "object" + }, + "frameAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The frame anchor specifies defaults for **x** and **y** based on the plot’s frame; it may be one of the four sides (*top*, *right*, *bottom*, *left*), one of the four corners (*top-left*, *top-right*, *bottom-right*,\n*bottom-left*), or the *middle* of the frame. For example, for tips distributed horizontally at the top of the frame:\n\n```js Plot.tip(data, {x: \"date\", frameAnchor: \"top\"}) ```" + }, + "lineHeight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line height in ems; defaults to 1. The line height affects the (typically vertical) separation between adjacent baselines of text, as well as the separation between the text and its anchor point." + }, + "lineWidth": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line width in ems (e.g., 10 for about 20 characters); defaults to infinity, disabling wrapping and clipping.\n\nIf **textOverflow** is null, lines will be wrapped at the specified length. If a line is split at a soft hyphen (\\xad), a hyphen (-) will be displayed at the end of the line. If **textOverflow** is not null, lines will be clipped according to the given strategy." + }, + "monospace": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, changes the default **fontFamily** to *monospace*, and uses simplified monospaced text metrics calculations." + }, + "pathFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The image filter for the tip’s box; defaults to a drop shadow." + }, + "pointer": { + "$ref": "#/definitions/TipPointer" + }, + "pointerSize": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The size of the tip’s pointer in pixels; defaults to 12." + }, + "preferredAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If an explicit tip anchor is not specified, an anchor is chosen automatically such that the tip fits within the plot’s frame; if the preferred anchor fits, it is chosen." + }, + "textAnchor": { + "anyOf": [ + { + "const": "start", + "type": "string" + }, + { + "const": "middle", + "type": "string" + }, + { + "const": "end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [text anchor][1] controls how text is aligned (typically horizontally) relative to its anchor point; it is one of *start*, *end*, or *middle*. If the frame anchor is *left*, *top-left*, or *bottom-left*, the default text anchor is *start*; if the frame anchor is *right*, *top-right*, or\n*bottom-right*, the default is *end*; otherwise it is *middle*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/text-anchor" + }, + "textOverflow": { + "anyOf": [ + { + "type": "null" + }, + { + "const": "clip", + "type": "string" + }, + { + "const": "ellipsis", + "type": "string" + }, + { + "const": "clip-start", + "type": "string" + }, + { + "const": "clip-end", + "type": "string" + }, + { + "const": "ellipsis-start", + "type": "string" + }, + { + "const": "ellipsis-middle", + "type": "string" + }, + { + "const": "ellipsis-end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How truncate (or wrap) lines of text longer than the given **lineWidth**; one of:\n\n- null (default) - preserve overflowing characters (and wrap if needed)\n- *clip* or *clip-end* - remove characters from the end\n- *clip-start* - remove characters from the start\n- *ellipsis* or *ellipsis-end* - replace characters from the end with an ellipsis (…)\n- *ellipsis-start* - replace characters from the start with an ellipsis (…)\n- *ellipsis-middle* - replace characters from the middle with an ellipsis (…)\n\nIf no **title** was specified, if text requires truncation, a title containing the non-truncated text will be implicitly added." + }, + "textPadding": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The padding around the text in pixels; defaults to 8." + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + } + }, + "type": "object" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to generate a tooltip for this mark, and any tip options." + }, + "title": { + "$ref": "#/definitions/ChannelValue", + "description": "The title; a channel specifying accessible, short textual descriptions as strings (possibly with newlines). If the tip option is specified, the title will be displayed with an interactive tooltip instead of using the SVG [title element][1].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/title" + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position of the cell; an optional ordinal channel typically bound to the *x* scale. If not specified, the cell spans the horizontal extent of the frame; otherwise the *x* scale must be a *band* scale.\n\nIf *x* represents quantitative or temporal values, use a barX mark instead; if *y* is also quantitative or temporal, use a rect mark." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position of the cell; an optional ordinal channel typically bound to the *y* scale. If not specified, the cell spans the vertical extent of the frame; otherwise the *y* scale must be a *band* scale.\n\nIf *y* represents quantitative or temporal values, use a barY mark instead; if *x* is also quantitative or temporal, use a rect mark." + } + }, + "required": [ + "data", + "mark" + ], + "type": "object" + }, + "CellY": { + "additionalProperties": false, + "description": "The cellY mark.", + "properties": { + "ariaDescription": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-description][1]; a constant textual description.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-description" + }, + "ariaHidden": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-hidden][1] state; a constant indicating whether the element is exposed to an accessibility API.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-hidden" + }, + "ariaLabel": { + "$ref": "#/definitions/ChannelValue", + "description": "The [aria-label][1]; a channel specifying short textual labels representing the value in the accessibility tree.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-label" + }, + "clip": { + "anyOf": [ + { + "const": "frame", + "type": "string" + }, + { + "const": "sphere", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to clip the mark; one of:\n\n- *frame* or true - clip to the plot’s frame (inner area)\n- *sphere* - clip to the projected sphere (*e.g.*, front hemisphere)\n- null or false - do not clip\n\nThe *sphere* clip option requires a geographic projection." + }, + "data": { + "$ref": "#/definitions/PlotMarkData", + "description": "The data source for the mark." + }, + "dx": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The horizontal offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "dy": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The vertical offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "facet": { + "anyOf": [ + { + "const": "auto", + "type": "string" + }, + { + "const": "include", + "type": "string" + }, + { + "const": "exclude", + "type": "string" + }, + { + "const": "super", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to enable or disable faceting; one of:\n\n- *auto* (default) - automatically determine if this mark should be faceted\n- *include* (or true) - draw the subset of the mark’s data in the current facet\n- *exclude* - draw the subset of the mark’s data *not* in the current facet\n- *super* - draw this mark in a single frame that covers all facets\n- null (or false) - repeat this mark’s data across all facets (*i.e.*, no faceting)\n\nWhen a mark uses *super* faceting, it is not allowed to use position scales (*x*, *y*, *fx*, or *fy*); *super* faceting is intended for decorations, such as labels and legends.\n\nWhen top-level faceting is used, the default *auto* setting is equivalent to *include* when the mark data is strictly equal to the top-level facet data; otherwise it is equivalent to null. When the *include* or *exclude* facet mode is chosen, the mark data must be parallel to the top-level facet data: the data must have the same length and order. If the data are not parallel, then the wrong data may be shown in each facet. The default\n*auto* therefore requires strict equality (`===`) for safety, and using the facet data as mark data is recommended when using the *exclude* facet mode. (To construct parallel data safely, consider using [*array*.map][1] on the facet data.)\n\nWhen mark-level faceting is used, the default *auto* setting is equivalent to *include*: the mark will be faceted if either the **fx** or **fy** channel option (or both) is specified. The null or false option will disable faceting, while *exclude* draws the subset of the mark’s data *not* in the current facet.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map" + }, + "facetAnchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "right", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "const": "left", + "type": "string" + }, + { + "const": "top-left", + "type": "string" + }, + { + "const": "top-right", + "type": "string" + }, + { + "const": "bottom-left", + "type": "string" + }, + { + "const": "bottom-right", + "type": "string" + }, + { + "const": "top-empty", + "type": "string" + }, + { + "const": "right-empty", + "type": "string" + }, + { + "const": "bottom-empty", + "type": "string" + }, + { + "const": "left-empty", + "type": "string" + }, + { + "const": "empty", + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to place the mark with respect to facets; one of:\n\n- null (default for most marks) - display the mark in each non-empty facet\n- *top*, *right*, *bottom*, or *left* - display the mark only in facets on the given side\n- *top-empty*, *right-empty*, *bottom-empty*, or *left-empty* (default for axis marks) - display the mark only in facets that have empty space on the given side: either the margin, or an empty facet\n- *empty* - display the mark in empty facets only" + }, + "fill": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill" + }, + "fillOpacity": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill-opacity][1]; a constant number between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill-opacity" + }, + "filter": { + "$ref": "#/definitions/ChannelValue", + "description": "Applies a transform to filter the mark’s index according to the given channel values; only truthy values are retained.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "fx": { + "$ref": "#/definitions/ChannelValue", + "description": "The horizontal facet position channel, for mark-level faceting, bound to the *fx* scale." + }, + "fy": { + "$ref": "#/definitions/ChannelValue", + "description": "The vertical facet position channel, for mark-level faceting, bound to the\n*fy* scale." + }, + "href": { + "$ref": "#/definitions/ChannelValue", + "description": "The [href][1]; a channel specifying URLs for clickable links. May be used in conjunction with the **target** option to open links in another window.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/href" + }, + "imageFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A CSS [filter][1]; a constant string used to adjust the rendering of images, such as *blur(5px)*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/filter" + }, + "inset": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four insets: **insetTop**,\n**insetRight**, **insetBottom**, and **insetLeft**. All insets typically default to zero, though not always (say when using bin transform). A positive inset reduces effective area, while a negative inset increases it." + }, + "insetBottom": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Insets the bottom edge by the specified number of pixels. A positive value insets towards the top edge (reducing effective area), while a negative value insets away from the top edge (increasing it)." + }, + "insetLeft": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Insets the left edge by the specified number of pixels. A positive value insets towards the right edge (reducing effective area), while a negative value insets away from the right edge (increasing it)." + }, + "insetRight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Insets the right edge by the specified number of pixels. A positive value insets towards the left edge (reducing effective area), while a negative value insets away from the left edge (increasing it)." + }, + "insetTop": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Insets the top edge by the specified number of pixels. A positive value insets towards the bottom edge (reducing effective area), while a negative value insets away from the bottom edge (increasing it)." + }, + "margin": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four mark margins: **marginTop**,\n**marginRight**, **marginBottom**, and **marginLeft**; typically defaults to 0, except for axis marks." + }, + "marginBottom": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s bottom margin; the minimum distance in pixels between the bottom edges of the inner and outer plot area." + }, + "marginLeft": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s left margin; the minimum distance in pixels between the left edges of the inner and outer plot area." + }, + "marginRight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s right margin; the minimum distance in pixels between the right edges of the mark’s inner and outer plot area." + }, + "marginTop": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s top margin; the minimum distance in pixels between the top edges of the inner and outer plot area." + }, + "mark": { + "const": "cellY", + "description": "Like cell, but **y** defaults to the zero-based index [0, 1, 2, …], and if\n**stroke** is not a channel, **fill** defaults to the identity function, assuming that *data* = [*y₀*, *y₁*, *y₂*, …].", + "type": "string" + }, + "mixBlendMode": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [mix-blend-mode][1]; a constant string specifying how to blend content such as *multiply*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode" + }, + "opacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally. For faster rendering, prefer the **strokeOpacity** or **fillOpacity** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/opacity" + }, + "paintOrder": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [paint-order][1]; a constant string specifying the order in which the\n**fill**, **stroke**, and any markers are drawn; defaults to *normal*, which draws the fill, then stroke, then markers; defaults to *stroke* for the text mark to create a “halo” around text to improve legibility.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/paint-order" + }, + "pointerEvents": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [pointer-events][1] property; a constant string such as *none*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/pointer-events" + }, + "reverse": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Applies a transform to reverse the order of the mark’s index, say for reverse input order." + }, + "rx": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The rounded corner [*x*-radius][1], either in pixels or as a percentage of the rect width. If **rx** is not specified, it defaults to **ry** if present, and otherwise draws square corners.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/rx" + }, + "ry": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The rounded corner [*y*-radius][1], either in pixels or as a percentage of the rect height. If **ry** is not specified, it defaults to **rx** if present, and otherwise draws square corners.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/ry" + }, + "select": { + "$ref": "#/definitions/SelectFilter", + "description": "Applies a filter transform after data is loaded to highlight selected values only. For example, `first` and `last` select the first or last values of series only (using the *z* channel to separate series). Meanwhile, `nearestX` and `nearestY` select the point nearest to the pointer along the *x* or *y* channel dimension. Unlike Mosaic selections, a mark level *select* is internal to the mark only, and does not populate a param or selection value to be shared across clients.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "shapeRendering": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [shape-rendering][1]; a constant string such as *crispEdges*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/shape-rendering" + }, + "sort": { + "anyOf": [ + { + "$ref": "#/definitions/SortOrder" + }, + { + "$ref": "#/definitions/ChannelDomainSort" + } + ], + "description": "Either applies a transform to sort the mark’s index by the specified channel values, or imputes ordinal scale domains from this mark’s channels.\n\nWhen imputing ordinal scale domains from channel values, the **sort** option is an object whose keys are ordinal scale names such as *x* or *fx*, and whose values are channel names such as *y*, *y1*, or *y2*. For example, to impute the *y* scale’s domain from the associated *x* channel values in ascending order:\n\n```js sort: {y: \"x\"} ```\n\nFor different sort options for different scales, replace the channel name with a *value* object and per-scale options:\n\n```js sort: {y: {value: \"-x\"}} ```\n\nWhen sorting the mark’s index, the **sort** option is instead one of:\n\n- a channel value definition for sorting given values in ascending order\n- a {value, order} object for sorting given values\n- a {channel, order} object for sorting the named channel’s values" + }, + "stroke": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke" + }, + "strokeDasharray": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dasharray][1]; a constant number indicating the length in pixels of alternating dashes and gaps, or a constant string of numbers separated by spaces or commas (_e.g._, *10 2* for dashes of 10 pixels separated by gaps of 2 pixels), or *none* (the default) for no dashing\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dasharray" + }, + "strokeDashoffset": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dashoffset][1]; a constant indicating the offset in pixels of the first dash along the stroke; defaults to zero.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dashoffset" + }, + "strokeLinecap": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linecap][1]; a constant specifying how to cap stroked paths, such as *butt*, *round*, or *square*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linecap" + }, + "strokeLinejoin": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linejoin][1]; a constant specifying how to join stroked paths, such as *bevel*, *miter*, *miter-clip*, or *round*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linejoin" + }, + "strokeMiterlimit": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-miterlimit][1]; a constant number specifying how to limit the length of *miter* joins on stroked paths.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-miterlimit" + }, + "strokeOpacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-opacity" + }, + "strokeWidth": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-width][1]; a constant number in pixels, or a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-width" + }, + "target": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [target][1]; a constant string specifying the target window (_e.g._,\n*_blank*) for clickable links; used in conjunction with the **href** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/target" + }, + "tip": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/TipPointer" + }, + { + "properties": { + "anchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The tip anchor specifies how to orient the tip box relative to its anchor position; it refers to the part of the tip box that is attached to the anchor point. For example, the *top-left* anchor places the top-left corner of tip box near the anchor position, hence placing the tip box below and to the right of the anchor position." + }, + "fontFamily": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font-family][1]; a constant; defaults to the plot’s font family, which is typically [*system-ui*][2].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-family [2]: https://drafts.csswg.org/css-fonts-4/#valdef-font-family-system-ui" + }, + "fontSize": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font size][1] in pixels; either a constant or a channel; defaults to the plot’s font size, which is typically 10. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-size" + }, + "fontStyle": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font style][1]; a constant; defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-style" + }, + "fontVariant": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font variant][1]; a constant; if the **text** channel contains numbers or dates, defaults to *tabular-nums* to facilitate comparing numbers; otherwise defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant" + }, + "fontWeight": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font weight][1]; a constant; defaults to the plot’s font weight, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight" + }, + "format": { + "additionalProperties": false, + "description": "How channel values are formatted for display. If a format is a string, it is interpreted as a (UTC) time format for temporal channels, and otherwise a number format.", + "properties": { + "ariaLabel": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fill": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fillOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fontSize": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fx": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fy": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "geometry": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "height": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "href": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "length": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "opacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "path": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "r": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "rotate": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "src": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "stroke": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeWidth": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "symbol": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "text": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "title": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "weight": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "width": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "z": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + } + }, + "type": "object" + }, + "frameAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The frame anchor specifies defaults for **x** and **y** based on the plot’s frame; it may be one of the four sides (*top*, *right*, *bottom*, *left*), one of the four corners (*top-left*, *top-right*, *bottom-right*,\n*bottom-left*), or the *middle* of the frame. For example, for tips distributed horizontally at the top of the frame:\n\n```js Plot.tip(data, {x: \"date\", frameAnchor: \"top\"}) ```" + }, + "lineHeight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line height in ems; defaults to 1. The line height affects the (typically vertical) separation between adjacent baselines of text, as well as the separation between the text and its anchor point." + }, + "lineWidth": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line width in ems (e.g., 10 for about 20 characters); defaults to infinity, disabling wrapping and clipping.\n\nIf **textOverflow** is null, lines will be wrapped at the specified length. If a line is split at a soft hyphen (\\xad), a hyphen (-) will be displayed at the end of the line. If **textOverflow** is not null, lines will be clipped according to the given strategy." + }, + "monospace": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, changes the default **fontFamily** to *monospace*, and uses simplified monospaced text metrics calculations." + }, + "pathFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The image filter for the tip’s box; defaults to a drop shadow." + }, + "pointer": { + "$ref": "#/definitions/TipPointer" + }, + "pointerSize": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The size of the tip’s pointer in pixels; defaults to 12." + }, + "preferredAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If an explicit tip anchor is not specified, an anchor is chosen automatically such that the tip fits within the plot’s frame; if the preferred anchor fits, it is chosen." + }, + "textAnchor": { + "anyOf": [ + { + "const": "start", + "type": "string" + }, + { + "const": "middle", + "type": "string" + }, + { + "const": "end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [text anchor][1] controls how text is aligned (typically horizontally) relative to its anchor point; it is one of *start*, *end*, or *middle*. If the frame anchor is *left*, *top-left*, or *bottom-left*, the default text anchor is *start*; if the frame anchor is *right*, *top-right*, or\n*bottom-right*, the default is *end*; otherwise it is *middle*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/text-anchor" + }, + "textOverflow": { + "anyOf": [ + { + "type": "null" + }, + { + "const": "clip", + "type": "string" + }, + { + "const": "ellipsis", + "type": "string" + }, + { + "const": "clip-start", + "type": "string" + }, + { + "const": "clip-end", + "type": "string" + }, + { + "const": "ellipsis-start", + "type": "string" + }, + { + "const": "ellipsis-middle", + "type": "string" + }, + { + "const": "ellipsis-end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How truncate (or wrap) lines of text longer than the given **lineWidth**; one of:\n\n- null (default) - preserve overflowing characters (and wrap if needed)\n- *clip* or *clip-end* - remove characters from the end\n- *clip-start* - remove characters from the start\n- *ellipsis* or *ellipsis-end* - replace characters from the end with an ellipsis (…)\n- *ellipsis-start* - replace characters from the start with an ellipsis (…)\n- *ellipsis-middle* - replace characters from the middle with an ellipsis (…)\n\nIf no **title** was specified, if text requires truncation, a title containing the non-truncated text will be implicitly added." + }, + "textPadding": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The padding around the text in pixels; defaults to 8." + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + } + }, + "type": "object" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to generate a tooltip for this mark, and any tip options." + }, + "title": { + "$ref": "#/definitions/ChannelValue", + "description": "The title; a channel specifying accessible, short textual descriptions as strings (possibly with newlines). If the tip option is specified, the title will be displayed with an interactive tooltip instead of using the SVG [title element][1].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/title" + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position of the cell; an optional ordinal channel typically bound to the *x* scale. If not specified, the cell spans the horizontal extent of the frame; otherwise the *x* scale must be a *band* scale.\n\nIf *x* represents quantitative or temporal values, use a barX mark instead; if *y* is also quantitative or temporal, use a rect mark." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position of the cell; an optional ordinal channel typically bound to the *y* scale. If not specified, the cell spans the vertical extent of the frame; otherwise the *y* scale must be a *band* scale.\n\nIf *y* represents quantitative or temporal values, use a barY mark instead; if *x* is also quantitative or temporal, use a rect mark." + } + }, + "required": [ + "data", + "mark" + ], + "type": "object" + }, + "Centroid": { + "additionalProperties": false, + "properties": { + "centroid": { + "anyOf": [ + { + "description": "A transform argument.", + "type": [ + "string", + "number", + "boolean" + ] + }, + { + "items": { + "description": "A transform argument.", + "type": [ + "string", + "number", + "boolean" + ] + }, + "maxItems": 1, + "minItems": 1, + "type": "array" + } + ], + "description": "Compute the 2D centroid of geometry-typed data. This transform requires the DuckDB `spatial` extension." + } + }, + "required": [ + "centroid" + ], + "type": "object" + }, + "CentroidX": { + "additionalProperties": false, + "properties": { + "centroidX": { + "anyOf": [ + { + "description": "A transform argument.", + "type": [ + "string", + "number", + "boolean" + ] + }, + { + "items": { + "description": "A transform argument.", + "type": [ + "string", + "number", + "boolean" + ] + }, + "maxItems": 1, + "minItems": 1, + "type": "array" + } + ], + "description": "Compute the centroid x-coordinate of geometry-typed data. This transform requires the DuckDB `spatial` extension." + } + }, + "required": [ + "centroidX" + ], + "type": "object" + }, + "CentroidY": { + "additionalProperties": false, + "properties": { + "centroidY": { + "anyOf": [ + { + "description": "A transform argument.", + "type": [ + "string", + "number", + "boolean" + ] + }, + { + "items": { + "description": "A transform argument.", + "type": [ + "string", + "number", + "boolean" + ] + }, + "maxItems": 1, + "minItems": 1, + "type": "array" + } + ], + "description": "Compute the centroid y-coordinate of geometry-typed data. This transform requires the DuckDB `spatial` extension." + } + }, + "required": [ + "centroidY" + ], + "type": "object" + }, + "ChannelDomainSort": { + "additionalProperties": false, + "description": "How to impute scale domains from channel values.", + "properties": { + "color": { + "$ref": "#/definitions/ChannelDomainValueSpec" + }, + "fx": { + "$ref": "#/definitions/ChannelDomainValueSpec" + }, + "fy": { + "$ref": "#/definitions/ChannelDomainValueSpec" + }, + "length": { + "$ref": "#/definitions/ChannelDomainValueSpec" + }, + "limit": { + "anyOf": [ + { + "type": "number" + }, + { + "items": [ + { + "title": "lo", + "type": "number" + }, + { + "title": "hi", + "type": "number" + } + ], + "maxItems": 2, + "minItems": 2, + "type": "array" + } + ], + "description": "If a positive number, limit the domain to the first *n* sorted values. If a negative number, limit the domain to the last *-n* sorted values. Hence, a positive **limit** with **reverse** true will return the top *n* values in descending order.\n\nIf an array [*lo*, *hi*], slices the sorted domain from *lo* (inclusive) to\n*hi* (exclusive). As with [*array*.slice][1], if either *lo* or *hi* are negative, it indicates an offset from the end of the array; if *lo* is undefined it defaults to 0, and if *hi* is undefined it defaults to Infinity.\n\nNote: limiting the imputed domain of one scale, say *x*, does not affect the imputed domain of another scale, say *y*; each scale domain is imputed independently.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/slice" + }, + "opacity": { + "$ref": "#/definitions/ChannelDomainValueSpec" + }, + "order": { + "description": "How to order reduced values.", + "enum": [ + "ascending", + "descending", + null + ], + "type": [ + "string", + "null" + ] + }, + "r": { + "$ref": "#/definitions/ChannelDomainValueSpec" + }, + "reduce": { + "anyOf": [ + { + "$ref": "#/definitions/Reducer" + }, + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "How to produce a singular value (for subsequent sorting) from aggregated channel values; one of:\n\n- true (default) - alias for *max*\n- false or null - disabled; don’t impute the scale domain\n- a named reducer implementation such as *count* or *sum*\n- a function that takes an array of values and returns the reduced value\n- an object that implements the *reduceIndex* method" + }, + "reverse": { + "description": "If true, reverse the order after sorting.", + "type": "boolean" + }, + "symbol": { + "$ref": "#/definitions/ChannelDomainValueSpec" + }, + "x": { + "$ref": "#/definitions/ChannelDomainValueSpec" + }, + "y": { + "$ref": "#/definitions/ChannelDomainValueSpec" + } + }, + "type": "object" + }, + "ChannelDomainValue": { + "anyOf": [ + { + "anyOf": [ + { + "$ref": "#/definitions/ChannelName" + }, + { + "const": "data", + "type": "string" + }, + { + "const": "width", + "type": "string" + }, + { + "const": "height", + "type": "string" + } + ], + "description": "A channel name, or an implied one for domain sorting." + }, + { + "const": "-ariaLabel", + "type": "string" + }, + { + "const": "-fill", + "type": "string" + }, + { + "const": "-fillOpacity", + "type": "string" + }, + { + "const": "-fontSize", + "type": "string" + }, + { + "const": "-fx", + "type": "string" + }, + { + "const": "-fy", + "type": "string" + }, + { + "const": "-geometry", + "type": "string" + }, + { + "const": "-height", + "type": "string" + }, + { + "const": "-href", + "type": "string" + }, + { + "const": "-length", + "type": "string" + }, + { + "const": "-opacity", + "type": "string" + }, + { + "const": "-path", + "type": "string" + }, + { + "const": "-r", + "type": "string" + }, + { + "const": "-rotate", + "type": "string" + }, + { + "const": "-src", + "type": "string" + }, + { + "const": "-stroke", + "type": "string" + }, + { + "const": "-strokeOpacity", + "type": "string" + }, + { + "const": "-strokeWidth", + "type": "string" + }, + { + "const": "-symbol", + "type": "string" + }, + { + "const": "-text", + "type": "string" + }, + { + "const": "-title", + "type": "string" + }, + { + "const": "-weight", + "type": "string" + }, + { + "const": "-width", + "type": "string" + }, + { + "const": "-x", + "type": "string" + }, + { + "const": "-x1", + "type": "string" + }, + { + "const": "-x2", + "type": "string" + }, + { + "const": "-y", + "type": "string" + }, + { + "const": "-y1", + "type": "string" + }, + { + "const": "-y2", + "type": "string" + }, + { + "const": "-z", + "type": "string" + }, + { + "const": "-data", + "type": "string" + }, + { + "type": "null" + } + ], + "description": "The available inputs for imputing scale domains. In addition to a named channel, an input may be specified as:\n\n- *data* - impute from mark data\n- *width* - impute from |*x2* - *x1*|\n- *height* - impute from |*y2* - *y1*|\n- null - impute from input order\n\nIf the *x* channel is not defined, the *x2* channel will be used instead if available, and similarly for *y* and *y2*; this is useful for marks that implicitly stack. The *data* input is typically used in conjunction with a custom **reduce** function, as when the built-in single-channel reducers are insufficient." + }, + "ChannelDomainValueSpec": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelDomainValue" + }, + { + "additionalProperties": false, + "properties": { + "limit": { + "anyOf": [ + { + "type": "number" + }, + { + "items": [ + { + "title": "lo", + "type": "number" + }, + { + "title": "hi", + "type": "number" + } + ], + "maxItems": 2, + "minItems": 2, + "type": "array" + } + ], + "description": "If a positive number, limit the domain to the first *n* sorted values. If a negative number, limit the domain to the last *-n* sorted values. Hence, a positive **limit** with **reverse** true will return the top *n* values in descending order.\n\nIf an array [*lo*, *hi*], slices the sorted domain from *lo* (inclusive) to\n*hi* (exclusive). As with [*array*.slice][1], if either *lo* or *hi* are negative, it indicates an offset from the end of the array; if *lo* is undefined it defaults to 0, and if *hi* is undefined it defaults to Infinity.\n\nNote: limiting the imputed domain of one scale, say *x*, does not affect the imputed domain of another scale, say *y*; each scale domain is imputed independently.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/slice" + }, + "order": { + "description": "How to order reduced values.", + "enum": [ + "ascending", + "descending", + null + ], + "type": [ + "string", + "null" + ] + }, + "reduce": { + "anyOf": [ + { + "$ref": "#/definitions/Reducer" + }, + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "description": "How to produce a singular value (for subsequent sorting) from aggregated channel values; one of:\n\n- true (default) - alias for *max*\n- false or null - disabled; don’t impute the scale domain\n- a named reducer implementation such as *count* or *sum*\n- a function that takes an array of values and returns the reduced value\n- an object that implements the *reduceIndex* method" + }, + "reverse": { + "description": "If true, reverse the order after sorting.", + "type": "boolean" + }, + "value": { + "$ref": "#/definitions/ChannelDomainValue" + } + }, + "required": [ + "value" + ], + "type": "object" + } + ], + "description": "How to derive a scale’s domain from a channel’s values." + }, + "ChannelName": { + "description": "The set of known channel names.", + "enum": [ + "ariaLabel", + "fill", + "fillOpacity", + "fontSize", + "fx", + "fy", + "geometry", + "height", + "href", + "length", + "opacity", + "path", + "r", + "rotate", + "src", + "stroke", + "strokeOpacity", + "strokeWidth", + "symbol", + "text", + "title", + "weight", + "width", + "x", + "x1", + "x2", + "y", + "y1", + "y2", + "z" + ], + "type": "string" + }, + "ChannelValue": { + "anyOf": [ + { + "items": {}, + "type": "array" + }, + { + "type": "string" + }, + { + "type": "number" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/Transform" + }, + { + "$ref": "#/definitions/SQLExpression" + }, + { + "$ref": "#/definitions/AggregateExpression" + } + ], + "description": "A channel’s values may be expressed as:\n\n- a field name, to extract the corresponding value for each datum\n- an iterable of values, typically of the same length as the data\n- a channel transform or SQL expression\n- a constant number or boolean\n- null to represent no value" + }, + "ChannelValueIntervalSpec": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "additionalProperties": false, + "properties": { + "interval": { + "$ref": "#/definitions/Interval" + }, + "value": { + "$ref": "#/definitions/ChannelValue" + } + }, + "required": [ + "value", + "interval" + ], + "type": "object" + } + ], + "description": "In some contexts, when specifying a mark channel’s value, you can provide a {value, interval} object to specify an associated interval." + }, + "ChannelValueSpec": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "additionalProperties": false, + "properties": { + "label": { + "type": "string" + }, + "scale": { + "anyOf": [ + { + "$ref": "#/definitions/ScaleName" + }, + { + "const": "auto", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + } + ] + }, + "value": { + "$ref": "#/definitions/ChannelValue" + } + }, + "required": [ + "value" + ], + "type": "object" + } + ], + "description": "When specifying a mark channel’s value, you can provide a {value, scale} object to override the scale that would normally be associated with the channel." + }, + "Circle": { + "additionalProperties": false, + "description": "The circle mark.", + "properties": { + "ariaDescription": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-description][1]; a constant textual description.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-description" + }, + "ariaHidden": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-hidden][1] state; a constant indicating whether the element is exposed to an accessibility API.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-hidden" + }, + "ariaLabel": { + "$ref": "#/definitions/ChannelValue", + "description": "The [aria-label][1]; a channel specifying short textual labels representing the value in the accessibility tree.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-label" + }, + "clip": { + "anyOf": [ + { + "const": "frame", + "type": "string" + }, + { + "const": "sphere", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to clip the mark; one of:\n\n- *frame* or true - clip to the plot’s frame (inner area)\n- *sphere* - clip to the projected sphere (*e.g.*, front hemisphere)\n- null or false - do not clip\n\nThe *sphere* clip option requires a geographic projection." + }, + "data": { + "$ref": "#/definitions/PlotMarkData", + "description": "The data source for the mark." + }, + "dx": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The horizontal offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "dy": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The vertical offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "facet": { + "anyOf": [ + { + "const": "auto", + "type": "string" + }, + { + "const": "include", + "type": "string" + }, + { + "const": "exclude", + "type": "string" + }, + { + "const": "super", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to enable or disable faceting; one of:\n\n- *auto* (default) - automatically determine if this mark should be faceted\n- *include* (or true) - draw the subset of the mark’s data in the current facet\n- *exclude* - draw the subset of the mark’s data *not* in the current facet\n- *super* - draw this mark in a single frame that covers all facets\n- null (or false) - repeat this mark’s data across all facets (*i.e.*, no faceting)\n\nWhen a mark uses *super* faceting, it is not allowed to use position scales (*x*, *y*, *fx*, or *fy*); *super* faceting is intended for decorations, such as labels and legends.\n\nWhen top-level faceting is used, the default *auto* setting is equivalent to *include* when the mark data is strictly equal to the top-level facet data; otherwise it is equivalent to null. When the *include* or *exclude* facet mode is chosen, the mark data must be parallel to the top-level facet data: the data must have the same length and order. If the data are not parallel, then the wrong data may be shown in each facet. The default\n*auto* therefore requires strict equality (`===`) for safety, and using the facet data as mark data is recommended when using the *exclude* facet mode. (To construct parallel data safely, consider using [*array*.map][1] on the facet data.)\n\nWhen mark-level faceting is used, the default *auto* setting is equivalent to *include*: the mark will be faceted if either the **fx** or **fy** channel option (or both) is specified. The null or false option will disable faceting, while *exclude* draws the subset of the mark’s data *not* in the current facet.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map" + }, + "facetAnchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "right", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "const": "left", + "type": "string" + }, + { + "const": "top-left", + "type": "string" + }, + { + "const": "top-right", + "type": "string" + }, + { + "const": "bottom-left", + "type": "string" + }, + { + "const": "bottom-right", + "type": "string" + }, + { + "const": "top-empty", + "type": "string" + }, + { + "const": "right-empty", + "type": "string" + }, + { + "const": "bottom-empty", + "type": "string" + }, + { + "const": "left-empty", + "type": "string" + }, + { + "const": "empty", + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to place the mark with respect to facets; one of:\n\n- null (default for most marks) - display the mark in each non-empty facet\n- *top*, *right*, *bottom*, or *left* - display the mark only in facets on the given side\n- *top-empty*, *right-empty*, *bottom-empty*, or *left-empty* (default for axis marks) - display the mark only in facets that have empty space on the given side: either the margin, or an empty facet\n- *empty* - display the mark in empty facets only" + }, + "fill": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill" + }, + "fillOpacity": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill-opacity][1]; a constant number between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill-opacity" + }, + "filter": { + "$ref": "#/definitions/ChannelValue", + "description": "Applies a transform to filter the mark’s index according to the given channel values; only truthy values are retained.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "frameAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The frame anchor specifies defaults for **x** and **y** based on the plot’s frame; it may be one of the four sides (*top*, *right*, *bottom*, *left*), one of the four corners (*top-left*, *top-right*, *bottom-right*,\n*bottom-left*), or the *middle* of the frame. For example, for dots distributed horizontally at the top of the frame:\n\n```js Plot.dot(data, {x: \"date\", frameAnchor: \"top\"}) ```" + }, + "fx": { + "$ref": "#/definitions/ChannelValue", + "description": "The horizontal facet position channel, for mark-level faceting, bound to the *fx* scale." + }, + "fy": { + "$ref": "#/definitions/ChannelValue", + "description": "The vertical facet position channel, for mark-level faceting, bound to the\n*fy* scale." + }, + "href": { + "$ref": "#/definitions/ChannelValue", + "description": "The [href][1]; a channel specifying URLs for clickable links. May be used in conjunction with the **target** option to open links in another window.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/href" + }, + "imageFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A CSS [filter][1]; a constant string used to adjust the rendering of images, such as *blur(5px)*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/filter" + }, + "margin": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four mark margins: **marginTop**,\n**marginRight**, **marginBottom**, and **marginLeft**; typically defaults to 0, except for axis marks." + }, + "marginBottom": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s bottom margin; the minimum distance in pixels between the bottom edges of the inner and outer plot area." + }, + "marginLeft": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s left margin; the minimum distance in pixels between the left edges of the inner and outer plot area." + }, + "marginRight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s right margin; the minimum distance in pixels between the right edges of the mark’s inner and outer plot area." + }, + "marginTop": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s top margin; the minimum distance in pixels between the top edges of the inner and outer plot area." + }, + "mark": { + "const": "circle", + "description": "Like dot, except that the **symbol** option is set to *circle*.", + "type": "string" + }, + "mixBlendMode": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [mix-blend-mode][1]; a constant string specifying how to blend content such as *multiply*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode" + }, + "opacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally. For faster rendering, prefer the **strokeOpacity** or **fillOpacity** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/opacity" + }, + "paintOrder": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [paint-order][1]; a constant string specifying the order in which the\n**fill**, **stroke**, and any markers are drawn; defaults to *normal*, which draws the fill, then stroke, then markers; defaults to *stroke* for the text mark to create a “halo” around text to improve legibility.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/paint-order" + }, + "pointerEvents": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [pointer-events][1] property; a constant string such as *none*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/pointer-events" + }, + "r": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The radius of dots; either a channel or constant. When a number, it is interpreted as a constant radius in pixels. Otherwise it is interpreted as a channel, typically bound to the *r* channel, which defaults to the *sqrt* type for proportional symbols. The radius defaults to 4.5 pixels when using the **symbol** channel, and otherwise 3 pixels. Dots with a nonpositive radius are not drawn." + }, + "reverse": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Applies a transform to reverse the order of the mark’s index, say for reverse input order." + }, + "rotate": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The rotation angle of dots in degrees clockwise; either a channel or a constant. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel. Defaults to 0°, pointing up." + }, + "select": { + "$ref": "#/definitions/SelectFilter", + "description": "Applies a filter transform after data is loaded to highlight selected values only. For example, `first` and `last` select the first or last values of series only (using the *z* channel to separate series). Meanwhile, `nearestX` and `nearestY` select the point nearest to the pointer along the *x* or *y* channel dimension. Unlike Mosaic selections, a mark level *select* is internal to the mark only, and does not populate a param or selection value to be shared across clients.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "shapeRendering": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [shape-rendering][1]; a constant string such as *crispEdges*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/shape-rendering" + }, + "sort": { + "anyOf": [ + { + "$ref": "#/definitions/SortOrder" + }, + { + "$ref": "#/definitions/ChannelDomainSort" + } + ], + "description": "Either applies a transform to sort the mark’s index by the specified channel values, or imputes ordinal scale domains from this mark’s channels.\n\nWhen imputing ordinal scale domains from channel values, the **sort** option is an object whose keys are ordinal scale names such as *x* or *fx*, and whose values are channel names such as *y*, *y1*, or *y2*. For example, to impute the *y* scale’s domain from the associated *x* channel values in ascending order:\n\n```js sort: {y: \"x\"} ```\n\nFor different sort options for different scales, replace the channel name with a *value* object and per-scale options:\n\n```js sort: {y: {value: \"-x\"}} ```\n\nWhen sorting the mark’s index, the **sort** option is instead one of:\n\n- a channel value definition for sorting given values in ascending order\n- a {value, order} object for sorting given values\n- a {channel, order} object for sorting the named channel’s values" + }, + "stroke": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke" + }, + "strokeDasharray": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dasharray][1]; a constant number indicating the length in pixels of alternating dashes and gaps, or a constant string of numbers separated by spaces or commas (_e.g._, *10 2* for dashes of 10 pixels separated by gaps of 2 pixels), or *none* (the default) for no dashing\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dasharray" + }, + "strokeDashoffset": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dashoffset][1]; a constant indicating the offset in pixels of the first dash along the stroke; defaults to zero.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dashoffset" + }, + "strokeLinecap": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linecap][1]; a constant specifying how to cap stroked paths, such as *butt*, *round*, or *square*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linecap" + }, + "strokeLinejoin": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linejoin][1]; a constant specifying how to join stroked paths, such as *bevel*, *miter*, *miter-clip*, or *round*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linejoin" + }, + "strokeMiterlimit": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-miterlimit][1]; a constant number specifying how to limit the length of *miter* joins on stroked paths.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-miterlimit" + }, + "strokeOpacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-opacity" + }, + "strokeWidth": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-width][1]; a constant number in pixels, or a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-width" + }, + "symbol": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/SymbolType" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The categorical symbol; either a channel or a constant. A constant symbol can be specified by a valid symbol name such as *star*, or a symbol object (implementing the draw method); otherwise it is interpreted as a channel. Defaults to *circle* for the **dot** mark, and *hexagon* for the\n**hexagon** mark.\n\nIf the **symbol** channel’s values are all symbols, symbol names, or nullish, the channel is unscaled (values are interpreted literally); otherwise, the channel is bound to the *symbol* scale." + }, + "target": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [target][1]; a constant string specifying the target window (_e.g._,\n*_blank*) for clickable links; used in conjunction with the **href** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/target" + }, + "tip": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/TipPointer" + }, + { + "properties": { + "anchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The tip anchor specifies how to orient the tip box relative to its anchor position; it refers to the part of the tip box that is attached to the anchor point. For example, the *top-left* anchor places the top-left corner of tip box near the anchor position, hence placing the tip box below and to the right of the anchor position." + }, + "fontFamily": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font-family][1]; a constant; defaults to the plot’s font family, which is typically [*system-ui*][2].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-family [2]: https://drafts.csswg.org/css-fonts-4/#valdef-font-family-system-ui" + }, + "fontSize": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font size][1] in pixels; either a constant or a channel; defaults to the plot’s font size, which is typically 10. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-size" + }, + "fontStyle": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font style][1]; a constant; defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-style" + }, + "fontVariant": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font variant][1]; a constant; if the **text** channel contains numbers or dates, defaults to *tabular-nums* to facilitate comparing numbers; otherwise defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant" + }, + "fontWeight": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font weight][1]; a constant; defaults to the plot’s font weight, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight" + }, + "format": { + "additionalProperties": false, + "description": "How channel values are formatted for display. If a format is a string, it is interpreted as a (UTC) time format for temporal channels, and otherwise a number format.", + "properties": { + "ariaLabel": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fill": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fillOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fontSize": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fx": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fy": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "geometry": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "height": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "href": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "length": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "opacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "path": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "r": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "rotate": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "src": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "stroke": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeWidth": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "symbol": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "text": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "title": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "weight": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "width": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "z": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + } + }, + "type": "object" + }, + "frameAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The frame anchor specifies defaults for **x** and **y** based on the plot’s frame; it may be one of the four sides (*top*, *right*, *bottom*, *left*), one of the four corners (*top-left*, *top-right*, *bottom-right*,\n*bottom-left*), or the *middle* of the frame. For example, for tips distributed horizontally at the top of the frame:\n\n```js Plot.tip(data, {x: \"date\", frameAnchor: \"top\"}) ```" + }, + "lineHeight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line height in ems; defaults to 1. The line height affects the (typically vertical) separation between adjacent baselines of text, as well as the separation between the text and its anchor point." + }, + "lineWidth": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line width in ems (e.g., 10 for about 20 characters); defaults to infinity, disabling wrapping and clipping.\n\nIf **textOverflow** is null, lines will be wrapped at the specified length. If a line is split at a soft hyphen (\\xad), a hyphen (-) will be displayed at the end of the line. If **textOverflow** is not null, lines will be clipped according to the given strategy." + }, + "monospace": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, changes the default **fontFamily** to *monospace*, and uses simplified monospaced text metrics calculations." + }, + "pathFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The image filter for the tip’s box; defaults to a drop shadow." + }, + "pointer": { + "$ref": "#/definitions/TipPointer" + }, + "pointerSize": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The size of the tip’s pointer in pixels; defaults to 12." + }, + "preferredAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If an explicit tip anchor is not specified, an anchor is chosen automatically such that the tip fits within the plot’s frame; if the preferred anchor fits, it is chosen." + }, + "textAnchor": { + "anyOf": [ + { + "const": "start", + "type": "string" + }, + { + "const": "middle", + "type": "string" + }, + { + "const": "end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [text anchor][1] controls how text is aligned (typically horizontally) relative to its anchor point; it is one of *start*, *end*, or *middle*. If the frame anchor is *left*, *top-left*, or *bottom-left*, the default text anchor is *start*; if the frame anchor is *right*, *top-right*, or\n*bottom-right*, the default is *end*; otherwise it is *middle*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/text-anchor" + }, + "textOverflow": { + "anyOf": [ + { + "type": "null" + }, + { + "const": "clip", + "type": "string" + }, + { + "const": "ellipsis", + "type": "string" + }, + { + "const": "clip-start", + "type": "string" + }, + { + "const": "clip-end", + "type": "string" + }, + { + "const": "ellipsis-start", + "type": "string" + }, + { + "const": "ellipsis-middle", + "type": "string" + }, + { + "const": "ellipsis-end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How truncate (or wrap) lines of text longer than the given **lineWidth**; one of:\n\n- null (default) - preserve overflowing characters (and wrap if needed)\n- *clip* or *clip-end* - remove characters from the end\n- *clip-start* - remove characters from the start\n- *ellipsis* or *ellipsis-end* - replace characters from the end with an ellipsis (…)\n- *ellipsis-start* - replace characters from the start with an ellipsis (…)\n- *ellipsis-middle* - replace characters from the middle with an ellipsis (…)\n\nIf no **title** was specified, if text requires truncation, a title containing the non-truncated text will be implicitly added." + }, + "textPadding": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The padding around the text in pixels; defaults to 8." + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + } + }, + "type": "object" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to generate a tooltip for this mark, and any tip options." + }, + "title": { + "$ref": "#/definitions/ChannelValue", + "description": "The title; a channel specifying accessible, short textual descriptions as strings (possibly with newlines). If the tip option is specified, the title will be displayed with an interactive tooltip instead of using the SVG [title element][1].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/title" + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel specifying the dot’s center, typically bound to the *x* scale." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel specifying the dot’s center, typically bound to the *y* scale." + }, + "z": { + "$ref": "#/definitions/ChannelValue", + "description": "An optional ordinal channel for grouping data into series." + } + }, + "required": [ + "data", + "mark" + ], + "type": "object" + }, + "ColorScaleType": { + "description": "The supported scale types for *color* encodings.\n\nFor quantitative data, one of:\n\n- *linear* (default) - linear transform (translate and scale)\n- *pow* - power (exponential) transform\n- *sqrt* - square-root transform; *pow* with *exponent* = 0.5\n- *log* - logarithmic transform\n- *symlog* - bi-symmetric logarithmic transform per Webber et al.\n\nFor temporal data, one of:\n\n- *utc* (default, recommended) - UTC time\n- *time* - local time\n\nFor ordinal data, one of:\n\n- *ordinal* - from discrete inputs to discrete outputs\n\nFor color, one of:\n\n- *categorical* - equivalent to *ordinal*; defaults to *observable10*\n- *sequential* - equivalent to *linear*; defaults to *turbo*\n- *cyclical* - equivalent to *linear*; defaults to *rainbow*\n- *threshold* - encodes using discrete thresholds; defaults to *rdylbu*\n- *quantile* - encodes using quantile thresholds; defaults to *rdylbu*\n- *quantize* - uniformly quantizes a continuous domain; defaults to *rdylbu*\n- *diverging* - *linear*, but with a pivot; defaults to *rdbu*\n- *diverging-log* - *log*, but with a pivot; defaults to *rdbu*\n- *diverging-pow* - *pow*, but with a pivot; defaults to *rdbu*\n- *diverging-sqrt* - *sqrt*, but with a pivot; defaults to *rdbu*\n- *diverging-symlog* - *symlog*, but with a pivot; defaults to *rdbu*\n\nOther scale types:\n\n- *identity* - do not transform values when encoding", + "enum": [ + "linear", + "pow", + "sqrt", + "log", + "symlog", + "utc", + "time", + "point", + "band", + "ordinal", + "sequential", + "cyclical", + "diverging", + "diverging-log", + "diverging-pow", + "diverging-sqrt", + "diverging-symlog", + "categorical", + "threshold", + "quantile", + "quantize", + "identity" + ], + "type": "string" + }, + "ColorScheme": { + "anyOf": [ + { + "description": "The built-in color schemes, cased.", + "enum": [ + "Accent", + "Category10", + "Dark2", + "Observable10", + "Paired", + "Pastel1", + "Pastel2", + "Set1", + "Set2", + "Set3", + "Tableau10", + "BrBG", + "PRGn", + "PiYG", + "PuOr", + "RdBu", + "RdGy", + "RdYlBu", + "RdYlGn", + "Spectral", + "BuRd", + "BuYlRd", + "Blues", + "Greens", + "Greys", + "Oranges", + "Purples", + "Reds", + "Turbo", + "Viridis", + "Magma", + "Inferno", + "Plasma", + "Cividis", + "Cubehelix", + "Warm", + "Cool", + "BuGn", + "BuPu", + "GnBu", + "OrRd", + "PuBu", + "PuBuGn", + "PuRd", + "RdPu", + "YlGn", + "YlGnBu", + "YlOrBr", + "YlOrRd", + "Rainbow", + "Sinebow" + ], + "type": "string" + }, + { + "properties": {}, + "type": "object" + }, + { + "properties": {}, + "type": "object" + }, + { + "properties": {}, + "type": "object" + }, + { + "properties": {}, + "type": "object" + }, + { + "properties": {}, + "type": "object" + }, + { + "properties": {}, + "type": "object" + }, + { + "properties": {}, + "type": "object" + }, + { + "properties": {}, + "type": "object" + }, + { + "properties": {}, + "type": "object" + }, + { + "properties": {}, + "type": "object" + }, + { + "properties": {}, + "type": "object" + }, + { + "properties": {}, + "type": "object" + }, + { + "properties": {}, + "type": "object" + }, + { + "properties": {}, + "type": "object" + }, + { + "properties": {}, + "type": "object" + }, + { + "properties": {}, + "type": "object" + }, + { + "properties": {}, + "type": "object" + }, + { + "properties": {}, + "type": "object" + }, + { + "properties": {}, + "type": "object" + }, + { + "properties": {}, + "type": "object" + }, + { + "properties": {}, + "type": "object" + }, + { + "properties": {}, + "type": "object" + }, + { + "properties": {}, + "type": "object" + }, + { + "properties": {}, + "type": "object" + }, + { + "properties": {}, + "type": "object" + }, + { + "properties": {}, + "type": "object" + }, + { + "properties": {}, + "type": "object" + }, + { + "properties": {}, + "type": "object" + }, + { + "properties": {}, + "type": "object" + }, + { + "properties": {}, + "type": "object" + }, + { + "properties": {}, + "type": "object" + }, + { + "properties": {}, + "type": "object" + }, + { + "properties": {}, + "type": "object" + }, + { + "properties": {}, + "type": "object" + }, + { + "properties": {}, + "type": "object" + }, + { + "properties": {}, + "type": "object" + }, + { + "properties": {}, + "type": "object" + }, + { + "properties": {}, + "type": "object" + }, + { + "properties": {}, + "type": "object" + }, + { + "properties": {}, + "type": "object" + }, + { + "properties": {}, + "type": "object" + }, + { + "properties": {}, + "type": "object" + }, + { + "properties": {}, + "type": "object" + }, + { + "properties": {}, + "type": "object" + }, + { + "properties": {}, + "type": "object" + }, + { + "properties": {}, + "type": "object" + }, + { + "properties": {}, + "type": "object" + }, + { + "properties": {}, + "type": "object" + }, + { + "properties": {}, + "type": "object" + }, + { + "properties": {}, + "type": "object" + }, + { + "properties": {}, + "type": "object" + } + ], + "description": "The built-in color schemes. For categorical data, one of:\n\n- *Accent* - eight colors\n- *Category10* - ten colors\n- *Dark2* - eight colors\n- *Observable10* (default) - ten colors\n- *Paired* - twelve paired colors\n- *Pastel1* - nine colors\n- *Pastel2* - eight colors\n- *Set1* - nine colors\n- *Set2* - eight colors\n- *Set3* - twelve colors\n- *Tableau10* - ten colors\n\nFor diverging data, one of:\n\n- *BrBG* - from brown to white to blue-green\n- *PRGn* - from purple to white to green\n- *PiYG* - from pink to white to yellow-green\n- *PuOr* - from purple to white to orange\n- *RdBu* (default) - from red to white to blue\n- *RdGy* - from red to white to gray\n- *RdYlBu* - from red to yellow to blue\n- *RdYlGn* - from red to yellow to green\n- *Spectral* - from red to blue, through the spectrum\n- *BuRd* - from blue to white to red\n- *BuYlRd* - from blue to yellow to red\n\nFor sequential data, one of:\n\n- *Blues* - from white to blue\n- *Greens* - from white to green\n- *Greys* - from white to gray\n- *Oranges* - from white to orange\n- *Purples* - from white to purple\n- *Reds* - from white to red\n- *Turbo* (default) - from blue to red, through the spectrum\n- *Viridis* - from blue to green to yellow\n- *Magma* - from purple to orange to yellow\n- *Inferno* - from purple to orange to yellow\n- *Plasma* - from purple to orange to yellow\n- *Cividis* - from blue to yellow\n- *Cubehelix* - from black to white, rotating hue\n- *Warm* - from purple to green, through warm hues\n- *Cool* - from green to to purple, through cool hues\n- *BuGn* - from light blue to dark green\n- *BuPu* - from light blue to dark purple\n- *GnBu* - from light green to dark blue\n- *OrRd* - from light orange to dark red\n- *PuBu* - from light purple to dark blue\n- *PuBuGn* - from light purple to blue to dark green\n- *PuRd* - from light purple to dark red\n- *RdPu* - from light red to dark purple\n- *YlGn* - from light yellow to dark green\n- *YlGnBu* - from light yellow to green to dark blue\n- *YlOrBr* - from light yellow to orange to dark brown\n- *YlOrRd* - from light yellow to orange to dark red\n\nFor cyclical data, one of:\n\n- *Rainbow* (default) - the less-angry rainbow color scheme\n- *Sinebow* - Bumgardner and Loyd’s “sinebow” scheme" + }, + "ColumnTransform": { + "anyOf": [ + { + "$ref": "#/definitions/Bin" + }, + { + "$ref": "#/definitions/DateMonth" + }, + { + "$ref": "#/definitions/DateMonthDay" + }, + { + "$ref": "#/definitions/DateDay" + }, + { + "$ref": "#/definitions/Centroid" + }, + { + "$ref": "#/definitions/CentroidX" + }, + { + "$ref": "#/definitions/CentroidY" + }, + { + "$ref": "#/definitions/GeoJSON" + } + ], + "description": "A data transform that maps one column value to another." + }, + "Component": { + "anyOf": [ + { + "$ref": "#/definitions/HConcat" + }, + { + "$ref": "#/definitions/VConcat" + }, + { + "$ref": "#/definitions/HSpace" + }, + { + "$ref": "#/definitions/VSpace" + }, + { + "$ref": "#/definitions/Menu" + }, + { + "$ref": "#/definitions/Search" + }, + { + "$ref": "#/definitions/Slider" + }, + { + "$ref": "#/definitions/Table" + }, + { + "$ref": "#/definitions/Plot" + }, + { + "$ref": "#/definitions/PlotMark" + }, + { + "$ref": "#/definitions/Legend" + } + ], + "description": "A specifcation component such as a plot, input widget, or layout." + }, + "Config": { + "description": "Configuration options.", + "properties": { + "extensions": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "type": "array" + } + ] + } + }, + "type": "object" + }, + "ContinuousScaleType": { + "description": "The supported scale types for continuous encoding channels.\n\nFor quantitative data, one of:\n\n- *linear* (default) - linear transform (translate and scale)\n- *pow* - power (exponential) transform\n- *sqrt* - square-root transform; *pow* with *exponent* = 0.5\n- *log* - logarithmic transform\n- *symlog* - bi-symmetric logarithmic transform per Webber et al.\n\nFor temporal data, one of:\n\n- *utc* (default, recommended) - UTC time\n- *time* - local time\n\nOther scale types:\n\n- *identity* - do not transform values when encoding", + "enum": [ + "linear", + "pow", + "sqrt", + "log", + "symlog", + "utc", + "time", + "identity" + ], + "type": "string" + }, + "Contour": { + "additionalProperties": false, + "description": "The contour mark.", + "properties": { + "ariaDescription": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-description][1]; a constant textual description.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-description" + }, + "ariaHidden": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-hidden][1] state; a constant indicating whether the element is exposed to an accessibility API.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-hidden" + }, + "ariaLabel": { + "$ref": "#/definitions/ChannelValue", + "description": "The [aria-label][1]; a channel specifying short textual labels representing the value in the accessibility tree.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-label" + }, + "bandwidth": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The kernel density bandwidth for smoothing, in pixels." + }, + "clip": { + "anyOf": [ + { + "const": "frame", + "type": "string" + }, + { + "const": "sphere", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to clip the mark; one of:\n\n- *frame* or true - clip to the plot’s frame (inner area)\n- *sphere* - clip to the projected sphere (*e.g.*, front hemisphere)\n- null or false - do not clip\n\nThe *sphere* clip option requires a geographic projection." + }, + "data": { + "$ref": "#/definitions/PlotMarkData", + "description": "The data source for the mark." + }, + "dx": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The horizontal offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "dy": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The vertical offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "facet": { + "anyOf": [ + { + "const": "auto", + "type": "string" + }, + { + "const": "include", + "type": "string" + }, + { + "const": "exclude", + "type": "string" + }, + { + "const": "super", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to enable or disable faceting; one of:\n\n- *auto* (default) - automatically determine if this mark should be faceted\n- *include* (or true) - draw the subset of the mark’s data in the current facet\n- *exclude* - draw the subset of the mark’s data *not* in the current facet\n- *super* - draw this mark in a single frame that covers all facets\n- null (or false) - repeat this mark’s data across all facets (*i.e.*, no faceting)\n\nWhen a mark uses *super* faceting, it is not allowed to use position scales (*x*, *y*, *fx*, or *fy*); *super* faceting is intended for decorations, such as labels and legends.\n\nWhen top-level faceting is used, the default *auto* setting is equivalent to *include* when the mark data is strictly equal to the top-level facet data; otherwise it is equivalent to null. When the *include* or *exclude* facet mode is chosen, the mark data must be parallel to the top-level facet data: the data must have the same length and order. If the data are not parallel, then the wrong data may be shown in each facet. The default\n*auto* therefore requires strict equality (`===`) for safety, and using the facet data as mark data is recommended when using the *exclude* facet mode. (To construct parallel data safely, consider using [*array*.map][1] on the facet data.)\n\nWhen mark-level faceting is used, the default *auto* setting is equivalent to *include*: the mark will be faceted if either the **fx** or **fy** channel option (or both) is specified. The null or false option will disable faceting, while *exclude* draws the subset of the mark’s data *not* in the current facet.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map" + }, + "facetAnchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "right", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "const": "left", + "type": "string" + }, + { + "const": "top-left", + "type": "string" + }, + { + "const": "top-right", + "type": "string" + }, + { + "const": "bottom-left", + "type": "string" + }, + { + "const": "bottom-right", + "type": "string" + }, + { + "const": "top-empty", + "type": "string" + }, + { + "const": "right-empty", + "type": "string" + }, + { + "const": "bottom-empty", + "type": "string" + }, + { + "const": "left-empty", + "type": "string" + }, + { + "const": "empty", + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to place the mark with respect to facets; one of:\n\n- null (default for most marks) - display the mark in each non-empty facet\n- *top*, *right*, *bottom*, or *left* - display the mark only in facets on the given side\n- *top-empty*, *right-empty*, *bottom-empty*, or *left-empty* (default for axis marks) - display the mark only in facets that have empty space on the given side: either the margin, or an empty facet\n- *empty* - display the mark in empty facets only" + }, + "fill": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill" + }, + "fillOpacity": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill-opacity][1]; a constant number between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill-opacity" + }, + "filter": { + "$ref": "#/definitions/ChannelValue", + "description": "Applies a transform to filter the mark’s index according to the given channel values; only truthy values are retained.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "fx": { + "$ref": "#/definitions/ChannelValue", + "description": "The horizontal facet position channel, for mark-level faceting, bound to the *fx* scale." + }, + "fy": { + "$ref": "#/definitions/ChannelValue", + "description": "The vertical facet position channel, for mark-level faceting, bound to the\n*fy* scale." + }, + "height": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The height (number of rows) of the grid, in actual pixels." + }, + "href": { + "$ref": "#/definitions/ChannelValue", + "description": "The [href][1]; a channel specifying URLs for clickable links. May be used in conjunction with the **target** option to open links in another window.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/href" + }, + "imageFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A CSS [filter][1]; a constant string used to adjust the rendering of images, such as *blur(5px)*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/filter" + }, + "interpolate": { + "anyOf": [ + { + "$ref": "#/definitions/GridInterpolate" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The spatial interpolation method; one of:\n\n- *none* - do not perform interpolation (the default), maps samples to single bins\n- *linear* - apply proportional linear interpolation across adjacent bins\n- *nearest* - assign each pixel to the closest sample’s value (Voronoi diagram)\n- *barycentric* - apply barycentric interpolation over the Delaunay triangulation\n- *random-walk* - apply a random walk from each pixel, stopping when near a sample" + }, + "margin": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four mark margins: **marginTop**,\n**marginRight**, **marginBottom**, and **marginLeft**; typically defaults to 0, except for axis marks." + }, + "marginBottom": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s bottom margin; the minimum distance in pixels between the bottom edges of the inner and outer plot area." + }, + "marginLeft": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s left margin; the minimum distance in pixels between the left edges of the inner and outer plot area." + }, + "marginRight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s right margin; the minimum distance in pixels between the right edges of the mark’s inner and outer plot area." + }, + "marginTop": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s top margin; the minimum distance in pixels between the top edges of the inner and outer plot area." + }, + "mark": { + "const": "contour", + "description": "A contour mark that draws isolines to delineate regions above and below a particular continuous value. It is often used to convey densities as a height field. The special column name \"density\" can be used to map density values to the fill or stroke options.", + "type": "string" + }, + "mixBlendMode": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [mix-blend-mode][1]; a constant string specifying how to blend content such as *multiply*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode" + }, + "opacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally. For faster rendering, prefer the **strokeOpacity** or **fillOpacity** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/opacity" + }, + "pad": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The bin padding, one of 1 (default) to include extra padding for the final bin, or 0 to make the bins flush with the maximum domain value." + }, + "paintOrder": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [paint-order][1]; a constant string specifying the order in which the\n**fill**, **stroke**, and any markers are drawn; defaults to *normal*, which draws the fill, then stroke, then markers; defaults to *stroke* for the text mark to create a “halo” around text to improve legibility.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/paint-order" + }, + "pixelSize": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The effective screen size of a raster pixel, used to determine the height and width of the raster from the frame’s dimensions; defaults to 1." + }, + "pointerEvents": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [pointer-events][1] property; a constant string such as *none*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/pointer-events" + }, + "reverse": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Applies a transform to reverse the order of the mark’s index, say for reverse input order." + }, + "select": { + "$ref": "#/definitions/SelectFilter", + "description": "Applies a filter transform after data is loaded to highlight selected values only. For example, `first` and `last` select the first or last values of series only (using the *z* channel to separate series). Meanwhile, `nearestX` and `nearestY` select the point nearest to the pointer along the *x* or *y* channel dimension. Unlike Mosaic selections, a mark level *select* is internal to the mark only, and does not populate a param or selection value to be shared across clients.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "shapeRendering": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [shape-rendering][1]; a constant string such as *crispEdges*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/shape-rendering" + }, + "sort": { + "anyOf": [ + { + "$ref": "#/definitions/SortOrder" + }, + { + "$ref": "#/definitions/ChannelDomainSort" + } + ], + "description": "Either applies a transform to sort the mark’s index by the specified channel values, or imputes ordinal scale domains from this mark’s channels.\n\nWhen imputing ordinal scale domains from channel values, the **sort** option is an object whose keys are ordinal scale names such as *x* or *fx*, and whose values are channel names such as *y*, *y1*, or *y2*. For example, to impute the *y* scale’s domain from the associated *x* channel values in ascending order:\n\n```js sort: {y: \"x\"} ```\n\nFor different sort options for different scales, replace the channel name with a *value* object and per-scale options:\n\n```js sort: {y: {value: \"-x\"}} ```\n\nWhen sorting the mark’s index, the **sort** option is instead one of:\n\n- a channel value definition for sorting given values in ascending order\n- a {value, order} object for sorting given values\n- a {channel, order} object for sorting the named channel’s values" + }, + "stroke": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke" + }, + "strokeDasharray": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dasharray][1]; a constant number indicating the length in pixels of alternating dashes and gaps, or a constant string of numbers separated by spaces or commas (_e.g._, *10 2* for dashes of 10 pixels separated by gaps of 2 pixels), or *none* (the default) for no dashing\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dasharray" + }, + "strokeDashoffset": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dashoffset][1]; a constant indicating the offset in pixels of the first dash along the stroke; defaults to zero.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dashoffset" + }, + "strokeLinecap": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linecap][1]; a constant specifying how to cap stroked paths, such as *butt*, *round*, or *square*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linecap" + }, + "strokeLinejoin": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linejoin][1]; a constant specifying how to join stroked paths, such as *bevel*, *miter*, *miter-clip*, or *round*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linejoin" + }, + "strokeMiterlimit": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-miterlimit][1]; a constant number specifying how to limit the length of *miter* joins on stroked paths.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-miterlimit" + }, + "strokeOpacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-opacity" + }, + "strokeWidth": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-width][1]; a constant number in pixels, or a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-width" + }, + "target": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [target][1]; a constant string specifying the target window (_e.g._,\n*_blank*) for clickable links; used in conjunction with the **href** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/target" + }, + "thresholds": { + "anyOf": [ + { + "type": "number" + }, + { + "items": { + "type": "number" + }, + "type": "array" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The number of contour thresholds to subdivide the domain into discrete level sets; defaults to 10. One of:\n\n- a count representing the desired number of bins\n- an array of *n* threshold values for *n* - 1 bins" + }, + "tip": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/TipPointer" + }, + { + "properties": { + "anchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The tip anchor specifies how to orient the tip box relative to its anchor position; it refers to the part of the tip box that is attached to the anchor point. For example, the *top-left* anchor places the top-left corner of tip box near the anchor position, hence placing the tip box below and to the right of the anchor position." + }, + "fontFamily": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font-family][1]; a constant; defaults to the plot’s font family, which is typically [*system-ui*][2].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-family [2]: https://drafts.csswg.org/css-fonts-4/#valdef-font-family-system-ui" + }, + "fontSize": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font size][1] in pixels; either a constant or a channel; defaults to the plot’s font size, which is typically 10. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-size" + }, + "fontStyle": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font style][1]; a constant; defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-style" + }, + "fontVariant": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font variant][1]; a constant; if the **text** channel contains numbers or dates, defaults to *tabular-nums* to facilitate comparing numbers; otherwise defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant" + }, + "fontWeight": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font weight][1]; a constant; defaults to the plot’s font weight, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight" + }, + "format": { + "additionalProperties": false, + "description": "How channel values are formatted for display. If a format is a string, it is interpreted as a (UTC) time format for temporal channels, and otherwise a number format.", + "properties": { + "ariaLabel": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fill": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fillOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fontSize": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fx": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fy": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "geometry": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "height": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "href": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "length": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "opacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "path": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "r": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "rotate": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "src": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "stroke": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeWidth": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "symbol": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "text": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "title": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "weight": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "width": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "z": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + } + }, + "type": "object" + }, + "frameAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The frame anchor specifies defaults for **x** and **y** based on the plot’s frame; it may be one of the four sides (*top*, *right*, *bottom*, *left*), one of the four corners (*top-left*, *top-right*, *bottom-right*,\n*bottom-left*), or the *middle* of the frame. For example, for tips distributed horizontally at the top of the frame:\n\n```js Plot.tip(data, {x: \"date\", frameAnchor: \"top\"}) ```" + }, + "lineHeight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line height in ems; defaults to 1. The line height affects the (typically vertical) separation between adjacent baselines of text, as well as the separation between the text and its anchor point." + }, + "lineWidth": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line width in ems (e.g., 10 for about 20 characters); defaults to infinity, disabling wrapping and clipping.\n\nIf **textOverflow** is null, lines will be wrapped at the specified length. If a line is split at a soft hyphen (\\xad), a hyphen (-) will be displayed at the end of the line. If **textOverflow** is not null, lines will be clipped according to the given strategy." + }, + "monospace": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, changes the default **fontFamily** to *monospace*, and uses simplified monospaced text metrics calculations." + }, + "pathFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The image filter for the tip’s box; defaults to a drop shadow." + }, + "pointer": { + "$ref": "#/definitions/TipPointer" + }, + "pointerSize": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The size of the tip’s pointer in pixels; defaults to 12." + }, + "preferredAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If an explicit tip anchor is not specified, an anchor is chosen automatically such that the tip fits within the plot’s frame; if the preferred anchor fits, it is chosen." + }, + "textAnchor": { + "anyOf": [ + { + "const": "start", + "type": "string" + }, + { + "const": "middle", + "type": "string" + }, + { + "const": "end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [text anchor][1] controls how text is aligned (typically horizontally) relative to its anchor point; it is one of *start*, *end*, or *middle*. If the frame anchor is *left*, *top-left*, or *bottom-left*, the default text anchor is *start*; if the frame anchor is *right*, *top-right*, or\n*bottom-right*, the default is *end*; otherwise it is *middle*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/text-anchor" + }, + "textOverflow": { + "anyOf": [ + { + "type": "null" + }, + { + "const": "clip", + "type": "string" + }, + { + "const": "ellipsis", + "type": "string" + }, + { + "const": "clip-start", + "type": "string" + }, + { + "const": "clip-end", + "type": "string" + }, + { + "const": "ellipsis-start", + "type": "string" + }, + { + "const": "ellipsis-middle", + "type": "string" + }, + { + "const": "ellipsis-end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How truncate (or wrap) lines of text longer than the given **lineWidth**; one of:\n\n- null (default) - preserve overflowing characters (and wrap if needed)\n- *clip* or *clip-end* - remove characters from the end\n- *clip-start* - remove characters from the start\n- *ellipsis* or *ellipsis-end* - replace characters from the end with an ellipsis (…)\n- *ellipsis-start* - replace characters from the start with an ellipsis (…)\n- *ellipsis-middle* - replace characters from the middle with an ellipsis (…)\n\nIf no **title** was specified, if text requires truncation, a title containing the non-truncated text will be implicitly added." + }, + "textPadding": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The padding around the text in pixels; defaults to 8." + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + } + }, + "type": "object" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to generate a tooltip for this mark, and any tip options." + }, + "title": { + "$ref": "#/definitions/ChannelValue", + "description": "The title; a channel specifying accessible, short textual descriptions as strings (possibly with newlines). If the tip option is specified, the title will be displayed with an interactive tooltip instead of using the SVG [title element][1].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/title" + }, + "width": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The width (number of columns) of the grid, in actual pixels." + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel, typically bound to the *x* scale. Domain values are binned into a grid with *width* horizontal bins." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel, typically bound to the *y* scale. Domain values are binned into a grid with *height* vertical bins." + } + }, + "required": [ + "data", + "mark" + ], + "type": "object" + }, + "Count": { + "additionalProperties": false, + "properties": { + "count": { + "anyOf": [ + { + "anyOf": [ + { + "type": "null" + }, + { + "maxItems": 0, + "minItems": 0, + "type": "array" + } + ], + "description": "A zero argument transform signature." + }, + { + "anyOf": [ + { + "description": "A transform argument.", + "type": [ + "string", + "number", + "boolean" + ] + }, + { + "items": { + "description": "A transform argument.", + "type": [ + "string", + "number", + "boolean" + ] + }, + "maxItems": 1, + "minItems": 1, + "type": "array" + } + ], + "description": "A single argument transform signature." + } + ], + "description": "Compute the count of records in an aggregation group." + }, + "distinct": { + "type": "boolean" + }, + "orderby": { + "anyOf": [ + { + "$ref": "#/definitions/TransformField" + }, + { + "items": { + "$ref": "#/definitions/TransformField" + }, + "type": "array" + } + ] + }, + "partitionby": { + "anyOf": [ + { + "$ref": "#/definitions/TransformField" + }, + { + "items": { + "$ref": "#/definitions/TransformField" + }, + "type": "array" + } + ] + }, + "range": { + "anyOf": [ + { + "items": { + "type": [ + "number", + "null" + ] + }, + "type": "array" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "rows": { + "anyOf": [ + { + "items": { + "type": [ + "number", + "null" + ] + }, + "type": "array" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + } + }, + "required": [ + "count" + ], + "type": "object" + }, + "CumeDist": { + "additionalProperties": false, + "properties": { + "cume_dist": { + "anyOf": [ + { + "type": "null" + }, + { + "maxItems": 0, + "minItems": 0, + "type": "array" + } + ], + "description": "Compute the cumulative distribution value over an ordered window partition. Equals the number of partition rows preceding or peer with the current row, divided by the total number of partition rows." + }, + "orderby": { + "anyOf": [ + { + "$ref": "#/definitions/TransformField" + }, + { + "items": { + "$ref": "#/definitions/TransformField" + }, + "type": "array" + } + ] + }, + "partitionby": { + "anyOf": [ + { + "$ref": "#/definitions/TransformField" + }, + { + "items": { + "$ref": "#/definitions/TransformField" + }, + "type": "array" + } + ] + }, + "range": { + "anyOf": [ + { + "items": { + "type": [ + "number", + "null" + ] + }, + "type": "array" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "rows": { + "anyOf": [ + { + "items": { + "type": [ + "number", + "null" + ] + }, + "type": "array" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + } + }, + "required": [ + "cume_dist" + ], + "type": "object" + }, + "Curve": { + "$ref": "#/definitions/CurveName", + "description": "How to interpolate between control points." + }, + "CurveName": { + "description": "The built-in curve implementations.", + "enum": [ + "basis", + "basis-closed", + "basis-open", + "bundle", + "bump-x", + "bump-y", + "cardinal", + "cardinal-closed", + "cardinal-open", + "catmull-rom", + "catmull-rom-closed", + "catmull-rom-open", + "linear", + "linear-closed", + "monotone-x", + "monotone-y", + "natural", + "step", + "step-after", + "step-before" + ], + "type": "string" + }, + "Data": { + "additionalProperties": { + "$ref": "#/definitions/DataDefinition" + }, + "description": "Top-level dataset definitions.", + "type": "object" + }, + "DataArray": { + "description": "An inline array of data objects to treat as JSON data.", + "items": { + "type": "object" + }, + "type": "array" + }, + "DataCSV": { + "additionalProperties": false, + "description": "A data definition that loads a csv file.", + "properties": { + "delimiter": { + "description": "The column delimiter string. If not specified, DuckDB will try to infer the delimiter automatically.", + "type": "string" + }, + "file": { + "description": "The file path for the dataset to load.", + "type": "string" + }, + "replace": { + "description": "Flag (default `true`) to replace an existing table of the same name. If `false`, creating a new table with an existing name raises an error.", + "type": "boolean" + }, + "sample_size": { + "description": "The sample size, in table rows, to consult for type inference. Set to `-1` to process all rows in the dataset.", + "type": "number" + }, + "select": { + "description": "A list of column names to extract upon load. Any other columns are omitted.", + "items": { + "type": "string" + }, + "type": "array" + }, + "temp": { + "description": "Flag (default `true`) to generate a temporary view or table.", + "type": "boolean" + }, + "type": { + "const": "csv", + "description": "The data source type. One of:\n- `\"table\"`: Define a new table based on a SQL query.\n- `\"csv\"`: Load a comma-separated values (CSV) file.\n- `\"json\"`: Load JavaScript Object Notation (json) data.\n- `\"parquet\"`: Load a Parquet file.\n- `\"spatial\"`: Load a spatial data file format via `ST_Read`.", + "type": "string" + }, + "view": { + "description": "Flag (default `false`) to generate a view instead of a table.", + "type": "boolean" + }, + "where": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "type": "array" + } + ], + "description": "A filter (WHERE clause) to apply upon load. Only rows that pass the filted are included." + } + }, + "required": [ + "type", + "file" + ], + "type": "object" + }, + "DataDefinition": { + "anyOf": [ + { + "$ref": "#/definitions/DataQuery" + }, + { + "$ref": "#/definitions/DataArray" + }, + { + "$ref": "#/definitions/DataFile" + }, + { + "$ref": "#/definitions/DataTable" + }, + { + "$ref": "#/definitions/DataParquet" + }, + { + "$ref": "#/definitions/DataCSV" + }, + { + "$ref": "#/definitions/DataSpatial" + }, + { + "$ref": "#/definitions/DataJSON" + }, + { + "$ref": "#/definitions/DataJSONObjects" + } + ] + }, + "DataFile": { + "additionalProperties": false, + "description": "A data definition that loads an external data file.", + "properties": { + "file": { + "description": "The data file to load. If no type option is provided, the file suffix must be one of `.csv`, `.json`, or `.parquet`.", + "type": [ + "string" + ] + }, + "replace": { + "description": "Flag (default `true`) to replace an existing table of the same name. If `false`, creating a new table with an existing name raises an error.", + "type": "boolean" + }, + "select": { + "description": "A list of column names to extract upon load. Any other columns are omitted.", + "items": { + "type": "string" + }, + "type": "array" + }, + "temp": { + "description": "Flag (default `true`) to generate a temporary view or table.", + "type": "boolean" + }, + "view": { + "description": "Flag (default `false`) to generate a view instead of a table.", + "type": "boolean" + }, + "where": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "type": "array" + } + ], + "description": "A filter (WHERE clause) to apply upon load. Only rows that pass the filted are included." + } + }, + "required": [ + "file" + ], + "type": "object" + }, + "DataJSON": { + "additionalProperties": false, + "properties": { + "file": { + "description": "The file path for the dataset to load.", + "type": "string" + }, + "replace": { + "description": "Flag (default `true`) to replace an existing table of the same name. If `false`, creating a new table with an existing name raises an error.", + "type": "boolean" + }, + "select": { + "description": "A list of column names to extract upon load. Any other columns are omitted.", + "items": { + "type": "string" + }, + "type": "array" + }, + "temp": { + "description": "Flag (default `true`) to generate a temporary view or table.", + "type": "boolean" + }, + "type": { + "const": "json", + "description": "The data source type. One of:\n- `\"table\"`: Define a new table based on a SQL query.\n- `\"csv\"`: Load a comma-separated values (CSV) file.\n- `\"json\"`: Load JavaScript Object Notation (json) data.\n- `\"parquet\"`: Load a Parquet file.\n- `\"spatial\"`: Load a spatial data file format via `ST_Read`.", + "type": "string" + }, + "view": { + "description": "Flag (default `false`) to generate a view instead of a table.", + "type": "boolean" + }, + "where": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "type": "array" + } + ], + "description": "A filter (WHERE clause) to apply upon load. Only rows that pass the filted are included." + } + }, + "required": [ + "type", + "file" + ], + "type": "object" + }, + "DataJSONObjects": { + "additionalProperties": false, + "properties": { + "data": { + "description": "An array of inline objects in JSON-style format.", + "items": { + "type": "object" + }, + "type": "array" + }, + "replace": { + "description": "Flag (default `true`) to replace an existing table of the same name. If `false`, creating a new table with an existing name raises an error.", + "type": "boolean" + }, + "select": { + "description": "A list of column names to extract upon load. Any other columns are omitted.", + "items": { + "type": "string" + }, + "type": "array" + }, + "temp": { + "description": "Flag (default `true`) to generate a temporary view or table.", + "type": "boolean" + }, + "type": { + "const": "json", + "description": "The data source type. One of:\n- `\"table\"`: Define a new table based on a SQL query.\n- `\"csv\"`: Load a comma-separated values (CSV) file.\n- `\"json\"`: Load JavaScript Object Notation (json) data.\n- `\"parquet\"`: Load a Parquet file.\n- `\"spatial\"`: Load a spatial data file format via `ST_Read`.", + "type": "string" + }, + "view": { + "description": "Flag (default `false`) to generate a view instead of a table.", + "type": "boolean" + }, + "where": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "type": "array" + } + ], + "description": "A filter (WHERE clause) to apply upon load. Only rows that pass the filted are included." + } + }, + "required": [ + "data" + ], + "type": "object" + }, + "DataParquet": { + "additionalProperties": false, + "description": "A data definition that loads a parquet file.", + "properties": { + "file": { + "description": "The file path for the dataset to load.", + "type": "string" + }, + "replace": { + "description": "Flag (default `true`) to replace an existing table of the same name. If `false`, creating a new table with an existing name raises an error.", + "type": "boolean" + }, + "select": { + "description": "A list of column names to extract upon load. Any other columns are omitted.", + "items": { + "type": "string" + }, + "type": "array" + }, + "temp": { + "description": "Flag (default `true`) to generate a temporary view or table.", + "type": "boolean" + }, + "type": { + "const": "parquet", + "description": "The data source type. One of:\n- `\"table\"`: Define a new table based on a SQL query.\n- `\"csv\"`: Load a comma-separated values (CSV) file.\n- `\"json\"`: Load JavaScript Object Notation (json) data.\n- `\"parquet\"`: Load a Parquet file.\n- `\"spatial\"`: Load a spatial data file format via `ST_Read`.", + "type": "string" + }, + "view": { + "description": "Flag (default `false`) to generate a view instead of a table.", + "type": "boolean" + }, + "where": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "type": "array" + } + ], + "description": "A filter (WHERE clause) to apply upon load. Only rows that pass the filted are included." + } + }, + "required": [ + "type", + "file" + ], + "type": "object" + }, + "DataQuery": { + "description": "A SQL query defining a new temporary database table.", + "type": "string" + }, + "DataSpatial": { + "additionalProperties": false, + "description": "A data definition that loads a supported spatial data file format.", + "properties": { + "file": { + "description": "The file path for the spatial dataset to load. See the [DuckDB spatial documention][1] for more information on supported file types.\n\n[1]: https://duckdb.org/docs/extensions/spatial.html#st_read--read-spatial-data-from-files", + "type": "string" + }, + "layer": { + "description": "The named layer to load from the file. For example, in a TopoJSON file the layer is the named object to extract. For Excel spreadsheet files, the layer is the name of the worksheet to extract.", + "type": "string" + }, + "replace": { + "description": "Flag (default `true`) to replace an existing table of the same name. If `false`, creating a new table with an existing name raises an error.", + "type": "boolean" + }, + "select": { + "description": "A list of column names to extract upon load. Any other columns are omitted.", + "items": { + "type": "string" + }, + "type": "array" + }, + "temp": { + "description": "Flag (default `true`) to generate a temporary view or table.", + "type": "boolean" + }, + "type": { + "const": "spatial", + "description": "The data source type. One of:\n- `\"table\"`: Define a new table based on a SQL query.\n- `\"csv\"`: Load a comma-separated values (CSV) file.\n- `\"json\"`: Load JavaScript Object Notation (json) data.\n- `\"parquet\"`: Load a Parquet file.\n- `\"spatial\"`: Load a spatial data file format via `ST_Read`.", + "type": "string" + }, + "view": { + "description": "Flag (default `false`) to generate a view instead of a table.", + "type": "boolean" + }, + "where": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "type": "array" + } + ], + "description": "A filter (WHERE clause) to apply upon load. Only rows that pass the filted are included." + } + }, + "required": [ + "type", + "file" + ], + "type": "object" + }, + "DataTable": { + "additionalProperties": false, + "description": "A data definition that queries an existing table.", + "properties": { + "query": { + "description": "A SQL query string for the desired table data.", + "type": "string" + }, + "replace": { + "description": "Flag (default `true`) to replace an existing table of the same name. If `false`, creating a new table with an existing name raises an error.", + "type": "boolean" + }, + "select": { + "description": "A list of column names to extract upon load. Any other columns are omitted.", + "items": { + "type": "string" + }, + "type": "array" + }, + "temp": { + "description": "Flag (default `true`) to generate a temporary view or table.", + "type": "boolean" + }, + "type": { + "const": "table", + "description": "The data source type. One of:\n- `\"table\"`: Define a new table based on a SQL query.\n- `\"csv\"`: Load a comma-separated values (CSV) file.\n- `\"json\"`: Load JavaScript Object Notation (json) data.\n- `\"parquet\"`: Load a Parquet file.\n- `\"spatial\"`: Load a spatial data file format via `ST_Read`.", + "type": "string" + }, + "view": { + "description": "Flag (default `false`) to generate a view instead of a table.", + "type": "boolean" + }, + "where": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "type": "array" + } + ], + "description": "A filter (WHERE clause) to apply upon load. Only rows that pass the filted are included." + } + }, + "required": [ + "type", + "query" + ], + "type": "object" + }, + "DateDay": { + "additionalProperties": false, + "properties": { + "dateDay": { + "anyOf": [ + { + "description": "A transform argument.", + "type": [ + "string", + "number", + "boolean" + ] + }, + { + "items": { + "description": "A transform argument.", + "type": [ + "string", + "number", + "boolean" + ] + }, + "maxItems": 1, + "minItems": 1, + "type": "array" + } + ], + "description": "Transform a Date value to a day of the month for cyclic comparison. Year and month values are collapsed to enable comparison over days only." + } + }, + "required": [ + "dateDay" + ], + "type": "object" + }, + "DateMonth": { + "additionalProperties": false, + "properties": { + "dateMonth": { + "anyOf": [ + { + "description": "A transform argument.", + "type": [ + "string", + "number", + "boolean" + ] + }, + { + "items": { + "description": "A transform argument.", + "type": [ + "string", + "number", + "boolean" + ] + }, + "maxItems": 1, + "minItems": 1, + "type": "array" + } + ], + "description": "Transform a Date value to a month boundary for cyclic comparison. Year values are collapsed to enable comparison over months only." + } + }, + "required": [ + "dateMonth" + ], + "type": "object" + }, + "DateMonthDay": { + "additionalProperties": false, + "properties": { + "dateMonthDay": { + "anyOf": [ + { + "description": "A transform argument.", + "type": [ + "string", + "number", + "boolean" + ] + }, + { + "items": { + "description": "A transform argument.", + "type": [ + "string", + "number", + "boolean" + ] + }, + "maxItems": 1, + "minItems": 1, + "type": "array" + } + ], + "description": "Transform a Date value to a month and day boundary for cyclic comparison. Year values are collapsed to enable comparison over months and days only." + } + }, + "required": [ + "dateMonthDay" + ], + "type": "object" + }, + "DelaunayLink": { + "additionalProperties": false, + "description": "The delaunayLink mark.", + "properties": { + "ariaDescription": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-description][1]; a constant textual description.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-description" + }, + "ariaHidden": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-hidden][1] state; a constant indicating whether the element is exposed to an accessibility API.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-hidden" + }, + "ariaLabel": { + "$ref": "#/definitions/ChannelValue", + "description": "The [aria-label][1]; a channel specifying short textual labels representing the value in the accessibility tree.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-label" + }, + "clip": { + "anyOf": [ + { + "const": "frame", + "type": "string" + }, + { + "const": "sphere", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to clip the mark; one of:\n\n- *frame* or true - clip to the plot’s frame (inner area)\n- *sphere* - clip to the projected sphere (*e.g.*, front hemisphere)\n- null or false - do not clip\n\nThe *sphere* clip option requires a geographic projection." + }, + "curve": { + "anyOf": [ + { + "$ref": "#/definitions/Curve" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The curve (interpolation) method for connecting adjacent points. One of:\n\n- *basis* - a cubic basis spline (repeating the end points)\n- *basis-open* - an open cubic basis spline\n- *basis-closed* - a closed cubic basis spline\n- *bump-x* - a Bézier curve with horizontal tangents\n- *bump-y* - a Bézier curve with vertical tangents\n- *bundle* - a straightened cubic basis spline (suitable for lines only, not areas)\n- *cardinal* - a cubic cardinal spline (with one-sided differences at the ends)\n- *cardinal-open* - an open cubic cardinal spline\n- *cardinal-closed* - an closed cubic cardinal spline\n- *catmull-rom* - a cubic Catmull–Rom spline (with one-sided differences at the ends)\n- *catmull-rom-open* - an open cubic Catmull–Rom spline\n- *catmull-rom-closed* - a closed cubic Catmull–Rom spline\n- *linear* - a piecewise linear curve (*i.e.*, straight line segments)\n- *linear-closed* - a closed piecewise linear curve (*i.e.*, straight line segments)\n- *monotone-x* - a cubic spline that preserves monotonicity in *x*\n- *monotone-y* - a cubic spline that preserves monotonicity in *y*\n- *natural* - a natural cubic spline\n- *step* - a piecewise constant function where *y* changes at the midpoint of *x*\n- *step-after* - a piecewise constant function where *y* changes after *x*\n- *step-before* - a piecewise constant function where *x* changes after *y*" + }, + "data": { + "$ref": "#/definitions/PlotMarkData", + "description": "The data source for the mark." + }, + "dx": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The horizontal offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "dy": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The vertical offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "facet": { + "anyOf": [ + { + "const": "auto", + "type": "string" + }, + { + "const": "include", + "type": "string" + }, + { + "const": "exclude", + "type": "string" + }, + { + "const": "super", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to enable or disable faceting; one of:\n\n- *auto* (default) - automatically determine if this mark should be faceted\n- *include* (or true) - draw the subset of the mark’s data in the current facet\n- *exclude* - draw the subset of the mark’s data *not* in the current facet\n- *super* - draw this mark in a single frame that covers all facets\n- null (or false) - repeat this mark’s data across all facets (*i.e.*, no faceting)\n\nWhen a mark uses *super* faceting, it is not allowed to use position scales (*x*, *y*, *fx*, or *fy*); *super* faceting is intended for decorations, such as labels and legends.\n\nWhen top-level faceting is used, the default *auto* setting is equivalent to *include* when the mark data is strictly equal to the top-level facet data; otherwise it is equivalent to null. When the *include* or *exclude* facet mode is chosen, the mark data must be parallel to the top-level facet data: the data must have the same length and order. If the data are not parallel, then the wrong data may be shown in each facet. The default\n*auto* therefore requires strict equality (`===`) for safety, and using the facet data as mark data is recommended when using the *exclude* facet mode. (To construct parallel data safely, consider using [*array*.map][1] on the facet data.)\n\nWhen mark-level faceting is used, the default *auto* setting is equivalent to *include*: the mark will be faceted if either the **fx** or **fy** channel option (or both) is specified. The null or false option will disable faceting, while *exclude* draws the subset of the mark’s data *not* in the current facet.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map" + }, + "facetAnchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "right", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "const": "left", + "type": "string" + }, + { + "const": "top-left", + "type": "string" + }, + { + "const": "top-right", + "type": "string" + }, + { + "const": "bottom-left", + "type": "string" + }, + { + "const": "bottom-right", + "type": "string" + }, + { + "const": "top-empty", + "type": "string" + }, + { + "const": "right-empty", + "type": "string" + }, + { + "const": "bottom-empty", + "type": "string" + }, + { + "const": "left-empty", + "type": "string" + }, + { + "const": "empty", + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to place the mark with respect to facets; one of:\n\n- null (default for most marks) - display the mark in each non-empty facet\n- *top*, *right*, *bottom*, or *left* - display the mark only in facets on the given side\n- *top-empty*, *right-empty*, *bottom-empty*, or *left-empty* (default for axis marks) - display the mark only in facets that have empty space on the given side: either the margin, or an empty facet\n- *empty* - display the mark in empty facets only" + }, + "fill": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill" + }, + "fillOpacity": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill-opacity][1]; a constant number between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill-opacity" + }, + "filter": { + "$ref": "#/definitions/ChannelValue", + "description": "Applies a transform to filter the mark’s index according to the given channel values; only truthy values are retained.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "fx": { + "$ref": "#/definitions/ChannelValue", + "description": "The horizontal facet position channel, for mark-level faceting, bound to the *fx* scale." + }, + "fy": { + "$ref": "#/definitions/ChannelValue", + "description": "The vertical facet position channel, for mark-level faceting, bound to the\n*fy* scale." + }, + "href": { + "$ref": "#/definitions/ChannelValue", + "description": "The [href][1]; a channel specifying URLs for clickable links. May be used in conjunction with the **target** option to open links in another window.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/href" + }, + "imageFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A CSS [filter][1]; a constant string used to adjust the rendering of images, such as *blur(5px)*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/filter" + }, + "margin": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four mark margins: **marginTop**,\n**marginRight**, **marginBottom**, and **marginLeft**; typically defaults to 0, except for axis marks." + }, + "marginBottom": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s bottom margin; the minimum distance in pixels between the bottom edges of the inner and outer plot area." + }, + "marginLeft": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s left margin; the minimum distance in pixels between the left edges of the inner and outer plot area." + }, + "marginRight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s right margin; the minimum distance in pixels between the right edges of the mark’s inner and outer plot area." + }, + "marginTop": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s top margin; the minimum distance in pixels between the top edges of the inner and outer plot area." + }, + "mark": { + "const": "delaunayLink", + "description": "A mark that draws links for each edge of the Delaunay triangulation of points given by the **x** and **y** channels. Like the link mark, except that **x1**, **y1**, **x2**, and **y2** are derived automatically from **x** and **y**. When an aesthetic channel is specified (such as\n**stroke** or **strokeWidth**), the link inherits the corresponding channel value from one of its two endpoints arbitrarily.\n\nIf **z** is specified, the input points are grouped by *z*, producing a separate Delaunay triangulation for each group.", + "type": "string" + }, + "marker": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for markerStart, markerMid, and markerEnd; one of:\n\n- a marker name such as *arrow* or *circle*\n- *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*" + }, + "markerEnd": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The marker for the ending point of a line segment; one of:\n\n- a marker name such as *arrow* or *circle*\n* *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*" + }, + "markerMid": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The marker for any middle (interior) points of a line segment. If the line segment only has a start and end point, this option has no effect. One of:\n\n- a marker name such as *arrow* or *circle*\n* *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*\n* a function - a custom marker function; see below" + }, + "markerStart": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The marker for the starting point of a line segment; one of:\n\n- a marker name such as *arrow* or *circle*\n* *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*" + }, + "mixBlendMode": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [mix-blend-mode][1]; a constant string specifying how to blend content such as *multiply*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode" + }, + "opacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally. For faster rendering, prefer the **strokeOpacity** or **fillOpacity** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/opacity" + }, + "paintOrder": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [paint-order][1]; a constant string specifying the order in which the\n**fill**, **stroke**, and any markers are drawn; defaults to *normal*, which draws the fill, then stroke, then markers; defaults to *stroke* for the text mark to create a “halo” around text to improve legibility.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/paint-order" + }, + "pointerEvents": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [pointer-events][1] property; a constant string such as *none*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/pointer-events" + }, + "reverse": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Applies a transform to reverse the order of the mark’s index, say for reverse input order." + }, + "select": { + "$ref": "#/definitions/SelectFilter", + "description": "Applies a filter transform after data is loaded to highlight selected values only. For example, `first` and `last` select the first or last values of series only (using the *z* channel to separate series). Meanwhile, `nearestX` and `nearestY` select the point nearest to the pointer along the *x* or *y* channel dimension. Unlike Mosaic selections, a mark level *select* is internal to the mark only, and does not populate a param or selection value to be shared across clients.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "shapeRendering": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [shape-rendering][1]; a constant string such as *crispEdges*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/shape-rendering" + }, + "sort": { + "anyOf": [ + { + "$ref": "#/definitions/SortOrder" + }, + { + "$ref": "#/definitions/ChannelDomainSort" + } + ], + "description": "Either applies a transform to sort the mark’s index by the specified channel values, or imputes ordinal scale domains from this mark’s channels.\n\nWhen imputing ordinal scale domains from channel values, the **sort** option is an object whose keys are ordinal scale names such as *x* or *fx*, and whose values are channel names such as *y*, *y1*, or *y2*. For example, to impute the *y* scale’s domain from the associated *x* channel values in ascending order:\n\n```js sort: {y: \"x\"} ```\n\nFor different sort options for different scales, replace the channel name with a *value* object and per-scale options:\n\n```js sort: {y: {value: \"-x\"}} ```\n\nWhen sorting the mark’s index, the **sort** option is instead one of:\n\n- a channel value definition for sorting given values in ascending order\n- a {value, order} object for sorting given values\n- a {channel, order} object for sorting the named channel’s values" + }, + "stroke": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke" + }, + "strokeDasharray": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dasharray][1]; a constant number indicating the length in pixels of alternating dashes and gaps, or a constant string of numbers separated by spaces or commas (_e.g._, *10 2* for dashes of 10 pixels separated by gaps of 2 pixels), or *none* (the default) for no dashing\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dasharray" + }, + "strokeDashoffset": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dashoffset][1]; a constant indicating the offset in pixels of the first dash along the stroke; defaults to zero.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dashoffset" + }, + "strokeLinecap": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linecap][1]; a constant specifying how to cap stroked paths, such as *butt*, *round*, or *square*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linecap" + }, + "strokeLinejoin": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linejoin][1]; a constant specifying how to join stroked paths, such as *bevel*, *miter*, *miter-clip*, or *round*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linejoin" + }, + "strokeMiterlimit": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-miterlimit][1]; a constant number specifying how to limit the length of *miter* joins on stroked paths.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-miterlimit" + }, + "strokeOpacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-opacity" + }, + "strokeWidth": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-width][1]; a constant number in pixels, or a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-width" + }, + "target": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [target][1]; a constant string specifying the target window (_e.g._,\n*_blank*) for clickable links; used in conjunction with the **href** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/target" + }, + "tension": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The tension option only has an effect on bundle, cardinal and Catmull–Rom splines (*bundle*, *cardinal*, *cardinal-open*, *cardinal-closed*,\n*catmull-rom*, *catmull-rom-open*, and *catmull-rom-closed*). For bundle splines, it corresponds to [beta][1]; for cardinal splines, [tension][2]; for Catmull–Rom splines, [alpha][3].\n\n[1]: https://d3js.org/d3-shape/curve#curveBundle_beta [2]: https://d3js.org/d3-shape/curve#curveCardinal_tension [3]: https://d3js.org/d3-shape/curve#curveCatmullRom_alpha" + }, + "tip": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/TipPointer" + }, + { + "properties": { + "anchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The tip anchor specifies how to orient the tip box relative to its anchor position; it refers to the part of the tip box that is attached to the anchor point. For example, the *top-left* anchor places the top-left corner of tip box near the anchor position, hence placing the tip box below and to the right of the anchor position." + }, + "fontFamily": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font-family][1]; a constant; defaults to the plot’s font family, which is typically [*system-ui*][2].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-family [2]: https://drafts.csswg.org/css-fonts-4/#valdef-font-family-system-ui" + }, + "fontSize": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font size][1] in pixels; either a constant or a channel; defaults to the plot’s font size, which is typically 10. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-size" + }, + "fontStyle": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font style][1]; a constant; defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-style" + }, + "fontVariant": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font variant][1]; a constant; if the **text** channel contains numbers or dates, defaults to *tabular-nums* to facilitate comparing numbers; otherwise defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant" + }, + "fontWeight": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font weight][1]; a constant; defaults to the plot’s font weight, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight" + }, + "format": { + "additionalProperties": false, + "description": "How channel values are formatted for display. If a format is a string, it is interpreted as a (UTC) time format for temporal channels, and otherwise a number format.", + "properties": { + "ariaLabel": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fill": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fillOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fontSize": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fx": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fy": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "geometry": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "height": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "href": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "length": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "opacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "path": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "r": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "rotate": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "src": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "stroke": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeWidth": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "symbol": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "text": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "title": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "weight": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "width": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "z": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + } + }, + "type": "object" + }, + "frameAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The frame anchor specifies defaults for **x** and **y** based on the plot’s frame; it may be one of the four sides (*top*, *right*, *bottom*, *left*), one of the four corners (*top-left*, *top-right*, *bottom-right*,\n*bottom-left*), or the *middle* of the frame. For example, for tips distributed horizontally at the top of the frame:\n\n```js Plot.tip(data, {x: \"date\", frameAnchor: \"top\"}) ```" + }, + "lineHeight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line height in ems; defaults to 1. The line height affects the (typically vertical) separation between adjacent baselines of text, as well as the separation between the text and its anchor point." + }, + "lineWidth": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line width in ems (e.g., 10 for about 20 characters); defaults to infinity, disabling wrapping and clipping.\n\nIf **textOverflow** is null, lines will be wrapped at the specified length. If a line is split at a soft hyphen (\\xad), a hyphen (-) will be displayed at the end of the line. If **textOverflow** is not null, lines will be clipped according to the given strategy." + }, + "monospace": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, changes the default **fontFamily** to *monospace*, and uses simplified monospaced text metrics calculations." + }, + "pathFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The image filter for the tip’s box; defaults to a drop shadow." + }, + "pointer": { + "$ref": "#/definitions/TipPointer" + }, + "pointerSize": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The size of the tip’s pointer in pixels; defaults to 12." + }, + "preferredAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If an explicit tip anchor is not specified, an anchor is chosen automatically such that the tip fits within the plot’s frame; if the preferred anchor fits, it is chosen." + }, + "textAnchor": { + "anyOf": [ + { + "const": "start", + "type": "string" + }, + { + "const": "middle", + "type": "string" + }, + { + "const": "end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [text anchor][1] controls how text is aligned (typically horizontally) relative to its anchor point; it is one of *start*, *end*, or *middle*. If the frame anchor is *left*, *top-left*, or *bottom-left*, the default text anchor is *start*; if the frame anchor is *right*, *top-right*, or\n*bottom-right*, the default is *end*; otherwise it is *middle*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/text-anchor" + }, + "textOverflow": { + "anyOf": [ + { + "type": "null" + }, + { + "const": "clip", + "type": "string" + }, + { + "const": "ellipsis", + "type": "string" + }, + { + "const": "clip-start", + "type": "string" + }, + { + "const": "clip-end", + "type": "string" + }, + { + "const": "ellipsis-start", + "type": "string" + }, + { + "const": "ellipsis-middle", + "type": "string" + }, + { + "const": "ellipsis-end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How truncate (or wrap) lines of text longer than the given **lineWidth**; one of:\n\n- null (default) - preserve overflowing characters (and wrap if needed)\n- *clip* or *clip-end* - remove characters from the end\n- *clip-start* - remove characters from the start\n- *ellipsis* or *ellipsis-end* - replace characters from the end with an ellipsis (…)\n- *ellipsis-start* - replace characters from the start with an ellipsis (…)\n- *ellipsis-middle* - replace characters from the middle with an ellipsis (…)\n\nIf no **title** was specified, if text requires truncation, a title containing the non-truncated text will be implicitly added." + }, + "textPadding": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The padding around the text in pixels; defaults to 8." + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + } + }, + "type": "object" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to generate a tooltip for this mark, and any tip options." + }, + "title": { + "$ref": "#/definitions/ChannelValue", + "description": "The title; a channel specifying accessible, short textual descriptions as strings (possibly with newlines). If the tip option is specified, the title will be displayed with an interactive tooltip instead of using the SVG [title element][1].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/title" + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel, typically bound to the *x* scale." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel, typically bound to the *y* scale." + }, + "z": { + "$ref": "#/definitions/ChannelValue", + "description": "An optional ordinal channel for grouping to produce multiple (possibly overlapping) triangulations." + } + }, + "required": [ + "data", + "mark" + ], + "type": "object" + }, + "DelaunayMesh": { + "additionalProperties": false, + "description": "The delaunayMesh mark.", + "properties": { + "ariaDescription": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-description][1]; a constant textual description.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-description" + }, + "ariaHidden": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-hidden][1] state; a constant indicating whether the element is exposed to an accessibility API.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-hidden" + }, + "ariaLabel": { + "$ref": "#/definitions/ChannelValue", + "description": "The [aria-label][1]; a channel specifying short textual labels representing the value in the accessibility tree.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-label" + }, + "clip": { + "anyOf": [ + { + "const": "frame", + "type": "string" + }, + { + "const": "sphere", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to clip the mark; one of:\n\n- *frame* or true - clip to the plot’s frame (inner area)\n- *sphere* - clip to the projected sphere (*e.g.*, front hemisphere)\n- null or false - do not clip\n\nThe *sphere* clip option requires a geographic projection." + }, + "curve": { + "anyOf": [ + { + "$ref": "#/definitions/Curve" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The curve (interpolation) method for connecting adjacent points. One of:\n\n- *basis* - a cubic basis spline (repeating the end points)\n- *basis-open* - an open cubic basis spline\n- *basis-closed* - a closed cubic basis spline\n- *bump-x* - a Bézier curve with horizontal tangents\n- *bump-y* - a Bézier curve with vertical tangents\n- *bundle* - a straightened cubic basis spline (suitable for lines only, not areas)\n- *cardinal* - a cubic cardinal spline (with one-sided differences at the ends)\n- *cardinal-open* - an open cubic cardinal spline\n- *cardinal-closed* - an closed cubic cardinal spline\n- *catmull-rom* - a cubic Catmull–Rom spline (with one-sided differences at the ends)\n- *catmull-rom-open* - an open cubic Catmull–Rom spline\n- *catmull-rom-closed* - a closed cubic Catmull–Rom spline\n- *linear* - a piecewise linear curve (*i.e.*, straight line segments)\n- *linear-closed* - a closed piecewise linear curve (*i.e.*, straight line segments)\n- *monotone-x* - a cubic spline that preserves monotonicity in *x*\n- *monotone-y* - a cubic spline that preserves monotonicity in *y*\n- *natural* - a natural cubic spline\n- *step* - a piecewise constant function where *y* changes at the midpoint of *x*\n- *step-after* - a piecewise constant function where *y* changes after *x*\n- *step-before* - a piecewise constant function where *x* changes after *y*" + }, + "data": { + "$ref": "#/definitions/PlotMarkData", + "description": "The data source for the mark." + }, + "dx": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The horizontal offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "dy": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The vertical offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "facet": { + "anyOf": [ + { + "const": "auto", + "type": "string" + }, + { + "const": "include", + "type": "string" + }, + { + "const": "exclude", + "type": "string" + }, + { + "const": "super", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to enable or disable faceting; one of:\n\n- *auto* (default) - automatically determine if this mark should be faceted\n- *include* (or true) - draw the subset of the mark’s data in the current facet\n- *exclude* - draw the subset of the mark’s data *not* in the current facet\n- *super* - draw this mark in a single frame that covers all facets\n- null (or false) - repeat this mark’s data across all facets (*i.e.*, no faceting)\n\nWhen a mark uses *super* faceting, it is not allowed to use position scales (*x*, *y*, *fx*, or *fy*); *super* faceting is intended for decorations, such as labels and legends.\n\nWhen top-level faceting is used, the default *auto* setting is equivalent to *include* when the mark data is strictly equal to the top-level facet data; otherwise it is equivalent to null. When the *include* or *exclude* facet mode is chosen, the mark data must be parallel to the top-level facet data: the data must have the same length and order. If the data are not parallel, then the wrong data may be shown in each facet. The default\n*auto* therefore requires strict equality (`===`) for safety, and using the facet data as mark data is recommended when using the *exclude* facet mode. (To construct parallel data safely, consider using [*array*.map][1] on the facet data.)\n\nWhen mark-level faceting is used, the default *auto* setting is equivalent to *include*: the mark will be faceted if either the **fx** or **fy** channel option (or both) is specified. The null or false option will disable faceting, while *exclude* draws the subset of the mark’s data *not* in the current facet.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map" + }, + "facetAnchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "right", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "const": "left", + "type": "string" + }, + { + "const": "top-left", + "type": "string" + }, + { + "const": "top-right", + "type": "string" + }, + { + "const": "bottom-left", + "type": "string" + }, + { + "const": "bottom-right", + "type": "string" + }, + { + "const": "top-empty", + "type": "string" + }, + { + "const": "right-empty", + "type": "string" + }, + { + "const": "bottom-empty", + "type": "string" + }, + { + "const": "left-empty", + "type": "string" + }, + { + "const": "empty", + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to place the mark with respect to facets; one of:\n\n- null (default for most marks) - display the mark in each non-empty facet\n- *top*, *right*, *bottom*, or *left* - display the mark only in facets on the given side\n- *top-empty*, *right-empty*, *bottom-empty*, or *left-empty* (default for axis marks) - display the mark only in facets that have empty space on the given side: either the margin, or an empty facet\n- *empty* - display the mark in empty facets only" + }, + "fill": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill" + }, + "fillOpacity": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill-opacity][1]; a constant number between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill-opacity" + }, + "filter": { + "$ref": "#/definitions/ChannelValue", + "description": "Applies a transform to filter the mark’s index according to the given channel values; only truthy values are retained.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "fx": { + "$ref": "#/definitions/ChannelValue", + "description": "The horizontal facet position channel, for mark-level faceting, bound to the *fx* scale." + }, + "fy": { + "$ref": "#/definitions/ChannelValue", + "description": "The vertical facet position channel, for mark-level faceting, bound to the\n*fy* scale." + }, + "href": { + "$ref": "#/definitions/ChannelValue", + "description": "The [href][1]; a channel specifying URLs for clickable links. May be used in conjunction with the **target** option to open links in another window.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/href" + }, + "imageFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A CSS [filter][1]; a constant string used to adjust the rendering of images, such as *blur(5px)*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/filter" + }, + "margin": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four mark margins: **marginTop**,\n**marginRight**, **marginBottom**, and **marginLeft**; typically defaults to 0, except for axis marks." + }, + "marginBottom": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s bottom margin; the minimum distance in pixels between the bottom edges of the inner and outer plot area." + }, + "marginLeft": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s left margin; the minimum distance in pixels between the left edges of the inner and outer plot area." + }, + "marginRight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s right margin; the minimum distance in pixels between the right edges of the mark’s inner and outer plot area." + }, + "marginTop": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s top margin; the minimum distance in pixels between the top edges of the inner and outer plot area." + }, + "mark": { + "const": "delaunayMesh", + "description": "A mark that draws a mesh of the Delaunay triangulation of the points given by the **x** and **y** channels. The **stroke** option defaults to _currentColor_, and the **strokeOpacity** defaults to 0.2; the **fill** option is not supported. When an aesthetic channel is specified (such as\n**stroke** or **strokeWidth**), the mesh inherits the corresponding channel value from one of its constituent points arbitrarily.\n\nIf **z** is specified, the input points are grouped by *z*, producing a separate Delaunay triangulation for each group.", + "type": "string" + }, + "marker": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for markerStart, markerMid, and markerEnd; one of:\n\n- a marker name such as *arrow* or *circle*\n- *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*" + }, + "markerEnd": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The marker for the ending point of a line segment; one of:\n\n- a marker name such as *arrow* or *circle*\n* *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*" + }, + "markerMid": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The marker for any middle (interior) points of a line segment. If the line segment only has a start and end point, this option has no effect. One of:\n\n- a marker name such as *arrow* or *circle*\n* *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*\n* a function - a custom marker function; see below" + }, + "markerStart": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The marker for the starting point of a line segment; one of:\n\n- a marker name such as *arrow* or *circle*\n* *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*" + }, + "mixBlendMode": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [mix-blend-mode][1]; a constant string specifying how to blend content such as *multiply*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode" + }, + "opacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally. For faster rendering, prefer the **strokeOpacity** or **fillOpacity** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/opacity" + }, + "paintOrder": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [paint-order][1]; a constant string specifying the order in which the\n**fill**, **stroke**, and any markers are drawn; defaults to *normal*, which draws the fill, then stroke, then markers; defaults to *stroke* for the text mark to create a “halo” around text to improve legibility.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/paint-order" + }, + "pointerEvents": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [pointer-events][1] property; a constant string such as *none*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/pointer-events" + }, + "reverse": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Applies a transform to reverse the order of the mark’s index, say for reverse input order." + }, + "select": { + "$ref": "#/definitions/SelectFilter", + "description": "Applies a filter transform after data is loaded to highlight selected values only. For example, `first` and `last` select the first or last values of series only (using the *z* channel to separate series). Meanwhile, `nearestX` and `nearestY` select the point nearest to the pointer along the *x* or *y* channel dimension. Unlike Mosaic selections, a mark level *select* is internal to the mark only, and does not populate a param or selection value to be shared across clients.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "shapeRendering": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [shape-rendering][1]; a constant string such as *crispEdges*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/shape-rendering" + }, + "sort": { + "anyOf": [ + { + "$ref": "#/definitions/SortOrder" + }, + { + "$ref": "#/definitions/ChannelDomainSort" + } + ], + "description": "Either applies a transform to sort the mark’s index by the specified channel values, or imputes ordinal scale domains from this mark’s channels.\n\nWhen imputing ordinal scale domains from channel values, the **sort** option is an object whose keys are ordinal scale names such as *x* or *fx*, and whose values are channel names such as *y*, *y1*, or *y2*. For example, to impute the *y* scale’s domain from the associated *x* channel values in ascending order:\n\n```js sort: {y: \"x\"} ```\n\nFor different sort options for different scales, replace the channel name with a *value* object and per-scale options:\n\n```js sort: {y: {value: \"-x\"}} ```\n\nWhen sorting the mark’s index, the **sort** option is instead one of:\n\n- a channel value definition for sorting given values in ascending order\n- a {value, order} object for sorting given values\n- a {channel, order} object for sorting the named channel’s values" + }, + "stroke": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke" + }, + "strokeDasharray": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dasharray][1]; a constant number indicating the length in pixels of alternating dashes and gaps, or a constant string of numbers separated by spaces or commas (_e.g._, *10 2* for dashes of 10 pixels separated by gaps of 2 pixels), or *none* (the default) for no dashing\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dasharray" + }, + "strokeDashoffset": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dashoffset][1]; a constant indicating the offset in pixels of the first dash along the stroke; defaults to zero.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dashoffset" + }, + "strokeLinecap": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linecap][1]; a constant specifying how to cap stroked paths, such as *butt*, *round*, or *square*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linecap" + }, + "strokeLinejoin": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linejoin][1]; a constant specifying how to join stroked paths, such as *bevel*, *miter*, *miter-clip*, or *round*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linejoin" + }, + "strokeMiterlimit": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-miterlimit][1]; a constant number specifying how to limit the length of *miter* joins on stroked paths.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-miterlimit" + }, + "strokeOpacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-opacity" + }, + "strokeWidth": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-width][1]; a constant number in pixels, or a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-width" + }, + "target": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [target][1]; a constant string specifying the target window (_e.g._,\n*_blank*) for clickable links; used in conjunction with the **href** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/target" + }, + "tension": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The tension option only has an effect on bundle, cardinal and Catmull–Rom splines (*bundle*, *cardinal*, *cardinal-open*, *cardinal-closed*,\n*catmull-rom*, *catmull-rom-open*, and *catmull-rom-closed*). For bundle splines, it corresponds to [beta][1]; for cardinal splines, [tension][2]; for Catmull–Rom splines, [alpha][3].\n\n[1]: https://d3js.org/d3-shape/curve#curveBundle_beta [2]: https://d3js.org/d3-shape/curve#curveCardinal_tension [3]: https://d3js.org/d3-shape/curve#curveCatmullRom_alpha" + }, + "tip": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/TipPointer" + }, + { + "properties": { + "anchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The tip anchor specifies how to orient the tip box relative to its anchor position; it refers to the part of the tip box that is attached to the anchor point. For example, the *top-left* anchor places the top-left corner of tip box near the anchor position, hence placing the tip box below and to the right of the anchor position." + }, + "fontFamily": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font-family][1]; a constant; defaults to the plot’s font family, which is typically [*system-ui*][2].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-family [2]: https://drafts.csswg.org/css-fonts-4/#valdef-font-family-system-ui" + }, + "fontSize": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font size][1] in pixels; either a constant or a channel; defaults to the plot’s font size, which is typically 10. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-size" + }, + "fontStyle": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font style][1]; a constant; defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-style" + }, + "fontVariant": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font variant][1]; a constant; if the **text** channel contains numbers or dates, defaults to *tabular-nums* to facilitate comparing numbers; otherwise defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant" + }, + "fontWeight": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font weight][1]; a constant; defaults to the plot’s font weight, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight" + }, + "format": { + "additionalProperties": false, + "description": "How channel values are formatted for display. If a format is a string, it is interpreted as a (UTC) time format for temporal channels, and otherwise a number format.", + "properties": { + "ariaLabel": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fill": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fillOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fontSize": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fx": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fy": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "geometry": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "height": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "href": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "length": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "opacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "path": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "r": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "rotate": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "src": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "stroke": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeWidth": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "symbol": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "text": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "title": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "weight": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "width": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "z": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + } + }, + "type": "object" + }, + "frameAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The frame anchor specifies defaults for **x** and **y** based on the plot’s frame; it may be one of the four sides (*top*, *right*, *bottom*, *left*), one of the four corners (*top-left*, *top-right*, *bottom-right*,\n*bottom-left*), or the *middle* of the frame. For example, for tips distributed horizontally at the top of the frame:\n\n```js Plot.tip(data, {x: \"date\", frameAnchor: \"top\"}) ```" + }, + "lineHeight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line height in ems; defaults to 1. The line height affects the (typically vertical) separation between adjacent baselines of text, as well as the separation between the text and its anchor point." + }, + "lineWidth": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line width in ems (e.g., 10 for about 20 characters); defaults to infinity, disabling wrapping and clipping.\n\nIf **textOverflow** is null, lines will be wrapped at the specified length. If a line is split at a soft hyphen (\\xad), a hyphen (-) will be displayed at the end of the line. If **textOverflow** is not null, lines will be clipped according to the given strategy." + }, + "monospace": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, changes the default **fontFamily** to *monospace*, and uses simplified monospaced text metrics calculations." + }, + "pathFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The image filter for the tip’s box; defaults to a drop shadow." + }, + "pointer": { + "$ref": "#/definitions/TipPointer" + }, + "pointerSize": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The size of the tip’s pointer in pixels; defaults to 12." + }, + "preferredAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If an explicit tip anchor is not specified, an anchor is chosen automatically such that the tip fits within the plot’s frame; if the preferred anchor fits, it is chosen." + }, + "textAnchor": { + "anyOf": [ + { + "const": "start", + "type": "string" + }, + { + "const": "middle", + "type": "string" + }, + { + "const": "end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [text anchor][1] controls how text is aligned (typically horizontally) relative to its anchor point; it is one of *start*, *end*, or *middle*. If the frame anchor is *left*, *top-left*, or *bottom-left*, the default text anchor is *start*; if the frame anchor is *right*, *top-right*, or\n*bottom-right*, the default is *end*; otherwise it is *middle*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/text-anchor" + }, + "textOverflow": { + "anyOf": [ + { + "type": "null" + }, + { + "const": "clip", + "type": "string" + }, + { + "const": "ellipsis", + "type": "string" + }, + { + "const": "clip-start", + "type": "string" + }, + { + "const": "clip-end", + "type": "string" + }, + { + "const": "ellipsis-start", + "type": "string" + }, + { + "const": "ellipsis-middle", + "type": "string" + }, + { + "const": "ellipsis-end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How truncate (or wrap) lines of text longer than the given **lineWidth**; one of:\n\n- null (default) - preserve overflowing characters (and wrap if needed)\n- *clip* or *clip-end* - remove characters from the end\n- *clip-start* - remove characters from the start\n- *ellipsis* or *ellipsis-end* - replace characters from the end with an ellipsis (…)\n- *ellipsis-start* - replace characters from the start with an ellipsis (…)\n- *ellipsis-middle* - replace characters from the middle with an ellipsis (…)\n\nIf no **title** was specified, if text requires truncation, a title containing the non-truncated text will be implicitly added." + }, + "textPadding": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The padding around the text in pixels; defaults to 8." + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + } + }, + "type": "object" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to generate a tooltip for this mark, and any tip options." + }, + "title": { + "$ref": "#/definitions/ChannelValue", + "description": "The title; a channel specifying accessible, short textual descriptions as strings (possibly with newlines). If the tip option is specified, the title will be displayed with an interactive tooltip instead of using the SVG [title element][1].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/title" + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel, typically bound to the *x* scale." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel, typically bound to the *y* scale." + }, + "z": { + "$ref": "#/definitions/ChannelValue", + "description": "An optional ordinal channel for grouping to produce multiple (possibly overlapping) triangulations." + } + }, + "required": [ + "data", + "mark" + ], + "type": "object" + }, + "DenseLine": { + "additionalProperties": false, + "description": "The denseLine mark.", + "properties": { + "ariaDescription": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-description][1]; a constant textual description.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-description" + }, + "ariaHidden": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-hidden][1] state; a constant indicating whether the element is exposed to an accessibility API.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-hidden" + }, + "ariaLabel": { + "$ref": "#/definitions/ChannelValue", + "description": "The [aria-label][1]; a channel specifying short textual labels representing the value in the accessibility tree.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-label" + }, + "bandwidth": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The kernel density bandwidth for smoothing, in pixels." + }, + "clip": { + "anyOf": [ + { + "const": "frame", + "type": "string" + }, + { + "const": "sphere", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to clip the mark; one of:\n\n- *frame* or true - clip to the plot’s frame (inner area)\n- *sphere* - clip to the projected sphere (*e.g.*, front hemisphere)\n- null or false - do not clip\n\nThe *sphere* clip option requires a geographic projection." + }, + "data": { + "$ref": "#/definitions/PlotMarkData", + "description": "The data source for the mark." + }, + "dx": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The horizontal offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "dy": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The vertical offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "facet": { + "anyOf": [ + { + "const": "auto", + "type": "string" + }, + { + "const": "include", + "type": "string" + }, + { + "const": "exclude", + "type": "string" + }, + { + "const": "super", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to enable or disable faceting; one of:\n\n- *auto* (default) - automatically determine if this mark should be faceted\n- *include* (or true) - draw the subset of the mark’s data in the current facet\n- *exclude* - draw the subset of the mark’s data *not* in the current facet\n- *super* - draw this mark in a single frame that covers all facets\n- null (or false) - repeat this mark’s data across all facets (*i.e.*, no faceting)\n\nWhen a mark uses *super* faceting, it is not allowed to use position scales (*x*, *y*, *fx*, or *fy*); *super* faceting is intended for decorations, such as labels and legends.\n\nWhen top-level faceting is used, the default *auto* setting is equivalent to *include* when the mark data is strictly equal to the top-level facet data; otherwise it is equivalent to null. When the *include* or *exclude* facet mode is chosen, the mark data must be parallel to the top-level facet data: the data must have the same length and order. If the data are not parallel, then the wrong data may be shown in each facet. The default\n*auto* therefore requires strict equality (`===`) for safety, and using the facet data as mark data is recommended when using the *exclude* facet mode. (To construct parallel data safely, consider using [*array*.map][1] on the facet data.)\n\nWhen mark-level faceting is used, the default *auto* setting is equivalent to *include*: the mark will be faceted if either the **fx** or **fy** channel option (or both) is specified. The null or false option will disable faceting, while *exclude* draws the subset of the mark’s data *not* in the current facet.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map" + }, + "facetAnchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "right", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "const": "left", + "type": "string" + }, + { + "const": "top-left", + "type": "string" + }, + { + "const": "top-right", + "type": "string" + }, + { + "const": "bottom-left", + "type": "string" + }, + { + "const": "bottom-right", + "type": "string" + }, + { + "const": "top-empty", + "type": "string" + }, + { + "const": "right-empty", + "type": "string" + }, + { + "const": "bottom-empty", + "type": "string" + }, + { + "const": "left-empty", + "type": "string" + }, + { + "const": "empty", + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to place the mark with respect to facets; one of:\n\n- null (default for most marks) - display the mark in each non-empty facet\n- *top*, *right*, *bottom*, or *left* - display the mark only in facets on the given side\n- *top-empty*, *right-empty*, *bottom-empty*, or *left-empty* (default for axis marks) - display the mark only in facets that have empty space on the given side: either the margin, or an empty facet\n- *empty* - display the mark in empty facets only" + }, + "fill": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The fill, typically bound to the *color* scale. Can be specified as a constant or a channel based on the input data. Use the special value `\"density\"` to map computed density values to pixel colors. Use an aggregate expression to instead visualize an aggregate value per raster bin. If fill is set to a constant color or to a non-aggregate field, opacity will be used to convey densities. If a non-aggregate (group by) field is provided, multiple rasters are created with a unique categorical color per layer." + }, + "fillOpacity": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The opacity, typically bound to the *opacity* scale. Can be specified as a constant or a channel based on the input data. Use the special value `\"density\"` to map computed density values to opacity. Use an aggregate expression to instead visualize an aggregate value per raster bin." + }, + "filter": { + "$ref": "#/definitions/ChannelValue", + "description": "Applies a transform to filter the mark’s index according to the given channel values; only truthy values are retained.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "fx": { + "$ref": "#/definitions/ChannelValue", + "description": "The horizontal facet position channel, for mark-level faceting, bound to the *fx* scale." + }, + "fy": { + "$ref": "#/definitions/ChannelValue", + "description": "The vertical facet position channel, for mark-level faceting, bound to the\n*fy* scale." + }, + "height": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The height (number of rows) of the grid, in actual pixels." + }, + "href": { + "$ref": "#/definitions/ChannelValue", + "description": "The [href][1]; a channel specifying URLs for clickable links. May be used in conjunction with the **target** option to open links in another window.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/href" + }, + "imageFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A CSS [filter][1]; a constant string used to adjust the rendering of images, such as *blur(5px)*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/filter" + }, + "imageRendering": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [image-rendering attribute][1]; defaults to *auto* (bilinear). The option may be set to *pixelated* to disable bilinear interpolation for a sharper image; however, note that this is not supported in WebKit.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/image-rendering" + }, + "interpolate": { + "anyOf": [ + { + "$ref": "#/definitions/GridInterpolate" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The spatial interpolation method; one of:\n\n- *none* - do not perform interpolation (the default), maps samples to single bins\n- *linear* - apply proportional linear interpolation across adjacent bins\n- *nearest* - assign each pixel to the closest sample’s value (Voronoi diagram)\n- *barycentric* - apply barycentric interpolation over the Delaunay triangulation\n- *random-walk* - apply a random walk from each pixel, stopping when near a sample" + }, + "margin": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four mark margins: **marginTop**,\n**marginRight**, **marginBottom**, and **marginLeft**; typically defaults to 0, except for axis marks." + }, + "marginBottom": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s bottom margin; the minimum distance in pixels between the bottom edges of the inner and outer plot area." + }, + "marginLeft": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s left margin; the minimum distance in pixels between the left edges of the inner and outer plot area." + }, + "marginRight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s right margin; the minimum distance in pixels between the right edges of the mark’s inner and outer plot area." + }, + "marginTop": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s top margin; the minimum distance in pixels between the top edges of the inner and outer plot area." + }, + "mark": { + "const": "denseLine", + "description": "A denseLine mark that plots line densities rather than point densities. The mark forms a binned raster grid and \"draws\" straight lines into it. To avoid over-weighting steep lines, by default each drawn series is normalized on a per-column basis to approximate arc length normalization. The values for each series are aggregated to form the line density, which is then drawn as an image similar to the raster mark.", + "type": "string" + }, + "mixBlendMode": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [mix-blend-mode][1]; a constant string specifying how to blend content such as *multiply*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode" + }, + "normalize": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Flag to perform approximate arc length normalization of line segments to prevent artifacts due to overcounting steep lines. Defaults to `true`." + }, + "opacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally. For faster rendering, prefer the **strokeOpacity** or **fillOpacity** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/opacity" + }, + "pad": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The bin padding, one of 1 (default) to include extra padding for the final bin, or 0 to make the bins flush with the maximum domain value." + }, + "paintOrder": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [paint-order][1]; a constant string specifying the order in which the\n**fill**, **stroke**, and any markers are drawn; defaults to *normal*, which draws the fill, then stroke, then markers; defaults to *stroke* for the text mark to create a “halo” around text to improve legibility.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/paint-order" + }, + "pixelSize": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The effective screen size of a raster pixel, used to determine the height and width of the raster from the frame’s dimensions; defaults to 1." + }, + "pointerEvents": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [pointer-events][1] property; a constant string such as *none*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/pointer-events" + }, + "reverse": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Applies a transform to reverse the order of the mark’s index, say for reverse input order." + }, + "select": { + "$ref": "#/definitions/SelectFilter", + "description": "Applies a filter transform after data is loaded to highlight selected values only. For example, `first` and `last` select the first or last values of series only (using the *z* channel to separate series). Meanwhile, `nearestX` and `nearestY` select the point nearest to the pointer along the *x* or *y* channel dimension. Unlike Mosaic selections, a mark level *select* is internal to the mark only, and does not populate a param or selection value to be shared across clients.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "shapeRendering": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [shape-rendering][1]; a constant string such as *crispEdges*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/shape-rendering" + }, + "sort": { + "anyOf": [ + { + "$ref": "#/definitions/SortOrder" + }, + { + "$ref": "#/definitions/ChannelDomainSort" + } + ], + "description": "Either applies a transform to sort the mark’s index by the specified channel values, or imputes ordinal scale domains from this mark’s channels.\n\nWhen imputing ordinal scale domains from channel values, the **sort** option is an object whose keys are ordinal scale names such as *x* or *fx*, and whose values are channel names such as *y*, *y1*, or *y2*. For example, to impute the *y* scale’s domain from the associated *x* channel values in ascending order:\n\n```js sort: {y: \"x\"} ```\n\nFor different sort options for different scales, replace the channel name with a *value* object and per-scale options:\n\n```js sort: {y: {value: \"-x\"}} ```\n\nWhen sorting the mark’s index, the **sort** option is instead one of:\n\n- a channel value definition for sorting given values in ascending order\n- a {value, order} object for sorting given values\n- a {channel, order} object for sorting the named channel’s values" + }, + "stroke": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke" + }, + "strokeDasharray": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dasharray][1]; a constant number indicating the length in pixels of alternating dashes and gaps, or a constant string of numbers separated by spaces or commas (_e.g._, *10 2* for dashes of 10 pixels separated by gaps of 2 pixels), or *none* (the default) for no dashing\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dasharray" + }, + "strokeDashoffset": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dashoffset][1]; a constant indicating the offset in pixels of the first dash along the stroke; defaults to zero.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dashoffset" + }, + "strokeLinecap": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linecap][1]; a constant specifying how to cap stroked paths, such as *butt*, *round*, or *square*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linecap" + }, + "strokeLinejoin": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linejoin][1]; a constant specifying how to join stroked paths, such as *bevel*, *miter*, *miter-clip*, or *round*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linejoin" + }, + "strokeMiterlimit": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-miterlimit][1]; a constant number specifying how to limit the length of *miter* joins on stroked paths.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-miterlimit" + }, + "strokeOpacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-opacity" + }, + "strokeWidth": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-width][1]; a constant number in pixels, or a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-width" + }, + "target": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [target][1]; a constant string specifying the target window (_e.g._,\n*_blank*) for clickable links; used in conjunction with the **href** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/target" + }, + "tip": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/TipPointer" + }, + { + "properties": { + "anchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The tip anchor specifies how to orient the tip box relative to its anchor position; it refers to the part of the tip box that is attached to the anchor point. For example, the *top-left* anchor places the top-left corner of tip box near the anchor position, hence placing the tip box below and to the right of the anchor position." + }, + "fontFamily": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font-family][1]; a constant; defaults to the plot’s font family, which is typically [*system-ui*][2].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-family [2]: https://drafts.csswg.org/css-fonts-4/#valdef-font-family-system-ui" + }, + "fontSize": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font size][1] in pixels; either a constant or a channel; defaults to the plot’s font size, which is typically 10. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-size" + }, + "fontStyle": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font style][1]; a constant; defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-style" + }, + "fontVariant": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font variant][1]; a constant; if the **text** channel contains numbers or dates, defaults to *tabular-nums* to facilitate comparing numbers; otherwise defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant" + }, + "fontWeight": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font weight][1]; a constant; defaults to the plot’s font weight, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight" + }, + "format": { + "additionalProperties": false, + "description": "How channel values are formatted for display. If a format is a string, it is interpreted as a (UTC) time format for temporal channels, and otherwise a number format.", + "properties": { + "ariaLabel": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fill": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fillOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fontSize": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fx": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fy": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "geometry": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "height": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "href": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "length": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "opacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "path": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "r": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "rotate": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "src": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "stroke": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeWidth": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "symbol": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "text": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "title": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "weight": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "width": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "z": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + } + }, + "type": "object" + }, + "frameAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The frame anchor specifies defaults for **x** and **y** based on the plot’s frame; it may be one of the four sides (*top*, *right*, *bottom*, *left*), one of the four corners (*top-left*, *top-right*, *bottom-right*,\n*bottom-left*), or the *middle* of the frame. For example, for tips distributed horizontally at the top of the frame:\n\n```js Plot.tip(data, {x: \"date\", frameAnchor: \"top\"}) ```" + }, + "lineHeight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line height in ems; defaults to 1. The line height affects the (typically vertical) separation between adjacent baselines of text, as well as the separation between the text and its anchor point." + }, + "lineWidth": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line width in ems (e.g., 10 for about 20 characters); defaults to infinity, disabling wrapping and clipping.\n\nIf **textOverflow** is null, lines will be wrapped at the specified length. If a line is split at a soft hyphen (\\xad), a hyphen (-) will be displayed at the end of the line. If **textOverflow** is not null, lines will be clipped according to the given strategy." + }, + "monospace": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, changes the default **fontFamily** to *monospace*, and uses simplified monospaced text metrics calculations." + }, + "pathFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The image filter for the tip’s box; defaults to a drop shadow." + }, + "pointer": { + "$ref": "#/definitions/TipPointer" + }, + "pointerSize": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The size of the tip’s pointer in pixels; defaults to 12." + }, + "preferredAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If an explicit tip anchor is not specified, an anchor is chosen automatically such that the tip fits within the plot’s frame; if the preferred anchor fits, it is chosen." + }, + "textAnchor": { + "anyOf": [ + { + "const": "start", + "type": "string" + }, + { + "const": "middle", + "type": "string" + }, + { + "const": "end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [text anchor][1] controls how text is aligned (typically horizontally) relative to its anchor point; it is one of *start*, *end*, or *middle*. If the frame anchor is *left*, *top-left*, or *bottom-left*, the default text anchor is *start*; if the frame anchor is *right*, *top-right*, or\n*bottom-right*, the default is *end*; otherwise it is *middle*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/text-anchor" + }, + "textOverflow": { + "anyOf": [ + { + "type": "null" + }, + { + "const": "clip", + "type": "string" + }, + { + "const": "ellipsis", + "type": "string" + }, + { + "const": "clip-start", + "type": "string" + }, + { + "const": "clip-end", + "type": "string" + }, + { + "const": "ellipsis-start", + "type": "string" + }, + { + "const": "ellipsis-middle", + "type": "string" + }, + { + "const": "ellipsis-end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How truncate (or wrap) lines of text longer than the given **lineWidth**; one of:\n\n- null (default) - preserve overflowing characters (and wrap if needed)\n- *clip* or *clip-end* - remove characters from the end\n- *clip-start* - remove characters from the start\n- *ellipsis* or *ellipsis-end* - replace characters from the end with an ellipsis (…)\n- *ellipsis-start* - replace characters from the start with an ellipsis (…)\n- *ellipsis-middle* - replace characters from the middle with an ellipsis (…)\n\nIf no **title** was specified, if text requires truncation, a title containing the non-truncated text will be implicitly added." + }, + "textPadding": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The padding around the text in pixels; defaults to 8." + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + } + }, + "type": "object" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to generate a tooltip for this mark, and any tip options." + }, + "title": { + "$ref": "#/definitions/ChannelValue", + "description": "The title; a channel specifying accessible, short textual descriptions as strings (possibly with newlines). If the tip option is specified, the title will be displayed with an interactive tooltip instead of using the SVG [title element][1].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/title" + }, + "width": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The width (number of columns) of the grid, in actual pixels." + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel, typically bound to the *x* scale. Domain values are binned into a grid with *width* horizontal bins." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel, typically bound to the *y* scale. Domain values are binned into a grid with *height* vertical bins." + }, + "z": { + "$ref": "#/definitions/ChannelValue", + "description": "A ordinal channel for grouping data into series to be drawn as separate lines." + } + }, + "required": [ + "data", + "mark" + ], + "type": "object" + }, + "DenseRank": { + "additionalProperties": false, + "properties": { + "dense_rank": { + "anyOf": [ + { + "type": "null" + }, + { + "maxItems": 0, + "minItems": 0, + "type": "array" + } + ], + "description": "Compute the dense row rank (no gaps) over an ordered window partition. Sorting ties do not result in gaps in the rank numbers ( [1, 1, 2, ...])." + }, + "orderby": { + "anyOf": [ + { + "$ref": "#/definitions/TransformField" + }, + { + "items": { + "$ref": "#/definitions/TransformField" + }, + "type": "array" + } + ] + }, + "partitionby": { + "anyOf": [ + { + "$ref": "#/definitions/TransformField" + }, + { + "items": { + "$ref": "#/definitions/TransformField" + }, + "type": "array" + } + ] + }, + "range": { + "anyOf": [ + { + "items": { + "type": [ + "number", + "null" + ] + }, + "type": "array" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "rows": { + "anyOf": [ + { + "items": { + "type": [ + "number", + "null" + ] + }, + "type": "array" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + } + }, + "required": [ + "dense_rank" + ], + "type": "object" + }, + "Density": { + "additionalProperties": false, + "description": "The density mark for 2D densities.", + "properties": { + "ariaDescription": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-description][1]; a constant textual description.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-description" + }, + "ariaHidden": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-hidden][1] state; a constant indicating whether the element is exposed to an accessibility API.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-hidden" + }, + "ariaLabel": { + "$ref": "#/definitions/ChannelValue", + "description": "The [aria-label][1]; a channel specifying short textual labels representing the value in the accessibility tree.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-label" + }, + "bandwidth": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The kernel density bandwidth for smoothing, in pixels." + }, + "clip": { + "anyOf": [ + { + "const": "frame", + "type": "string" + }, + { + "const": "sphere", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to clip the mark; one of:\n\n- *frame* or true - clip to the plot’s frame (inner area)\n- *sphere* - clip to the projected sphere (*e.g.*, front hemisphere)\n- null or false - do not clip\n\nThe *sphere* clip option requires a geographic projection." + }, + "data": { + "$ref": "#/definitions/PlotMarkData", + "description": "The data source for the mark." + }, + "dx": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The horizontal offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "dy": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The vertical offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "facet": { + "anyOf": [ + { + "const": "auto", + "type": "string" + }, + { + "const": "include", + "type": "string" + }, + { + "const": "exclude", + "type": "string" + }, + { + "const": "super", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to enable or disable faceting; one of:\n\n- *auto* (default) - automatically determine if this mark should be faceted\n- *include* (or true) - draw the subset of the mark’s data in the current facet\n- *exclude* - draw the subset of the mark’s data *not* in the current facet\n- *super* - draw this mark in a single frame that covers all facets\n- null (or false) - repeat this mark’s data across all facets (*i.e.*, no faceting)\n\nWhen a mark uses *super* faceting, it is not allowed to use position scales (*x*, *y*, *fx*, or *fy*); *super* faceting is intended for decorations, such as labels and legends.\n\nWhen top-level faceting is used, the default *auto* setting is equivalent to *include* when the mark data is strictly equal to the top-level facet data; otherwise it is equivalent to null. When the *include* or *exclude* facet mode is chosen, the mark data must be parallel to the top-level facet data: the data must have the same length and order. If the data are not parallel, then the wrong data may be shown in each facet. The default\n*auto* therefore requires strict equality (`===`) for safety, and using the facet data as mark data is recommended when using the *exclude* facet mode. (To construct parallel data safely, consider using [*array*.map][1] on the facet data.)\n\nWhen mark-level faceting is used, the default *auto* setting is equivalent to *include*: the mark will be faceted if either the **fx** or **fy** channel option (or both) is specified. The null or false option will disable faceting, while *exclude* draws the subset of the mark’s data *not* in the current facet.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map" + }, + "facetAnchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "right", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "const": "left", + "type": "string" + }, + { + "const": "top-left", + "type": "string" + }, + { + "const": "top-right", + "type": "string" + }, + { + "const": "bottom-left", + "type": "string" + }, + { + "const": "bottom-right", + "type": "string" + }, + { + "const": "top-empty", + "type": "string" + }, + { + "const": "right-empty", + "type": "string" + }, + { + "const": "bottom-empty", + "type": "string" + }, + { + "const": "left-empty", + "type": "string" + }, + { + "const": "empty", + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to place the mark with respect to facets; one of:\n\n- null (default for most marks) - display the mark in each non-empty facet\n- *top*, *right*, *bottom*, or *left* - display the mark only in facets on the given side\n- *top-empty*, *right-empty*, *bottom-empty*, or *left-empty* (default for axis marks) - display the mark only in facets that have empty space on the given side: either the margin, or an empty facet\n- *empty* - display the mark in empty facets only" + }, + "fill": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill" + }, + "fillOpacity": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill-opacity][1]; a constant number between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill-opacity" + }, + "filter": { + "$ref": "#/definitions/ChannelValue", + "description": "Applies a transform to filter the mark’s index according to the given channel values; only truthy values are retained.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "fontFamily": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font-family][1]; a constant; defaults to the plot’s font family, which is typically [*system-ui*][2].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-family [2]: https://drafts.csswg.org/css-fonts-4/#valdef-font-family-system-ui" + }, + "fontSize": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font size][1] in pixels; either a constant or a channel; defaults to the plot’s font size, which is typically 10. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-size" + }, + "fontStyle": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font style][1]; a constant; defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-style" + }, + "fontVariant": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font variant][1]; a constant; if the **text** channel contains numbers or dates, defaults to *tabular-nums* to facilitate comparing numbers; otherwise defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant" + }, + "fontWeight": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font weight][1]; a constant; defaults to the plot’s font weight, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight" + }, + "frameAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The frame anchor specifies defaults for **x** and **y** based on the plot’s frame; it may be one of the four sides (*top*, *right*, *bottom*, *left*), one of the four corners (*top-left*, *top-right*, *bottom-right*,\n*bottom-left*), or the *middle* of the frame. For example, for dots distributed horizontally at the top of the frame:\n\n```js Plot.dot(data, {x: \"date\", frameAnchor: \"top\"}) ```" + }, + "fx": { + "$ref": "#/definitions/ChannelValue", + "description": "The horizontal facet position channel, for mark-level faceting, bound to the *fx* scale." + }, + "fy": { + "$ref": "#/definitions/ChannelValue", + "description": "The vertical facet position channel, for mark-level faceting, bound to the\n*fy* scale." + }, + "height": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The height (number of rows) of the grid, in actual pixels." + }, + "href": { + "$ref": "#/definitions/ChannelValue", + "description": "The [href][1]; a channel specifying URLs for clickable links. May be used in conjunction with the **target** option to open links in another window.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/href" + }, + "imageFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A CSS [filter][1]; a constant string used to adjust the rendering of images, such as *blur(5px)*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/filter" + }, + "interpolate": { + "anyOf": [ + { + "$ref": "#/definitions/GridInterpolate" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The spatial interpolation method; one of:\n\n- *none* - do not perform interpolation (the default), maps samples to single bins\n- *linear* - apply proportional linear interpolation across adjacent bins\n- *nearest* - assign each pixel to the closest sample’s value (Voronoi diagram)\n- *barycentric* - apply barycentric interpolation over the Delaunay triangulation\n- *random-walk* - apply a random walk from each pixel, stopping when near a sample" + }, + "lineHeight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line height in ems; defaults to 1. The line height affects the (typically vertical) separation between adjacent baselines of text, as well as the separation between the text and its anchor point." + }, + "lineWidth": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line width in ems (e.g., 10 for about 20 characters); defaults to infinity, disabling wrapping and clipping.\n\nIf **textOverflow** is null, lines will be wrapped at the specified length. If a line is split at a soft hyphen (\\xad), a hyphen (-) will be displayed at the end of the line. If **textOverflow** is not null, lines will be clipped according to the given strategy." + }, + "margin": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four mark margins: **marginTop**,\n**marginRight**, **marginBottom**, and **marginLeft**; typically defaults to 0, except for axis marks." + }, + "marginBottom": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s bottom margin; the minimum distance in pixels between the bottom edges of the inner and outer plot area." + }, + "marginLeft": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s left margin; the minimum distance in pixels between the left edges of the inner and outer plot area." + }, + "marginRight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s right margin; the minimum distance in pixels between the right edges of the mark’s inner and outer plot area." + }, + "marginTop": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s top margin; the minimum distance in pixels between the top edges of the inner and outer plot area." + }, + "mark": { + "const": "density", + "description": "A 2D density mark that shows smoothed point cloud densities along two dimensions. The mark bins the data, counts the number of records that fall into each bin, and smooths the resulting counts, then plots the smoothed distribution, by default using a circular dot mark. The density mark calculates density values that can be mapped to encoding channels such as fill or r using the special field name \"density\".\n\nSet the *type* property to use a different base mark type.", + "type": "string" + }, + "mixBlendMode": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [mix-blend-mode][1]; a constant string specifying how to blend content such as *multiply*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode" + }, + "monospace": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, changes the default **fontFamily** to *monospace*, and uses simplified monospaced text metrics calculations." + }, + "opacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally. For faster rendering, prefer the **strokeOpacity** or **fillOpacity** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/opacity" + }, + "pad": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The bin padding, one of 1 (default) to include extra padding for the final bin, or 0 to make the bins flush with the maximum domain value." + }, + "paintOrder": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [paint-order][1]; a constant string specifying the order in which the\n**fill**, **stroke**, and any markers are drawn; defaults to *normal*, which draws the fill, then stroke, then markers; defaults to *stroke* for the text mark to create a “halo” around text to improve legibility.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/paint-order" + }, + "pixelSize": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The effective screen size of a raster pixel, used to determine the height and width of the raster from the frame’s dimensions; defaults to 1." + }, + "pointerEvents": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [pointer-events][1] property; a constant string such as *none*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/pointer-events" + }, + "r": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The radius of dots; either a channel or constant. When a number, it is interpreted as a constant radius in pixels. Otherwise it is interpreted as a channel, typically bound to the *r* channel, which defaults to the *sqrt* type for proportional symbols. The radius defaults to 4.5 pixels when using the **symbol** channel, and otherwise 3 pixels. Dots with a nonpositive radius are not drawn." + }, + "reverse": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Applies a transform to reverse the order of the mark’s index, say for reverse input order." + }, + "rotate": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The rotation angle of dots in degrees clockwise; either a channel or a constant. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel. Defaults to 0°, pointing up." + }, + "select": { + "$ref": "#/definitions/SelectFilter", + "description": "Applies a filter transform after data is loaded to highlight selected values only. For example, `first` and `last` select the first or last values of series only (using the *z* channel to separate series). Meanwhile, `nearestX` and `nearestY` select the point nearest to the pointer along the *x* or *y* channel dimension. Unlike Mosaic selections, a mark level *select* is internal to the mark only, and does not populate a param or selection value to be shared across clients.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "shapeRendering": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [shape-rendering][1]; a constant string such as *crispEdges*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/shape-rendering" + }, + "sort": { + "anyOf": [ + { + "$ref": "#/definitions/SortOrder" + }, + { + "$ref": "#/definitions/ChannelDomainSort" + } + ], + "description": "Either applies a transform to sort the mark’s index by the specified channel values, or imputes ordinal scale domains from this mark’s channels.\n\nWhen imputing ordinal scale domains from channel values, the **sort** option is an object whose keys are ordinal scale names such as *x* or *fx*, and whose values are channel names such as *y*, *y1*, or *y2*. For example, to impute the *y* scale’s domain from the associated *x* channel values in ascending order:\n\n```js sort: {y: \"x\"} ```\n\nFor different sort options for different scales, replace the channel name with a *value* object and per-scale options:\n\n```js sort: {y: {value: \"-x\"}} ```\n\nWhen sorting the mark’s index, the **sort** option is instead one of:\n\n- a channel value definition for sorting given values in ascending order\n- a {value, order} object for sorting given values\n- a {channel, order} object for sorting the named channel’s values" + }, + "stroke": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke" + }, + "strokeDasharray": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dasharray][1]; a constant number indicating the length in pixels of alternating dashes and gaps, or a constant string of numbers separated by spaces or commas (_e.g._, *10 2* for dashes of 10 pixels separated by gaps of 2 pixels), or *none* (the default) for no dashing\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dasharray" + }, + "strokeDashoffset": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dashoffset][1]; a constant indicating the offset in pixels of the first dash along the stroke; defaults to zero.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dashoffset" + }, + "strokeLinecap": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linecap][1]; a constant specifying how to cap stroked paths, such as *butt*, *round*, or *square*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linecap" + }, + "strokeLinejoin": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linejoin][1]; a constant specifying how to join stroked paths, such as *bevel*, *miter*, *miter-clip*, or *round*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linejoin" + }, + "strokeMiterlimit": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-miterlimit][1]; a constant number specifying how to limit the length of *miter* joins on stroked paths.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-miterlimit" + }, + "strokeOpacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-opacity" + }, + "strokeWidth": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-width][1]; a constant number in pixels, or a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-width" + }, + "symbol": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/SymbolType" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The categorical symbol; either a channel or a constant. A constant symbol can be specified by a valid symbol name such as *star*, or a symbol object (implementing the draw method); otherwise it is interpreted as a channel. Defaults to *circle* for the **dot** mark, and *hexagon* for the\n**hexagon** mark.\n\nIf the **symbol** channel’s values are all symbols, symbol names, or nullish, the channel is unscaled (values are interpreted literally); otherwise, the channel is bound to the *symbol* scale." + }, + "target": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [target][1]; a constant string specifying the target window (_e.g._,\n*_blank*) for clickable links; used in conjunction with the **href** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/target" + }, + "textAnchor": { + "anyOf": [ + { + "const": "start", + "type": "string" + }, + { + "const": "middle", + "type": "string" + }, + { + "const": "end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [text anchor][1] controls how text is aligned (typically horizontally) relative to its anchor point; it is one of *start*, *end*, or *middle*. If the frame anchor is *left*, *top-left*, or *bottom-left*, the default text anchor is *start*; if the frame anchor is *right*, *top-right*, or\n*bottom-right*, the default is *end*; otherwise it is *middle*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/text-anchor" + }, + "textOverflow": { + "anyOf": [ + { + "type": "null" + }, + { + "const": "clip", + "type": "string" + }, + { + "const": "ellipsis", + "type": "string" + }, + { + "const": "clip-start", + "type": "string" + }, + { + "const": "clip-end", + "type": "string" + }, + { + "const": "ellipsis-start", + "type": "string" + }, + { + "const": "ellipsis-middle", + "type": "string" + }, + { + "const": "ellipsis-end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How truncate (or wrap) lines of text longer than the given **lineWidth**; one of:\n\n- null (default) - preserve overflowing characters (and wrap if needed)\n- *clip* or *clip-end* - remove characters from the end\n- *clip-start* - remove characters from the start\n- *ellipsis* or *ellipsis-end* - replace characters from the end with an ellipsis (…)\n- *ellipsis-start* - replace characters from the start with an ellipsis (…)\n- *ellipsis-middle* - replace characters from the middle with an ellipsis (…)\n\nIf no **title** was specified, if text requires truncation, a title containing the non-truncated text will be implicitly added." + }, + "tip": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/TipPointer" + }, + { + "properties": { + "anchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The tip anchor specifies how to orient the tip box relative to its anchor position; it refers to the part of the tip box that is attached to the anchor point. For example, the *top-left* anchor places the top-left corner of tip box near the anchor position, hence placing the tip box below and to the right of the anchor position." + }, + "fontFamily": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font-family][1]; a constant; defaults to the plot’s font family, which is typically [*system-ui*][2].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-family [2]: https://drafts.csswg.org/css-fonts-4/#valdef-font-family-system-ui" + }, + "fontSize": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font size][1] in pixels; either a constant or a channel; defaults to the plot’s font size, which is typically 10. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-size" + }, + "fontStyle": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font style][1]; a constant; defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-style" + }, + "fontVariant": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font variant][1]; a constant; if the **text** channel contains numbers or dates, defaults to *tabular-nums* to facilitate comparing numbers; otherwise defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant" + }, + "fontWeight": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font weight][1]; a constant; defaults to the plot’s font weight, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight" + }, + "format": { + "additionalProperties": false, + "description": "How channel values are formatted for display. If a format is a string, it is interpreted as a (UTC) time format for temporal channels, and otherwise a number format.", + "properties": { + "ariaLabel": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fill": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fillOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fontSize": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fx": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fy": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "geometry": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "height": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "href": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "length": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "opacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "path": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "r": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "rotate": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "src": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "stroke": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeWidth": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "symbol": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "text": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "title": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "weight": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "width": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "z": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + } + }, + "type": "object" + }, + "frameAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The frame anchor specifies defaults for **x** and **y** based on the plot’s frame; it may be one of the four sides (*top*, *right*, *bottom*, *left*), one of the four corners (*top-left*, *top-right*, *bottom-right*,\n*bottom-left*), or the *middle* of the frame. For example, for tips distributed horizontally at the top of the frame:\n\n```js Plot.tip(data, {x: \"date\", frameAnchor: \"top\"}) ```" + }, + "lineHeight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line height in ems; defaults to 1. The line height affects the (typically vertical) separation between adjacent baselines of text, as well as the separation between the text and its anchor point." + }, + "lineWidth": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line width in ems (e.g., 10 for about 20 characters); defaults to infinity, disabling wrapping and clipping.\n\nIf **textOverflow** is null, lines will be wrapped at the specified length. If a line is split at a soft hyphen (\\xad), a hyphen (-) will be displayed at the end of the line. If **textOverflow** is not null, lines will be clipped according to the given strategy." + }, + "monospace": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, changes the default **fontFamily** to *monospace*, and uses simplified monospaced text metrics calculations." + }, + "pathFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The image filter for the tip’s box; defaults to a drop shadow." + }, + "pointer": { + "$ref": "#/definitions/TipPointer" + }, + "pointerSize": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The size of the tip’s pointer in pixels; defaults to 12." + }, + "preferredAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If an explicit tip anchor is not specified, an anchor is chosen automatically such that the tip fits within the plot’s frame; if the preferred anchor fits, it is chosen." + }, + "textAnchor": { + "anyOf": [ + { + "const": "start", + "type": "string" + }, + { + "const": "middle", + "type": "string" + }, + { + "const": "end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [text anchor][1] controls how text is aligned (typically horizontally) relative to its anchor point; it is one of *start*, *end*, or *middle*. If the frame anchor is *left*, *top-left*, or *bottom-left*, the default text anchor is *start*; if the frame anchor is *right*, *top-right*, or\n*bottom-right*, the default is *end*; otherwise it is *middle*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/text-anchor" + }, + "textOverflow": { + "anyOf": [ + { + "type": "null" + }, + { + "const": "clip", + "type": "string" + }, + { + "const": "ellipsis", + "type": "string" + }, + { + "const": "clip-start", + "type": "string" + }, + { + "const": "clip-end", + "type": "string" + }, + { + "const": "ellipsis-start", + "type": "string" + }, + { + "const": "ellipsis-middle", + "type": "string" + }, + { + "const": "ellipsis-end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How truncate (or wrap) lines of text longer than the given **lineWidth**; one of:\n\n- null (default) - preserve overflowing characters (and wrap if needed)\n- *clip* or *clip-end* - remove characters from the end\n- *clip-start* - remove characters from the start\n- *ellipsis* or *ellipsis-end* - replace characters from the end with an ellipsis (…)\n- *ellipsis-start* - replace characters from the start with an ellipsis (…)\n- *ellipsis-middle* - replace characters from the middle with an ellipsis (…)\n\nIf no **title** was specified, if text requires truncation, a title containing the non-truncated text will be implicitly added." + }, + "textPadding": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The padding around the text in pixels; defaults to 8." + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + } + }, + "type": "object" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to generate a tooltip for this mark, and any tip options." + }, + "title": { + "$ref": "#/definitions/ChannelValue", + "description": "The title; a channel specifying accessible, short textual descriptions as strings (possibly with newlines). If the tip option is specified, the title will be displayed with an interactive tooltip instead of using the SVG [title element][1].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/title" + }, + "type": { + "anyOf": [ + { + "const": "dot", + "type": "string" + }, + { + "const": "circle", + "type": "string" + }, + { + "const": "hexagon", + "type": "string" + }, + { + "const": "cell", + "type": "string" + }, + { + "const": "text", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The basic mark type to use to render 2D density values. Defaults to a dot mark; cell and text marks are also supported." + }, + "width": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The width (number of columns) of the grid, in actual pixels." + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel, typically bound to the *x* scale. Domain values are binned into a grid with *width* horizontal bins." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel, typically bound to the *y* scale. Domain values are binned into a grid with *height* vertical bins." + }, + "z": { + "$ref": "#/definitions/ChannelValue", + "description": "An optional ordinal channel for grouping data into series." + } + }, + "required": [ + "data", + "mark" + ], + "type": "object" + }, + "DensityX": { + "anyOf": [ + { + "additionalProperties": false, + "properties": { + "ariaDescription": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-description][1]; a constant textual description.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-description" + }, + "ariaHidden": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-hidden][1] state; a constant indicating whether the element is exposed to an accessibility API.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-hidden" + }, + "ariaLabel": { + "$ref": "#/definitions/ChannelValue", + "description": "The [aria-label][1]; a channel specifying short textual labels representing the value in the accessibility tree.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-label" + }, + "bandwidth": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The kernel density bandwidth for smoothing, in pixels. Defaults to 20." + }, + "bins": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The number of bins over which to discretize the data prior to smoothing. Defaults to 1024." + }, + "clip": { + "anyOf": [ + { + "const": "frame", + "type": "string" + }, + { + "const": "sphere", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to clip the mark; one of:\n\n- *frame* or true - clip to the plot’s frame (inner area)\n- *sphere* - clip to the projected sphere (*e.g.*, front hemisphere)\n- null or false - do not clip\n\nThe *sphere* clip option requires a geographic projection." + }, + "curve": { + "anyOf": [ + { + "$ref": "#/definitions/Curve" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The curve (interpolation) method for connecting adjacent points. One of:\n\n- *basis* - a cubic basis spline (repeating the end points)\n- *basis-open* - an open cubic basis spline\n- *basis-closed* - a closed cubic basis spline\n- *bump-x* - a Bézier curve with horizontal tangents\n- *bump-y* - a Bézier curve with vertical tangents\n- *bundle* - a straightened cubic basis spline (suitable for lines only, not areas)\n- *cardinal* - a cubic cardinal spline (with one-sided differences at the ends)\n- *cardinal-open* - an open cubic cardinal spline\n- *cardinal-closed* - an closed cubic cardinal spline\n- *catmull-rom* - a cubic Catmull–Rom spline (with one-sided differences at the ends)\n- *catmull-rom-open* - an open cubic Catmull–Rom spline\n- *catmull-rom-closed* - a closed cubic Catmull–Rom spline\n- *linear* - a piecewise linear curve (*i.e.*, straight line segments)\n- *linear-closed* - a closed piecewise linear curve (*i.e.*, straight line segments)\n- *monotone-x* - a cubic spline that preserves monotonicity in *x*\n- *monotone-y* - a cubic spline that preserves monotonicity in *y*\n- *natural* - a natural cubic spline\n- *step* - a piecewise constant function where *y* changes at the midpoint of *x*\n- *step-after* - a piecewise constant function where *y* changes after *x*\n- *step-before* - a piecewise constant function where *x* changes after *y*" + }, + "data": { + "$ref": "#/definitions/PlotMarkData", + "description": "The data source for the mark." + }, + "dx": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The horizontal offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "dy": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The vertical offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "facet": { + "anyOf": [ + { + "const": "auto", + "type": "string" + }, + { + "const": "include", + "type": "string" + }, + { + "const": "exclude", + "type": "string" + }, + { + "const": "super", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to enable or disable faceting; one of:\n\n- *auto* (default) - automatically determine if this mark should be faceted\n- *include* (or true) - draw the subset of the mark’s data in the current facet\n- *exclude* - draw the subset of the mark’s data *not* in the current facet\n- *super* - draw this mark in a single frame that covers all facets\n- null (or false) - repeat this mark’s data across all facets (*i.e.*, no faceting)\n\nWhen a mark uses *super* faceting, it is not allowed to use position scales (*x*, *y*, *fx*, or *fy*); *super* faceting is intended for decorations, such as labels and legends.\n\nWhen top-level faceting is used, the default *auto* setting is equivalent to *include* when the mark data is strictly equal to the top-level facet data; otherwise it is equivalent to null. When the *include* or *exclude* facet mode is chosen, the mark data must be parallel to the top-level facet data: the data must have the same length and order. If the data are not parallel, then the wrong data may be shown in each facet. The default\n*auto* therefore requires strict equality (`===`) for safety, and using the facet data as mark data is recommended when using the *exclude* facet mode. (To construct parallel data safely, consider using [*array*.map][1] on the facet data.)\n\nWhen mark-level faceting is used, the default *auto* setting is equivalent to *include*: the mark will be faceted if either the **fx** or **fy** channel option (or both) is specified. The null or false option will disable faceting, while *exclude* draws the subset of the mark’s data *not* in the current facet.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map" + }, + "facetAnchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "right", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "const": "left", + "type": "string" + }, + { + "const": "top-left", + "type": "string" + }, + { + "const": "top-right", + "type": "string" + }, + { + "const": "bottom-left", + "type": "string" + }, + { + "const": "bottom-right", + "type": "string" + }, + { + "const": "top-empty", + "type": "string" + }, + { + "const": "right-empty", + "type": "string" + }, + { + "const": "bottom-empty", + "type": "string" + }, + { + "const": "left-empty", + "type": "string" + }, + { + "const": "empty", + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to place the mark with respect to facets; one of:\n\n- null (default for most marks) - display the mark in each non-empty facet\n- *top*, *right*, *bottom*, or *left* - display the mark only in facets on the given side\n- *top-empty*, *right-empty*, *bottom-empty*, or *left-empty* (default for axis marks) - display the mark only in facets that have empty space on the given side: either the margin, or an empty facet\n- *empty* - display the mark in empty facets only" + }, + "fill": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill" + }, + "fillOpacity": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill-opacity][1]; a constant number between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill-opacity" + }, + "filter": { + "$ref": "#/definitions/ChannelValue", + "description": "Applies a transform to filter the mark’s index according to the given channel values; only truthy values are retained.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "fx": { + "$ref": "#/definitions/ChannelValue", + "description": "The horizontal facet position channel, for mark-level faceting, bound to the *fx* scale." + }, + "fy": { + "$ref": "#/definitions/ChannelValue", + "description": "The vertical facet position channel, for mark-level faceting, bound to the\n*fy* scale." + }, + "href": { + "$ref": "#/definitions/ChannelValue", + "description": "The [href][1]; a channel specifying URLs for clickable links. May be used in conjunction with the **target** option to open links in another window.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/href" + }, + "imageFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A CSS [filter][1]; a constant string used to adjust the rendering of images, such as *blur(5px)*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/filter" + }, + "margin": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four mark margins: **marginTop**,\n**marginRight**, **marginBottom**, and **marginLeft**; typically defaults to 0, except for axis marks." + }, + "marginBottom": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s bottom margin; the minimum distance in pixels between the bottom edges of the inner and outer plot area." + }, + "marginLeft": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s left margin; the minimum distance in pixels between the left edges of the inner and outer plot area." + }, + "marginRight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s right margin; the minimum distance in pixels between the right edges of the mark’s inner and outer plot area." + }, + "marginTop": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s top margin; the minimum distance in pixels between the top edges of the inner and outer plot area." + }, + "mark": { + "const": "densityX", + "description": "A densityX mark that visualizes smoothed point cloud densities along the\n**x** dimension. The mark bins the data, counts the number of records that fall into each bin, smooths the resulting counts, and then plots the smoothed distribution, by default using an areaX mark.\n\nSet the *type* property to use a different base mark type.", + "type": "string" + }, + "mixBlendMode": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [mix-blend-mode][1]; a constant string specifying how to blend content such as *multiply*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode" + }, + "offset": { + "anyOf": [ + { + "$ref": "#/definitions/StackOffset" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "After stacking, an optional **offset** can be applied to translate and scale stacks, say to produce a streamgraph; defaults to null for a zero baseline (**y** = 0 for stackY, and **x** = 0 for stackX). If the *wiggle* offset is used, the default **order** changes to *inside-out*." + }, + "opacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally. For faster rendering, prefer the **strokeOpacity** or **fillOpacity** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/opacity" + }, + "order": { + "anyOf": [ + { + "$ref": "#/definitions/StackOrder" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The order in which stacks are layered; one of:\n\n- null (default) for input order\n- a named stack order method such as *inside-out* or *sum*\n- a field name, for natural order of the corresponding values\n- a function of data, for natural order of the corresponding values\n- an array of explicit **z** values in the desired order\n\nIf the *wiggle* **offset** is used, as for a streamgraph, the default changes to *inside-out*." + }, + "paintOrder": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [paint-order][1]; a constant string specifying the order in which the\n**fill**, **stroke**, and any markers are drawn; defaults to *normal*, which draws the fill, then stroke, then markers; defaults to *stroke* for the text mark to create a “halo” around text to improve legibility.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/paint-order" + }, + "pointerEvents": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [pointer-events][1] property; a constant string such as *none*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/pointer-events" + }, + "reverse": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Applies a transform to reverse the order of the mark’s index, say for reverse input order." + }, + "select": { + "$ref": "#/definitions/SelectFilter", + "description": "Applies a filter transform after data is loaded to highlight selected values only. For example, `first` and `last` select the first or last values of series only (using the *z* channel to separate series). Meanwhile, `nearestX` and `nearestY` select the point nearest to the pointer along the *x* or *y* channel dimension. Unlike Mosaic selections, a mark level *select* is internal to the mark only, and does not populate a param or selection value to be shared across clients.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "shapeRendering": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [shape-rendering][1]; a constant string such as *crispEdges*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/shape-rendering" + }, + "sort": { + "anyOf": [ + { + "$ref": "#/definitions/SortOrder" + }, + { + "$ref": "#/definitions/ChannelDomainSort" + } + ], + "description": "Either applies a transform to sort the mark’s index by the specified channel values, or imputes ordinal scale domains from this mark’s channels.\n\nWhen imputing ordinal scale domains from channel values, the **sort** option is an object whose keys are ordinal scale names such as *x* or *fx*, and whose values are channel names such as *y*, *y1*, or *y2*. For example, to impute the *y* scale’s domain from the associated *x* channel values in ascending order:\n\n```js sort: {y: \"x\"} ```\n\nFor different sort options for different scales, replace the channel name with a *value* object and per-scale options:\n\n```js sort: {y: {value: \"-x\"}} ```\n\nWhen sorting the mark’s index, the **sort** option is instead one of:\n\n- a channel value definition for sorting given values in ascending order\n- a {value, order} object for sorting given values\n- a {channel, order} object for sorting the named channel’s values" + }, + "stroke": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke" + }, + "strokeDasharray": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dasharray][1]; a constant number indicating the length in pixels of alternating dashes and gaps, or a constant string of numbers separated by spaces or commas (_e.g._, *10 2* for dashes of 10 pixels separated by gaps of 2 pixels), or *none* (the default) for no dashing\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dasharray" + }, + "strokeDashoffset": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dashoffset][1]; a constant indicating the offset in pixels of the first dash along the stroke; defaults to zero.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dashoffset" + }, + "strokeLinecap": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linecap][1]; a constant specifying how to cap stroked paths, such as *butt*, *round*, or *square*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linecap" + }, + "strokeLinejoin": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linejoin][1]; a constant specifying how to join stroked paths, such as *bevel*, *miter*, *miter-clip*, or *round*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linejoin" + }, + "strokeMiterlimit": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-miterlimit][1]; a constant number specifying how to limit the length of *miter* joins on stroked paths.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-miterlimit" + }, + "strokeOpacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-opacity" + }, + "strokeWidth": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-width][1]; a constant number in pixels, or a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-width" + }, + "target": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [target][1]; a constant string specifying the target window (_e.g._,\n*_blank*) for clickable links; used in conjunction with the **href** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/target" + }, + "tension": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The tension option only has an effect on bundle, cardinal and Catmull–Rom splines (*bundle*, *cardinal*, *cardinal-open*, *cardinal-closed*,\n*catmull-rom*, *catmull-rom-open*, and *catmull-rom-closed*). For bundle splines, it corresponds to [beta][1]; for cardinal splines, [tension][2]; for Catmull–Rom splines, [alpha][3].\n\n[1]: https://d3js.org/d3-shape/curve#curveBundle_beta [2]: https://d3js.org/d3-shape/curve#curveCardinal_tension [3]: https://d3js.org/d3-shape/curve#curveCatmullRom_alpha" + }, + "tip": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/TipPointer" + }, + { + "properties": { + "anchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The tip anchor specifies how to orient the tip box relative to its anchor position; it refers to the part of the tip box that is attached to the anchor point. For example, the *top-left* anchor places the top-left corner of tip box near the anchor position, hence placing the tip box below and to the right of the anchor position." + }, + "fontFamily": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font-family][1]; a constant; defaults to the plot’s font family, which is typically [*system-ui*][2].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-family [2]: https://drafts.csswg.org/css-fonts-4/#valdef-font-family-system-ui" + }, + "fontSize": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font size][1] in pixels; either a constant or a channel; defaults to the plot’s font size, which is typically 10. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-size" + }, + "fontStyle": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font style][1]; a constant; defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-style" + }, + "fontVariant": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font variant][1]; a constant; if the **text** channel contains numbers or dates, defaults to *tabular-nums* to facilitate comparing numbers; otherwise defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant" + }, + "fontWeight": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font weight][1]; a constant; defaults to the plot’s font weight, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight" + }, + "format": { + "additionalProperties": false, + "description": "How channel values are formatted for display. If a format is a string, it is interpreted as a (UTC) time format for temporal channels, and otherwise a number format.", + "properties": { + "ariaLabel": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fill": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fillOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fontSize": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fx": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fy": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "geometry": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "height": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "href": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "length": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "opacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "path": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "r": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "rotate": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "src": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "stroke": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeWidth": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "symbol": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "text": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "title": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "weight": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "width": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "z": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + } + }, + "type": "object" + }, + "frameAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The frame anchor specifies defaults for **x** and **y** based on the plot’s frame; it may be one of the four sides (*top*, *right*, *bottom*, *left*), one of the four corners (*top-left*, *top-right*, *bottom-right*,\n*bottom-left*), or the *middle* of the frame. For example, for tips distributed horizontally at the top of the frame:\n\n```js Plot.tip(data, {x: \"date\", frameAnchor: \"top\"}) ```" + }, + "lineHeight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line height in ems; defaults to 1. The line height affects the (typically vertical) separation between adjacent baselines of text, as well as the separation between the text and its anchor point." + }, + "lineWidth": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line width in ems (e.g., 10 for about 20 characters); defaults to infinity, disabling wrapping and clipping.\n\nIf **textOverflow** is null, lines will be wrapped at the specified length. If a line is split at a soft hyphen (\\xad), a hyphen (-) will be displayed at the end of the line. If **textOverflow** is not null, lines will be clipped according to the given strategy." + }, + "monospace": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, changes the default **fontFamily** to *monospace*, and uses simplified monospaced text metrics calculations." + }, + "pathFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The image filter for the tip’s box; defaults to a drop shadow." + }, + "pointer": { + "$ref": "#/definitions/TipPointer" + }, + "pointerSize": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The size of the tip’s pointer in pixels; defaults to 12." + }, + "preferredAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If an explicit tip anchor is not specified, an anchor is chosen automatically such that the tip fits within the plot’s frame; if the preferred anchor fits, it is chosen." + }, + "textAnchor": { + "anyOf": [ + { + "const": "start", + "type": "string" + }, + { + "const": "middle", + "type": "string" + }, + { + "const": "end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [text anchor][1] controls how text is aligned (typically horizontally) relative to its anchor point; it is one of *start*, *end*, or *middle*. If the frame anchor is *left*, *top-left*, or *bottom-left*, the default text anchor is *start*; if the frame anchor is *right*, *top-right*, or\n*bottom-right*, the default is *end*; otherwise it is *middle*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/text-anchor" + }, + "textOverflow": { + "anyOf": [ + { + "type": "null" + }, + { + "const": "clip", + "type": "string" + }, + { + "const": "ellipsis", + "type": "string" + }, + { + "const": "clip-start", + "type": "string" + }, + { + "const": "clip-end", + "type": "string" + }, + { + "const": "ellipsis-start", + "type": "string" + }, + { + "const": "ellipsis-middle", + "type": "string" + }, + { + "const": "ellipsis-end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How truncate (or wrap) lines of text longer than the given **lineWidth**; one of:\n\n- null (default) - preserve overflowing characters (and wrap if needed)\n- *clip* or *clip-end* - remove characters from the end\n- *clip-start* - remove characters from the start\n- *ellipsis* or *ellipsis-end* - replace characters from the end with an ellipsis (…)\n- *ellipsis-start* - replace characters from the start with an ellipsis (…)\n- *ellipsis-middle* - replace characters from the middle with an ellipsis (…)\n\nIf no **title** was specified, if text requires truncation, a title containing the non-truncated text will be implicitly added." + }, + "textPadding": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The padding around the text in pixels; defaults to 8." + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + } + }, + "type": "object" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to generate a tooltip for this mark, and any tip options." + }, + "title": { + "$ref": "#/definitions/ChannelValue", + "description": "The title; a channel specifying accessible, short textual descriptions as strings (possibly with newlines). If the tip option is specified, the title will be displayed with an interactive tooltip instead of using the SVG [title element][1].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/title" + }, + "type": { + "const": "areaX", + "description": "The basic mark type to use to render 1D density values. Defaults to an areaX mark; lineX, dotX, and textX marks are also supported.", + "type": "string" + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel, typically bound to the *y* scale; defaults to the zero-based index of the data [0, 1, 2, …]." + }, + "z": { + "$ref": "#/definitions/ChannelValue", + "description": "An optional ordinal channel for grouping data into (possibly stacked) series to be drawn as separate areas; defaults to **fill** if a channel, or\n**stroke** if a channel." + } + }, + "required": [ + "data", + "mark", + "type" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "ariaDescription": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-description][1]; a constant textual description.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-description" + }, + "ariaHidden": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-hidden][1] state; a constant indicating whether the element is exposed to an accessibility API.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-hidden" + }, + "ariaLabel": { + "$ref": "#/definitions/ChannelValue", + "description": "The [aria-label][1]; a channel specifying short textual labels representing the value in the accessibility tree.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-label" + }, + "bandwidth": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The kernel density bandwidth for smoothing, in pixels. Defaults to 20." + }, + "bins": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The number of bins over which to discretize the data prior to smoothing. Defaults to 1024." + }, + "clip": { + "anyOf": [ + { + "const": "frame", + "type": "string" + }, + { + "const": "sphere", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to clip the mark; one of:\n\n- *frame* or true - clip to the plot’s frame (inner area)\n- *sphere* - clip to the projected sphere (*e.g.*, front hemisphere)\n- null or false - do not clip\n\nThe *sphere* clip option requires a geographic projection." + }, + "curve": { + "anyOf": [ + { + "$ref": "#/definitions/Curve" + }, + { + "const": "auto", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The curve (interpolation) method for connecting adjacent points. One of:\n\n- *basis* - a cubic basis spline (repeating the end points)\n- *basis-open* - an open cubic basis spline\n- *basis-closed* - a closed cubic basis spline\n- *bump-x* - a Bézier curve with horizontal tangents\n- *bump-y* - a Bézier curve with vertical tangents\n- *bundle* - a straightened cubic basis spline (suitable for lines only, not areas)\n- *cardinal* - a cubic cardinal spline (with one-sided differences at the ends)\n- *cardinal-open* - an open cubic cardinal spline\n- *cardinal-closed* - an closed cubic cardinal spline\n- *catmull-rom* - a cubic Catmull–Rom spline (with one-sided differences at the ends)\n- *catmull-rom-open* - an open cubic Catmull–Rom spline\n- *catmull-rom-closed* - a closed cubic Catmull–Rom spline\n- *linear* - a piecewise linear curve (*i.e.*, straight line segments)\n- *linear-closed* - a closed piecewise linear curve (*i.e.*, straight line segments)\n- *monotone-x* - a cubic spline that preserves monotonicity in *x*\n- *monotone-y* - a cubic spline that preserves monotonicity in *y*\n- *natural* - a natural cubic spline\n- *step* - a piecewise constant function where *y* changes at the midpoint of *x*\n- *step-after* - a piecewise constant function where *y* changes after *x*\n- *step-before* - a piecewise constant function where *x* changes after *y*\n- *auto* (default) - like *linear*, but use the (possibly spherical) projection, if any\n\nThe *auto* curve is typically used in conjunction with a spherical projection to interpolate along geodesics." + }, + "data": { + "$ref": "#/definitions/PlotMarkData", + "description": "The data source for the mark." + }, + "dx": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The horizontal offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "dy": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The vertical offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "facet": { + "anyOf": [ + { + "const": "auto", + "type": "string" + }, + { + "const": "include", + "type": "string" + }, + { + "const": "exclude", + "type": "string" + }, + { + "const": "super", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to enable or disable faceting; one of:\n\n- *auto* (default) - automatically determine if this mark should be faceted\n- *include* (or true) - draw the subset of the mark’s data in the current facet\n- *exclude* - draw the subset of the mark’s data *not* in the current facet\n- *super* - draw this mark in a single frame that covers all facets\n- null (or false) - repeat this mark’s data across all facets (*i.e.*, no faceting)\n\nWhen a mark uses *super* faceting, it is not allowed to use position scales (*x*, *y*, *fx*, or *fy*); *super* faceting is intended for decorations, such as labels and legends.\n\nWhen top-level faceting is used, the default *auto* setting is equivalent to *include* when the mark data is strictly equal to the top-level facet data; otherwise it is equivalent to null. When the *include* or *exclude* facet mode is chosen, the mark data must be parallel to the top-level facet data: the data must have the same length and order. If the data are not parallel, then the wrong data may be shown in each facet. The default\n*auto* therefore requires strict equality (`===`) for safety, and using the facet data as mark data is recommended when using the *exclude* facet mode. (To construct parallel data safely, consider using [*array*.map][1] on the facet data.)\n\nWhen mark-level faceting is used, the default *auto* setting is equivalent to *include*: the mark will be faceted if either the **fx** or **fy** channel option (or both) is specified. The null or false option will disable faceting, while *exclude* draws the subset of the mark’s data *not* in the current facet.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map" + }, + "facetAnchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "right", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "const": "left", + "type": "string" + }, + { + "const": "top-left", + "type": "string" + }, + { + "const": "top-right", + "type": "string" + }, + { + "const": "bottom-left", + "type": "string" + }, + { + "const": "bottom-right", + "type": "string" + }, + { + "const": "top-empty", + "type": "string" + }, + { + "const": "right-empty", + "type": "string" + }, + { + "const": "bottom-empty", + "type": "string" + }, + { + "const": "left-empty", + "type": "string" + }, + { + "const": "empty", + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to place the mark with respect to facets; one of:\n\n- null (default for most marks) - display the mark in each non-empty facet\n- *top*, *right*, *bottom*, or *left* - display the mark only in facets on the given side\n- *top-empty*, *right-empty*, *bottom-empty*, or *left-empty* (default for axis marks) - display the mark only in facets that have empty space on the given side: either the margin, or an empty facet\n- *empty* - display the mark in empty facets only" + }, + "fill": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill" + }, + "fillOpacity": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill-opacity][1]; a constant number between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill-opacity" + }, + "filter": { + "$ref": "#/definitions/ChannelValue", + "description": "Applies a transform to filter the mark’s index according to the given channel values; only truthy values are retained.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "fx": { + "$ref": "#/definitions/ChannelValue", + "description": "The horizontal facet position channel, for mark-level faceting, bound to the *fx* scale." + }, + "fy": { + "$ref": "#/definitions/ChannelValue", + "description": "The vertical facet position channel, for mark-level faceting, bound to the\n*fy* scale." + }, + "href": { + "$ref": "#/definitions/ChannelValue", + "description": "The [href][1]; a channel specifying URLs for clickable links. May be used in conjunction with the **target** option to open links in another window.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/href" + }, + "imageFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A CSS [filter][1]; a constant string used to adjust the rendering of images, such as *blur(5px)*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/filter" + }, + "margin": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four mark margins: **marginTop**,\n**marginRight**, **marginBottom**, and **marginLeft**; typically defaults to 0, except for axis marks." + }, + "marginBottom": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s bottom margin; the minimum distance in pixels between the bottom edges of the inner and outer plot area." + }, + "marginLeft": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s left margin; the minimum distance in pixels between the left edges of the inner and outer plot area." + }, + "marginRight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s right margin; the minimum distance in pixels between the right edges of the mark’s inner and outer plot area." + }, + "marginTop": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s top margin; the minimum distance in pixels between the top edges of the inner and outer plot area." + }, + "mark": { + "const": "densityX", + "description": "A densityX mark that visualizes smoothed point cloud densities along the\n**x** dimension. The mark bins the data, counts the number of records that fall into each bin, smooths the resulting counts, and then plots the smoothed distribution, by default using an areaX mark.\n\nSet the *type* property to use a different base mark type.", + "type": "string" + }, + "marker": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for markerStart, markerMid, and markerEnd; one of:\n\n- a marker name such as *arrow* or *circle*\n- *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*" + }, + "markerEnd": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The marker for the ending point of a line segment; one of:\n\n- a marker name such as *arrow* or *circle*\n* *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*" + }, + "markerMid": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The marker for any middle (interior) points of a line segment. If the line segment only has a start and end point, this option has no effect. One of:\n\n- a marker name such as *arrow* or *circle*\n* *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*\n* a function - a custom marker function; see below" + }, + "markerStart": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The marker for the starting point of a line segment; one of:\n\n- a marker name such as *arrow* or *circle*\n* *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*" + }, + "mixBlendMode": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [mix-blend-mode][1]; a constant string specifying how to blend content such as *multiply*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode" + }, + "opacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally. For faster rendering, prefer the **strokeOpacity** or **fillOpacity** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/opacity" + }, + "paintOrder": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [paint-order][1]; a constant string specifying the order in which the\n**fill**, **stroke**, and any markers are drawn; defaults to *normal*, which draws the fill, then stroke, then markers; defaults to *stroke* for the text mark to create a “halo” around text to improve legibility.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/paint-order" + }, + "pointerEvents": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [pointer-events][1] property; a constant string such as *none*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/pointer-events" + }, + "reverse": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Applies a transform to reverse the order of the mark’s index, say for reverse input order." + }, + "select": { + "$ref": "#/definitions/SelectFilter", + "description": "Applies a filter transform after data is loaded to highlight selected values only. For example, `first` and `last` select the first or last values of series only (using the *z* channel to separate series). Meanwhile, `nearestX` and `nearestY` select the point nearest to the pointer along the *x* or *y* channel dimension. Unlike Mosaic selections, a mark level *select* is internal to the mark only, and does not populate a param or selection value to be shared across clients.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "shapeRendering": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [shape-rendering][1]; a constant string such as *crispEdges*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/shape-rendering" + }, + "sort": { + "anyOf": [ + { + "$ref": "#/definitions/SortOrder" + }, + { + "$ref": "#/definitions/ChannelDomainSort" + } + ], + "description": "Either applies a transform to sort the mark’s index by the specified channel values, or imputes ordinal scale domains from this mark’s channels.\n\nWhen imputing ordinal scale domains from channel values, the **sort** option is an object whose keys are ordinal scale names such as *x* or *fx*, and whose values are channel names such as *y*, *y1*, or *y2*. For example, to impute the *y* scale’s domain from the associated *x* channel values in ascending order:\n\n```js sort: {y: \"x\"} ```\n\nFor different sort options for different scales, replace the channel name with a *value* object and per-scale options:\n\n```js sort: {y: {value: \"-x\"}} ```\n\nWhen sorting the mark’s index, the **sort** option is instead one of:\n\n- a channel value definition for sorting given values in ascending order\n- a {value, order} object for sorting given values\n- a {channel, order} object for sorting the named channel’s values" + }, + "stroke": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke" + }, + "strokeDasharray": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dasharray][1]; a constant number indicating the length in pixels of alternating dashes and gaps, or a constant string of numbers separated by spaces or commas (_e.g._, *10 2* for dashes of 10 pixels separated by gaps of 2 pixels), or *none* (the default) for no dashing\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dasharray" + }, + "strokeDashoffset": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dashoffset][1]; a constant indicating the offset in pixels of the first dash along the stroke; defaults to zero.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dashoffset" + }, + "strokeLinecap": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linecap][1]; a constant specifying how to cap stroked paths, such as *butt*, *round*, or *square*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linecap" + }, + "strokeLinejoin": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linejoin][1]; a constant specifying how to join stroked paths, such as *bevel*, *miter*, *miter-clip*, or *round*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linejoin" + }, + "strokeMiterlimit": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-miterlimit][1]; a constant number specifying how to limit the length of *miter* joins on stroked paths.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-miterlimit" + }, + "strokeOpacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-opacity" + }, + "strokeWidth": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-width][1]; a constant number in pixels, or a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-width" + }, + "target": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [target][1]; a constant string specifying the target window (_e.g._,\n*_blank*) for clickable links; used in conjunction with the **href** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/target" + }, + "tension": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The tension option only has an effect on bundle, cardinal and Catmull–Rom splines (*bundle*, *cardinal*, *cardinal-open*, *cardinal-closed*,\n*catmull-rom*, *catmull-rom-open*, and *catmull-rom-closed*). For bundle splines, it corresponds to [beta][1]; for cardinal splines, [tension][2]; for Catmull–Rom splines, [alpha][3].\n\n[1]: https://d3js.org/d3-shape/curve#curveBundle_beta [2]: https://d3js.org/d3-shape/curve#curveCardinal_tension [3]: https://d3js.org/d3-shape/curve#curveCatmullRom_alpha" + }, + "tip": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/TipPointer" + }, + { + "properties": { + "anchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The tip anchor specifies how to orient the tip box relative to its anchor position; it refers to the part of the tip box that is attached to the anchor point. For example, the *top-left* anchor places the top-left corner of tip box near the anchor position, hence placing the tip box below and to the right of the anchor position." + }, + "fontFamily": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font-family][1]; a constant; defaults to the plot’s font family, which is typically [*system-ui*][2].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-family [2]: https://drafts.csswg.org/css-fonts-4/#valdef-font-family-system-ui" + }, + "fontSize": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font size][1] in pixels; either a constant or a channel; defaults to the plot’s font size, which is typically 10. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-size" + }, + "fontStyle": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font style][1]; a constant; defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-style" + }, + "fontVariant": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font variant][1]; a constant; if the **text** channel contains numbers or dates, defaults to *tabular-nums* to facilitate comparing numbers; otherwise defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant" + }, + "fontWeight": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font weight][1]; a constant; defaults to the plot’s font weight, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight" + }, + "format": { + "additionalProperties": false, + "description": "How channel values are formatted for display. If a format is a string, it is interpreted as a (UTC) time format for temporal channels, and otherwise a number format.", + "properties": { + "ariaLabel": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fill": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fillOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fontSize": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fx": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fy": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "geometry": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "height": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "href": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "length": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "opacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "path": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "r": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "rotate": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "src": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "stroke": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeWidth": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "symbol": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "text": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "title": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "weight": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "width": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "z": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + } + }, + "type": "object" + }, + "frameAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The frame anchor specifies defaults for **x** and **y** based on the plot’s frame; it may be one of the four sides (*top*, *right*, *bottom*, *left*), one of the four corners (*top-left*, *top-right*, *bottom-right*,\n*bottom-left*), or the *middle* of the frame. For example, for tips distributed horizontally at the top of the frame:\n\n```js Plot.tip(data, {x: \"date\", frameAnchor: \"top\"}) ```" + }, + "lineHeight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line height in ems; defaults to 1. The line height affects the (typically vertical) separation between adjacent baselines of text, as well as the separation between the text and its anchor point." + }, + "lineWidth": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line width in ems (e.g., 10 for about 20 characters); defaults to infinity, disabling wrapping and clipping.\n\nIf **textOverflow** is null, lines will be wrapped at the specified length. If a line is split at a soft hyphen (\\xad), a hyphen (-) will be displayed at the end of the line. If **textOverflow** is not null, lines will be clipped according to the given strategy." + }, + "monospace": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, changes the default **fontFamily** to *monospace*, and uses simplified monospaced text metrics calculations." + }, + "pathFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The image filter for the tip’s box; defaults to a drop shadow." + }, + "pointer": { + "$ref": "#/definitions/TipPointer" + }, + "pointerSize": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The size of the tip’s pointer in pixels; defaults to 12." + }, + "preferredAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If an explicit tip anchor is not specified, an anchor is chosen automatically such that the tip fits within the plot’s frame; if the preferred anchor fits, it is chosen." + }, + "textAnchor": { + "anyOf": [ + { + "const": "start", + "type": "string" + }, + { + "const": "middle", + "type": "string" + }, + { + "const": "end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [text anchor][1] controls how text is aligned (typically horizontally) relative to its anchor point; it is one of *start*, *end*, or *middle*. If the frame anchor is *left*, *top-left*, or *bottom-left*, the default text anchor is *start*; if the frame anchor is *right*, *top-right*, or\n*bottom-right*, the default is *end*; otherwise it is *middle*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/text-anchor" + }, + "textOverflow": { + "anyOf": [ + { + "type": "null" + }, + { + "const": "clip", + "type": "string" + }, + { + "const": "ellipsis", + "type": "string" + }, + { + "const": "clip-start", + "type": "string" + }, + { + "const": "clip-end", + "type": "string" + }, + { + "const": "ellipsis-start", + "type": "string" + }, + { + "const": "ellipsis-middle", + "type": "string" + }, + { + "const": "ellipsis-end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How truncate (or wrap) lines of text longer than the given **lineWidth**; one of:\n\n- null (default) - preserve overflowing characters (and wrap if needed)\n- *clip* or *clip-end* - remove characters from the end\n- *clip-start* - remove characters from the start\n- *ellipsis* or *ellipsis-end* - replace characters from the end with an ellipsis (…)\n- *ellipsis-start* - replace characters from the start with an ellipsis (…)\n- *ellipsis-middle* - replace characters from the middle with an ellipsis (…)\n\nIf no **title** was specified, if text requires truncation, a title containing the non-truncated text will be implicitly added." + }, + "textPadding": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The padding around the text in pixels; defaults to 8." + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + } + }, + "type": "object" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to generate a tooltip for this mark, and any tip options." + }, + "title": { + "$ref": "#/definitions/ChannelValue", + "description": "The title; a channel specifying accessible, short textual descriptions as strings (possibly with newlines). If the tip option is specified, the title will be displayed with an interactive tooltip instead of using the SVG [title element][1].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/title" + }, + "type": { + "const": "lineX", + "description": "The basic mark type to use to render 1D density values. Defaults to an areaX mark; lineX, dotX, and textX marks are also supported.", + "type": "string" + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel, typically bound to the *y* scale; defaults to the zero-based index of the data [0, 1, 2, …]." + }, + "z": { + "$ref": "#/definitions/ChannelValue", + "description": "An optional ordinal channel for grouping data into (possibly stacked) series to be drawn as separate lines. If not specified, it defaults to\n**fill** if a channel, or **stroke** if a channel." + } + }, + "required": [ + "data", + "mark", + "type" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "ariaDescription": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-description][1]; a constant textual description.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-description" + }, + "ariaHidden": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-hidden][1] state; a constant indicating whether the element is exposed to an accessibility API.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-hidden" + }, + "ariaLabel": { + "$ref": "#/definitions/ChannelValue", + "description": "The [aria-label][1]; a channel specifying short textual labels representing the value in the accessibility tree.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-label" + }, + "bandwidth": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The kernel density bandwidth for smoothing, in pixels. Defaults to 20." + }, + "bins": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The number of bins over which to discretize the data prior to smoothing. Defaults to 1024." + }, + "clip": { + "anyOf": [ + { + "const": "frame", + "type": "string" + }, + { + "const": "sphere", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to clip the mark; one of:\n\n- *frame* or true - clip to the plot’s frame (inner area)\n- *sphere* - clip to the projected sphere (*e.g.*, front hemisphere)\n- null or false - do not clip\n\nThe *sphere* clip option requires a geographic projection." + }, + "data": { + "$ref": "#/definitions/PlotMarkData", + "description": "The data source for the mark." + }, + "dx": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The horizontal offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "dy": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The vertical offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "facet": { + "anyOf": [ + { + "const": "auto", + "type": "string" + }, + { + "const": "include", + "type": "string" + }, + { + "const": "exclude", + "type": "string" + }, + { + "const": "super", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to enable or disable faceting; one of:\n\n- *auto* (default) - automatically determine if this mark should be faceted\n- *include* (or true) - draw the subset of the mark’s data in the current facet\n- *exclude* - draw the subset of the mark’s data *not* in the current facet\n- *super* - draw this mark in a single frame that covers all facets\n- null (or false) - repeat this mark’s data across all facets (*i.e.*, no faceting)\n\nWhen a mark uses *super* faceting, it is not allowed to use position scales (*x*, *y*, *fx*, or *fy*); *super* faceting is intended for decorations, such as labels and legends.\n\nWhen top-level faceting is used, the default *auto* setting is equivalent to *include* when the mark data is strictly equal to the top-level facet data; otherwise it is equivalent to null. When the *include* or *exclude* facet mode is chosen, the mark data must be parallel to the top-level facet data: the data must have the same length and order. If the data are not parallel, then the wrong data may be shown in each facet. The default\n*auto* therefore requires strict equality (`===`) for safety, and using the facet data as mark data is recommended when using the *exclude* facet mode. (To construct parallel data safely, consider using [*array*.map][1] on the facet data.)\n\nWhen mark-level faceting is used, the default *auto* setting is equivalent to *include*: the mark will be faceted if either the **fx** or **fy** channel option (or both) is specified. The null or false option will disable faceting, while *exclude* draws the subset of the mark’s data *not* in the current facet.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map" + }, + "facetAnchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "right", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "const": "left", + "type": "string" + }, + { + "const": "top-left", + "type": "string" + }, + { + "const": "top-right", + "type": "string" + }, + { + "const": "bottom-left", + "type": "string" + }, + { + "const": "bottom-right", + "type": "string" + }, + { + "const": "top-empty", + "type": "string" + }, + { + "const": "right-empty", + "type": "string" + }, + { + "const": "bottom-empty", + "type": "string" + }, + { + "const": "left-empty", + "type": "string" + }, + { + "const": "empty", + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to place the mark with respect to facets; one of:\n\n- null (default for most marks) - display the mark in each non-empty facet\n- *top*, *right*, *bottom*, or *left* - display the mark only in facets on the given side\n- *top-empty*, *right-empty*, *bottom-empty*, or *left-empty* (default for axis marks) - display the mark only in facets that have empty space on the given side: either the margin, or an empty facet\n- *empty* - display the mark in empty facets only" + }, + "fill": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill" + }, + "fillOpacity": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill-opacity][1]; a constant number between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill-opacity" + }, + "filter": { + "$ref": "#/definitions/ChannelValue", + "description": "Applies a transform to filter the mark’s index according to the given channel values; only truthy values are retained.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "frameAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The frame anchor specifies defaults for **x** and **y** based on the plot’s frame; it may be one of the four sides (*top*, *right*, *bottom*, *left*), one of the four corners (*top-left*, *top-right*, *bottom-right*,\n*bottom-left*), or the *middle* of the frame. For example, for dots distributed horizontally at the top of the frame:\n\n```js Plot.dot(data, {x: \"date\", frameAnchor: \"top\"}) ```" + }, + "fx": { + "$ref": "#/definitions/ChannelValue", + "description": "The horizontal facet position channel, for mark-level faceting, bound to the *fx* scale." + }, + "fy": { + "$ref": "#/definitions/ChannelValue", + "description": "The vertical facet position channel, for mark-level faceting, bound to the\n*fy* scale." + }, + "href": { + "$ref": "#/definitions/ChannelValue", + "description": "The [href][1]; a channel specifying URLs for clickable links. May be used in conjunction with the **target** option to open links in another window.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/href" + }, + "imageFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A CSS [filter][1]; a constant string used to adjust the rendering of images, such as *blur(5px)*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/filter" + }, + "margin": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four mark margins: **marginTop**,\n**marginRight**, **marginBottom**, and **marginLeft**; typically defaults to 0, except for axis marks." + }, + "marginBottom": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s bottom margin; the minimum distance in pixels between the bottom edges of the inner and outer plot area." + }, + "marginLeft": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s left margin; the minimum distance in pixels between the left edges of the inner and outer plot area." + }, + "marginRight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s right margin; the minimum distance in pixels between the right edges of the mark’s inner and outer plot area." + }, + "marginTop": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s top margin; the minimum distance in pixels between the top edges of the inner and outer plot area." + }, + "mark": { + "const": "densityX", + "description": "A densityX mark that visualizes smoothed point cloud densities along the\n**x** dimension. The mark bins the data, counts the number of records that fall into each bin, smooths the resulting counts, and then plots the smoothed distribution, by default using an areaX mark.\n\nSet the *type* property to use a different base mark type.", + "type": "string" + }, + "mixBlendMode": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [mix-blend-mode][1]; a constant string specifying how to blend content such as *multiply*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode" + }, + "opacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally. For faster rendering, prefer the **strokeOpacity** or **fillOpacity** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/opacity" + }, + "paintOrder": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [paint-order][1]; a constant string specifying the order in which the\n**fill**, **stroke**, and any markers are drawn; defaults to *normal*, which draws the fill, then stroke, then markers; defaults to *stroke* for the text mark to create a “halo” around text to improve legibility.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/paint-order" + }, + "pointerEvents": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [pointer-events][1] property; a constant string such as *none*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/pointer-events" + }, + "r": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The radius of dots; either a channel or constant. When a number, it is interpreted as a constant radius in pixels. Otherwise it is interpreted as a channel, typically bound to the *r* channel, which defaults to the *sqrt* type for proportional symbols. The radius defaults to 4.5 pixels when using the **symbol** channel, and otherwise 3 pixels. Dots with a nonpositive radius are not drawn." + }, + "reverse": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Applies a transform to reverse the order of the mark’s index, say for reverse input order." + }, + "rotate": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The rotation angle of dots in degrees clockwise; either a channel or a constant. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel. Defaults to 0°, pointing up." + }, + "select": { + "$ref": "#/definitions/SelectFilter", + "description": "Applies a filter transform after data is loaded to highlight selected values only. For example, `first` and `last` select the first or last values of series only (using the *z* channel to separate series). Meanwhile, `nearestX` and `nearestY` select the point nearest to the pointer along the *x* or *y* channel dimension. Unlike Mosaic selections, a mark level *select* is internal to the mark only, and does not populate a param or selection value to be shared across clients.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "shapeRendering": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [shape-rendering][1]; a constant string such as *crispEdges*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/shape-rendering" + }, + "sort": { + "anyOf": [ + { + "$ref": "#/definitions/SortOrder" + }, + { + "$ref": "#/definitions/ChannelDomainSort" + } + ], + "description": "Either applies a transform to sort the mark’s index by the specified channel values, or imputes ordinal scale domains from this mark’s channels.\n\nWhen imputing ordinal scale domains from channel values, the **sort** option is an object whose keys are ordinal scale names such as *x* or *fx*, and whose values are channel names such as *y*, *y1*, or *y2*. For example, to impute the *y* scale’s domain from the associated *x* channel values in ascending order:\n\n```js sort: {y: \"x\"} ```\n\nFor different sort options for different scales, replace the channel name with a *value* object and per-scale options:\n\n```js sort: {y: {value: \"-x\"}} ```\n\nWhen sorting the mark’s index, the **sort** option is instead one of:\n\n- a channel value definition for sorting given values in ascending order\n- a {value, order} object for sorting given values\n- a {channel, order} object for sorting the named channel’s values" + }, + "stroke": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke" + }, + "strokeDasharray": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dasharray][1]; a constant number indicating the length in pixels of alternating dashes and gaps, or a constant string of numbers separated by spaces or commas (_e.g._, *10 2* for dashes of 10 pixels separated by gaps of 2 pixels), or *none* (the default) for no dashing\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dasharray" + }, + "strokeDashoffset": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dashoffset][1]; a constant indicating the offset in pixels of the first dash along the stroke; defaults to zero.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dashoffset" + }, + "strokeLinecap": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linecap][1]; a constant specifying how to cap stroked paths, such as *butt*, *round*, or *square*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linecap" + }, + "strokeLinejoin": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linejoin][1]; a constant specifying how to join stroked paths, such as *bevel*, *miter*, *miter-clip*, or *round*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linejoin" + }, + "strokeMiterlimit": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-miterlimit][1]; a constant number specifying how to limit the length of *miter* joins on stroked paths.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-miterlimit" + }, + "strokeOpacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-opacity" + }, + "strokeWidth": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-width][1]; a constant number in pixels, or a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-width" + }, + "symbol": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/SymbolType" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The categorical symbol; either a channel or a constant. A constant symbol can be specified by a valid symbol name such as *star*, or a symbol object (implementing the draw method); otherwise it is interpreted as a channel. Defaults to *circle* for the **dot** mark, and *hexagon* for the\n**hexagon** mark.\n\nIf the **symbol** channel’s values are all symbols, symbol names, or nullish, the channel is unscaled (values are interpreted literally); otherwise, the channel is bound to the *symbol* scale." + }, + "target": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [target][1]; a constant string specifying the target window (_e.g._,\n*_blank*) for clickable links; used in conjunction with the **href** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/target" + }, + "tip": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/TipPointer" + }, + { + "properties": { + "anchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The tip anchor specifies how to orient the tip box relative to its anchor position; it refers to the part of the tip box that is attached to the anchor point. For example, the *top-left* anchor places the top-left corner of tip box near the anchor position, hence placing the tip box below and to the right of the anchor position." + }, + "fontFamily": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font-family][1]; a constant; defaults to the plot’s font family, which is typically [*system-ui*][2].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-family [2]: https://drafts.csswg.org/css-fonts-4/#valdef-font-family-system-ui" + }, + "fontSize": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font size][1] in pixels; either a constant or a channel; defaults to the plot’s font size, which is typically 10. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-size" + }, + "fontStyle": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font style][1]; a constant; defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-style" + }, + "fontVariant": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font variant][1]; a constant; if the **text** channel contains numbers or dates, defaults to *tabular-nums* to facilitate comparing numbers; otherwise defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant" + }, + "fontWeight": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font weight][1]; a constant; defaults to the plot’s font weight, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight" + }, + "format": { + "additionalProperties": false, + "description": "How channel values are formatted for display. If a format is a string, it is interpreted as a (UTC) time format for temporal channels, and otherwise a number format.", + "properties": { + "ariaLabel": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fill": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fillOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fontSize": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fx": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fy": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "geometry": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "height": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "href": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "length": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "opacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "path": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "r": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "rotate": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "src": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "stroke": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeWidth": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "symbol": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "text": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "title": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "weight": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "width": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "z": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + } + }, + "type": "object" + }, + "frameAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The frame anchor specifies defaults for **x** and **y** based on the plot’s frame; it may be one of the four sides (*top*, *right*, *bottom*, *left*), one of the four corners (*top-left*, *top-right*, *bottom-right*,\n*bottom-left*), or the *middle* of the frame. For example, for tips distributed horizontally at the top of the frame:\n\n```js Plot.tip(data, {x: \"date\", frameAnchor: \"top\"}) ```" + }, + "lineHeight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line height in ems; defaults to 1. The line height affects the (typically vertical) separation between adjacent baselines of text, as well as the separation between the text and its anchor point." + }, + "lineWidth": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line width in ems (e.g., 10 for about 20 characters); defaults to infinity, disabling wrapping and clipping.\n\nIf **textOverflow** is null, lines will be wrapped at the specified length. If a line is split at a soft hyphen (\\xad), a hyphen (-) will be displayed at the end of the line. If **textOverflow** is not null, lines will be clipped according to the given strategy." + }, + "monospace": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, changes the default **fontFamily** to *monospace*, and uses simplified monospaced text metrics calculations." + }, + "pathFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The image filter for the tip’s box; defaults to a drop shadow." + }, + "pointer": { + "$ref": "#/definitions/TipPointer" + }, + "pointerSize": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The size of the tip’s pointer in pixels; defaults to 12." + }, + "preferredAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If an explicit tip anchor is not specified, an anchor is chosen automatically such that the tip fits within the plot’s frame; if the preferred anchor fits, it is chosen." + }, + "textAnchor": { + "anyOf": [ + { + "const": "start", + "type": "string" + }, + { + "const": "middle", + "type": "string" + }, + { + "const": "end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [text anchor][1] controls how text is aligned (typically horizontally) relative to its anchor point; it is one of *start*, *end*, or *middle*. If the frame anchor is *left*, *top-left*, or *bottom-left*, the default text anchor is *start*; if the frame anchor is *right*, *top-right*, or\n*bottom-right*, the default is *end*; otherwise it is *middle*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/text-anchor" + }, + "textOverflow": { + "anyOf": [ + { + "type": "null" + }, + { + "const": "clip", + "type": "string" + }, + { + "const": "ellipsis", + "type": "string" + }, + { + "const": "clip-start", + "type": "string" + }, + { + "const": "clip-end", + "type": "string" + }, + { + "const": "ellipsis-start", + "type": "string" + }, + { + "const": "ellipsis-middle", + "type": "string" + }, + { + "const": "ellipsis-end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How truncate (or wrap) lines of text longer than the given **lineWidth**; one of:\n\n- null (default) - preserve overflowing characters (and wrap if needed)\n- *clip* or *clip-end* - remove characters from the end\n- *clip-start* - remove characters from the start\n- *ellipsis* or *ellipsis-end* - replace characters from the end with an ellipsis (…)\n- *ellipsis-start* - replace characters from the start with an ellipsis (…)\n- *ellipsis-middle* - replace characters from the middle with an ellipsis (…)\n\nIf no **title** was specified, if text requires truncation, a title containing the non-truncated text will be implicitly added." + }, + "textPadding": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The padding around the text in pixels; defaults to 8." + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + } + }, + "type": "object" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to generate a tooltip for this mark, and any tip options." + }, + "title": { + "$ref": "#/definitions/ChannelValue", + "description": "The title; a channel specifying accessible, short textual descriptions as strings (possibly with newlines). If the tip option is specified, the title will be displayed with an interactive tooltip instead of using the SVG [title element][1].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/title" + }, + "type": { + "const": "dotX", + "description": "The basic mark type to use to render 1D density values. Defaults to an areaX mark; lineX, dotX, and textX marks are also supported.", + "type": "string" + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel specifying the dot’s center, typically bound to the *y* scale." + }, + "z": { + "$ref": "#/definitions/ChannelValue", + "description": "An optional ordinal channel for grouping data into series." + } + }, + "required": [ + "data", + "mark", + "type" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "ariaDescription": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-description][1]; a constant textual description.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-description" + }, + "ariaHidden": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-hidden][1] state; a constant indicating whether the element is exposed to an accessibility API.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-hidden" + }, + "ariaLabel": { + "$ref": "#/definitions/ChannelValue", + "description": "The [aria-label][1]; a channel specifying short textual labels representing the value in the accessibility tree.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-label" + }, + "bandwidth": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The kernel density bandwidth for smoothing, in pixels. Defaults to 20." + }, + "bins": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The number of bins over which to discretize the data prior to smoothing. Defaults to 1024." + }, + "clip": { + "anyOf": [ + { + "const": "frame", + "type": "string" + }, + { + "const": "sphere", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to clip the mark; one of:\n\n- *frame* or true - clip to the plot’s frame (inner area)\n- *sphere* - clip to the projected sphere (*e.g.*, front hemisphere)\n- null or false - do not clip\n\nThe *sphere* clip option requires a geographic projection." + }, + "data": { + "$ref": "#/definitions/PlotMarkData", + "description": "The data source for the mark." + }, + "dx": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The horizontal offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "dy": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The vertical offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "facet": { + "anyOf": [ + { + "const": "auto", + "type": "string" + }, + { + "const": "include", + "type": "string" + }, + { + "const": "exclude", + "type": "string" + }, + { + "const": "super", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to enable or disable faceting; one of:\n\n- *auto* (default) - automatically determine if this mark should be faceted\n- *include* (or true) - draw the subset of the mark’s data in the current facet\n- *exclude* - draw the subset of the mark’s data *not* in the current facet\n- *super* - draw this mark in a single frame that covers all facets\n- null (or false) - repeat this mark’s data across all facets (*i.e.*, no faceting)\n\nWhen a mark uses *super* faceting, it is not allowed to use position scales (*x*, *y*, *fx*, or *fy*); *super* faceting is intended for decorations, such as labels and legends.\n\nWhen top-level faceting is used, the default *auto* setting is equivalent to *include* when the mark data is strictly equal to the top-level facet data; otherwise it is equivalent to null. When the *include* or *exclude* facet mode is chosen, the mark data must be parallel to the top-level facet data: the data must have the same length and order. If the data are not parallel, then the wrong data may be shown in each facet. The default\n*auto* therefore requires strict equality (`===`) for safety, and using the facet data as mark data is recommended when using the *exclude* facet mode. (To construct parallel data safely, consider using [*array*.map][1] on the facet data.)\n\nWhen mark-level faceting is used, the default *auto* setting is equivalent to *include*: the mark will be faceted if either the **fx** or **fy** channel option (or both) is specified. The null or false option will disable faceting, while *exclude* draws the subset of the mark’s data *not* in the current facet.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map" + }, + "facetAnchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "right", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "const": "left", + "type": "string" + }, + { + "const": "top-left", + "type": "string" + }, + { + "const": "top-right", + "type": "string" + }, + { + "const": "bottom-left", + "type": "string" + }, + { + "const": "bottom-right", + "type": "string" + }, + { + "const": "top-empty", + "type": "string" + }, + { + "const": "right-empty", + "type": "string" + }, + { + "const": "bottom-empty", + "type": "string" + }, + { + "const": "left-empty", + "type": "string" + }, + { + "const": "empty", + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to place the mark with respect to facets; one of:\n\n- null (default for most marks) - display the mark in each non-empty facet\n- *top*, *right*, *bottom*, or *left* - display the mark only in facets on the given side\n- *top-empty*, *right-empty*, *bottom-empty*, or *left-empty* (default for axis marks) - display the mark only in facets that have empty space on the given side: either the margin, or an empty facet\n- *empty* - display the mark in empty facets only" + }, + "fill": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill" + }, + "fillOpacity": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill-opacity][1]; a constant number between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill-opacity" + }, + "filter": { + "$ref": "#/definitions/ChannelValue", + "description": "Applies a transform to filter the mark’s index according to the given channel values; only truthy values are retained.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "fontFamily": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font-family][1]; a constant; defaults to the plot’s font family, which is typically [*system-ui*][2].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-family [2]: https://drafts.csswg.org/css-fonts-4/#valdef-font-family-system-ui" + }, + "fontSize": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font size][1] in pixels; either a constant or a channel; defaults to the plot’s font size, which is typically 10. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-size" + }, + "fontStyle": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font style][1]; a constant; defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-style" + }, + "fontVariant": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font variant][1]; a constant; if the **text** channel contains numbers or dates, defaults to *tabular-nums* to facilitate comparing numbers; otherwise defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant" + }, + "fontWeight": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font weight][1]; a constant; defaults to the plot’s font weight, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight" + }, + "frameAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The frame anchor specifies defaults for **x** and **y**, along with\n**textAnchor** and **lineAnchor**, based on the plot’s frame; it may be one of the four sides (*top*, *right*, *bottom*, *left*), one of the four corners (*top-left*, *top-right*, *bottom-right*, *bottom-left*), or the\n*middle* of the frame." + }, + "fx": { + "$ref": "#/definitions/ChannelValue", + "description": "The horizontal facet position channel, for mark-level faceting, bound to the *fx* scale." + }, + "fy": { + "$ref": "#/definitions/ChannelValue", + "description": "The vertical facet position channel, for mark-level faceting, bound to the\n*fy* scale." + }, + "href": { + "$ref": "#/definitions/ChannelValue", + "description": "The [href][1]; a channel specifying URLs for clickable links. May be used in conjunction with the **target** option to open links in another window.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/href" + }, + "imageFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A CSS [filter][1]; a constant string used to adjust the rendering of images, such as *blur(5px)*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/filter" + }, + "lineAnchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "middle", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line anchor controls how text is aligned (typically vertically) relative to its anchor point; it is one of *top*, *bottom*, or *middle*. If the frame anchor is *top*, *top-left*, or *top-right*, the default line anchor is *top*; if the frame anchor is *bottom*, *bottom-right*, or\n*bottom-left*, the default is *bottom*; otherwise it is *middle*." + }, + "lineHeight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line height in ems; defaults to 1. The line height affects the (typically vertical) separation between adjacent baselines of text, as well as the separation between the text and its anchor point." + }, + "lineWidth": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line width in ems (e.g., 10 for about 20 characters); defaults to infinity, disabling wrapping and clipping.\n\nIf **textOverflow** is null, lines will be wrapped at the specified length. If a line is split at a soft hyphen (\\xad), a hyphen (-) will be displayed at the end of the line. If **textOverflow** is not null, lines will be clipped according to the given strategy." + }, + "margin": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four mark margins: **marginTop**,\n**marginRight**, **marginBottom**, and **marginLeft**; typically defaults to 0, except for axis marks." + }, + "marginBottom": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s bottom margin; the minimum distance in pixels between the bottom edges of the inner and outer plot area." + }, + "marginLeft": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s left margin; the minimum distance in pixels between the left edges of the inner and outer plot area." + }, + "marginRight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s right margin; the minimum distance in pixels between the right edges of the mark’s inner and outer plot area." + }, + "marginTop": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s top margin; the minimum distance in pixels between the top edges of the inner and outer plot area." + }, + "mark": { + "const": "densityX", + "description": "A densityX mark that visualizes smoothed point cloud densities along the\n**x** dimension. The mark bins the data, counts the number of records that fall into each bin, smooths the resulting counts, and then plots the smoothed distribution, by default using an areaX mark.\n\nSet the *type* property to use a different base mark type.", + "type": "string" + }, + "mixBlendMode": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [mix-blend-mode][1]; a constant string specifying how to blend content such as *multiply*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode" + }, + "monospace": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, changes the default **fontFamily** to *monospace*, and uses simplified monospaced text metrics calculations." + }, + "opacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally. For faster rendering, prefer the **strokeOpacity** or **fillOpacity** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/opacity" + }, + "paintOrder": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [paint-order][1]; a constant string specifying the order in which the\n**fill**, **stroke**, and any markers are drawn; defaults to *normal*, which draws the fill, then stroke, then markers; defaults to *stroke* for the text mark to create a “halo” around text to improve legibility.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/paint-order" + }, + "pointerEvents": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [pointer-events][1] property; a constant string such as *none*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/pointer-events" + }, + "reverse": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Applies a transform to reverse the order of the mark’s index, say for reverse input order." + }, + "rotate": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The rotation angle in degrees clockwise; a constant or a channel; defaults to 0°. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel." + }, + "select": { + "$ref": "#/definitions/SelectFilter", + "description": "Applies a filter transform after data is loaded to highlight selected values only. For example, `first` and `last` select the first or last values of series only (using the *z* channel to separate series). Meanwhile, `nearestX` and `nearestY` select the point nearest to the pointer along the *x* or *y* channel dimension. Unlike Mosaic selections, a mark level *select* is internal to the mark only, and does not populate a param or selection value to be shared across clients.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "shapeRendering": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [shape-rendering][1]; a constant string such as *crispEdges*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/shape-rendering" + }, + "sort": { + "anyOf": [ + { + "$ref": "#/definitions/SortOrder" + }, + { + "$ref": "#/definitions/ChannelDomainSort" + } + ], + "description": "Either applies a transform to sort the mark’s index by the specified channel values, or imputes ordinal scale domains from this mark’s channels.\n\nWhen imputing ordinal scale domains from channel values, the **sort** option is an object whose keys are ordinal scale names such as *x* or *fx*, and whose values are channel names such as *y*, *y1*, or *y2*. For example, to impute the *y* scale’s domain from the associated *x* channel values in ascending order:\n\n```js sort: {y: \"x\"} ```\n\nFor different sort options for different scales, replace the channel name with a *value* object and per-scale options:\n\n```js sort: {y: {value: \"-x\"}} ```\n\nWhen sorting the mark’s index, the **sort** option is instead one of:\n\n- a channel value definition for sorting given values in ascending order\n- a {value, order} object for sorting given values\n- a {channel, order} object for sorting the named channel’s values" + }, + "stroke": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke" + }, + "strokeDasharray": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dasharray][1]; a constant number indicating the length in pixels of alternating dashes and gaps, or a constant string of numbers separated by spaces or commas (_e.g._, *10 2* for dashes of 10 pixels separated by gaps of 2 pixels), or *none* (the default) for no dashing\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dasharray" + }, + "strokeDashoffset": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dashoffset][1]; a constant indicating the offset in pixels of the first dash along the stroke; defaults to zero.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dashoffset" + }, + "strokeLinecap": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linecap][1]; a constant specifying how to cap stroked paths, such as *butt*, *round*, or *square*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linecap" + }, + "strokeLinejoin": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linejoin][1]; a constant specifying how to join stroked paths, such as *bevel*, *miter*, *miter-clip*, or *round*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linejoin" + }, + "strokeMiterlimit": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-miterlimit][1]; a constant number specifying how to limit the length of *miter* joins on stroked paths.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-miterlimit" + }, + "strokeOpacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-opacity" + }, + "strokeWidth": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-width][1]; a constant number in pixels, or a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-width" + }, + "target": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [target][1]; a constant string specifying the target window (_e.g._,\n*_blank*) for clickable links; used in conjunction with the **href** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/target" + }, + "text": { + "$ref": "#/definitions/ChannelValue", + "description": "The text contents channel, possibly with line breaks (\\n, \\r\\n, or \\r). If not specified, defaults to the zero-based index [0, 1, 2, …]." + }, + "textAnchor": { + "anyOf": [ + { + "const": "start", + "type": "string" + }, + { + "const": "middle", + "type": "string" + }, + { + "const": "end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [text anchor][1] controls how text is aligned (typically horizontally) relative to its anchor point; it is one of *start*, *end*, or *middle*. If the frame anchor is *left*, *top-left*, or *bottom-left*, the default text anchor is *start*; if the frame anchor is *right*, *top-right*, or\n*bottom-right*, the default is *end*; otherwise it is *middle*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/text-anchor" + }, + "textOverflow": { + "anyOf": [ + { + "type": "null" + }, + { + "const": "clip", + "type": "string" + }, + { + "const": "ellipsis", + "type": "string" + }, + { + "const": "clip-start", + "type": "string" + }, + { + "const": "clip-end", + "type": "string" + }, + { + "const": "ellipsis-start", + "type": "string" + }, + { + "const": "ellipsis-middle", + "type": "string" + }, + { + "const": "ellipsis-end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How truncate (or wrap) lines of text longer than the given **lineWidth**; one of:\n\n- null (default) - preserve overflowing characters (and wrap if needed)\n- *clip* or *clip-end* - remove characters from the end\n- *clip-start* - remove characters from the start\n- *ellipsis* or *ellipsis-end* - replace characters from the end with an ellipsis (…)\n- *ellipsis-start* - replace characters from the start with an ellipsis (…)\n- *ellipsis-middle* - replace characters from the middle with an ellipsis (…)\n\nIf no **title** was specified, if text requires truncation, a title containing the non-truncated text will be implicitly added." + }, + "tip": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/TipPointer" + }, + { + "properties": { + "anchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The tip anchor specifies how to orient the tip box relative to its anchor position; it refers to the part of the tip box that is attached to the anchor point. For example, the *top-left* anchor places the top-left corner of tip box near the anchor position, hence placing the tip box below and to the right of the anchor position." + }, + "fontFamily": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font-family][1]; a constant; defaults to the plot’s font family, which is typically [*system-ui*][2].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-family [2]: https://drafts.csswg.org/css-fonts-4/#valdef-font-family-system-ui" + }, + "fontSize": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font size][1] in pixels; either a constant or a channel; defaults to the plot’s font size, which is typically 10. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-size" + }, + "fontStyle": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font style][1]; a constant; defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-style" + }, + "fontVariant": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font variant][1]; a constant; if the **text** channel contains numbers or dates, defaults to *tabular-nums* to facilitate comparing numbers; otherwise defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant" + }, + "fontWeight": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font weight][1]; a constant; defaults to the plot’s font weight, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight" + }, + "format": { + "additionalProperties": false, + "description": "How channel values are formatted for display. If a format is a string, it is interpreted as a (UTC) time format for temporal channels, and otherwise a number format.", + "properties": { + "ariaLabel": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fill": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fillOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fontSize": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fx": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fy": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "geometry": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "height": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "href": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "length": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "opacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "path": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "r": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "rotate": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "src": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "stroke": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeWidth": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "symbol": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "text": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "title": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "weight": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "width": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "z": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + } + }, + "type": "object" + }, + "frameAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The frame anchor specifies defaults for **x** and **y** based on the plot’s frame; it may be one of the four sides (*top*, *right*, *bottom*, *left*), one of the four corners (*top-left*, *top-right*, *bottom-right*,\n*bottom-left*), or the *middle* of the frame. For example, for tips distributed horizontally at the top of the frame:\n\n```js Plot.tip(data, {x: \"date\", frameAnchor: \"top\"}) ```" + }, + "lineHeight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line height in ems; defaults to 1. The line height affects the (typically vertical) separation between adjacent baselines of text, as well as the separation between the text and its anchor point." + }, + "lineWidth": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line width in ems (e.g., 10 for about 20 characters); defaults to infinity, disabling wrapping and clipping.\n\nIf **textOverflow** is null, lines will be wrapped at the specified length. If a line is split at a soft hyphen (\\xad), a hyphen (-) will be displayed at the end of the line. If **textOverflow** is not null, lines will be clipped according to the given strategy." + }, + "monospace": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, changes the default **fontFamily** to *monospace*, and uses simplified monospaced text metrics calculations." + }, + "pathFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The image filter for the tip’s box; defaults to a drop shadow." + }, + "pointer": { + "$ref": "#/definitions/TipPointer" + }, + "pointerSize": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The size of the tip’s pointer in pixels; defaults to 12." + }, + "preferredAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If an explicit tip anchor is not specified, an anchor is chosen automatically such that the tip fits within the plot’s frame; if the preferred anchor fits, it is chosen." + }, + "textAnchor": { + "anyOf": [ + { + "const": "start", + "type": "string" + }, + { + "const": "middle", + "type": "string" + }, + { + "const": "end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [text anchor][1] controls how text is aligned (typically horizontally) relative to its anchor point; it is one of *start*, *end*, or *middle*. If the frame anchor is *left*, *top-left*, or *bottom-left*, the default text anchor is *start*; if the frame anchor is *right*, *top-right*, or\n*bottom-right*, the default is *end*; otherwise it is *middle*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/text-anchor" + }, + "textOverflow": { + "anyOf": [ + { + "type": "null" + }, + { + "const": "clip", + "type": "string" + }, + { + "const": "ellipsis", + "type": "string" + }, + { + "const": "clip-start", + "type": "string" + }, + { + "const": "clip-end", + "type": "string" + }, + { + "const": "ellipsis-start", + "type": "string" + }, + { + "const": "ellipsis-middle", + "type": "string" + }, + { + "const": "ellipsis-end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How truncate (or wrap) lines of text longer than the given **lineWidth**; one of:\n\n- null (default) - preserve overflowing characters (and wrap if needed)\n- *clip* or *clip-end* - remove characters from the end\n- *clip-start* - remove characters from the start\n- *ellipsis* or *ellipsis-end* - replace characters from the end with an ellipsis (…)\n- *ellipsis-start* - replace characters from the start with an ellipsis (…)\n- *ellipsis-middle* - replace characters from the middle with an ellipsis (…)\n\nIf no **title** was specified, if text requires truncation, a title containing the non-truncated text will be implicitly added." + }, + "textPadding": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The padding around the text in pixels; defaults to 8." + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + } + }, + "type": "object" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to generate a tooltip for this mark, and any tip options." + }, + "title": { + "$ref": "#/definitions/ChannelValue", + "description": "The title; a channel specifying accessible, short textual descriptions as strings (possibly with newlines). If the tip option is specified, the title will be displayed with an interactive tooltip instead of using the SVG [title element][1].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/title" + }, + "type": { + "const": "textX", + "description": "The basic mark type to use to render 1D density values. Defaults to an areaX mark; lineX, dotX, and textX marks are also supported.", + "type": "string" + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel specifying the text’s anchor point, typically bound to the *y* scale." + }, + "z": { + "$ref": "#/definitions/ChannelValue", + "description": "An optional ordinal channel for grouping data into series." + } + }, + "required": [ + "data", + "mark", + "type" + ], + "type": "object" + } + ], + "description": "The densityX mark." + }, + "DensityY": { + "anyOf": [ + { + "additionalProperties": false, + "properties": { + "ariaDescription": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-description][1]; a constant textual description.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-description" + }, + "ariaHidden": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-hidden][1] state; a constant indicating whether the element is exposed to an accessibility API.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-hidden" + }, + "ariaLabel": { + "$ref": "#/definitions/ChannelValue", + "description": "The [aria-label][1]; a channel specifying short textual labels representing the value in the accessibility tree.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-label" + }, + "bandwidth": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The kernel density bandwidth for smoothing, in pixels. Defaults to 20." + }, + "bins": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The number of bins over which to discretize the data prior to smoothing. Defaults to 1024." + }, + "clip": { + "anyOf": [ + { + "const": "frame", + "type": "string" + }, + { + "const": "sphere", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to clip the mark; one of:\n\n- *frame* or true - clip to the plot’s frame (inner area)\n- *sphere* - clip to the projected sphere (*e.g.*, front hemisphere)\n- null or false - do not clip\n\nThe *sphere* clip option requires a geographic projection." + }, + "curve": { + "anyOf": [ + { + "$ref": "#/definitions/Curve" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The curve (interpolation) method for connecting adjacent points. One of:\n\n- *basis* - a cubic basis spline (repeating the end points)\n- *basis-open* - an open cubic basis spline\n- *basis-closed* - a closed cubic basis spline\n- *bump-x* - a Bézier curve with horizontal tangents\n- *bump-y* - a Bézier curve with vertical tangents\n- *bundle* - a straightened cubic basis spline (suitable for lines only, not areas)\n- *cardinal* - a cubic cardinal spline (with one-sided differences at the ends)\n- *cardinal-open* - an open cubic cardinal spline\n- *cardinal-closed* - an closed cubic cardinal spline\n- *catmull-rom* - a cubic Catmull–Rom spline (with one-sided differences at the ends)\n- *catmull-rom-open* - an open cubic Catmull–Rom spline\n- *catmull-rom-closed* - a closed cubic Catmull–Rom spline\n- *linear* - a piecewise linear curve (*i.e.*, straight line segments)\n- *linear-closed* - a closed piecewise linear curve (*i.e.*, straight line segments)\n- *monotone-x* - a cubic spline that preserves monotonicity in *x*\n- *monotone-y* - a cubic spline that preserves monotonicity in *y*\n- *natural* - a natural cubic spline\n- *step* - a piecewise constant function where *y* changes at the midpoint of *x*\n- *step-after* - a piecewise constant function where *y* changes after *x*\n- *step-before* - a piecewise constant function where *x* changes after *y*" + }, + "data": { + "$ref": "#/definitions/PlotMarkData", + "description": "The data source for the mark." + }, + "dx": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The horizontal offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "dy": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The vertical offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "facet": { + "anyOf": [ + { + "const": "auto", + "type": "string" + }, + { + "const": "include", + "type": "string" + }, + { + "const": "exclude", + "type": "string" + }, + { + "const": "super", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to enable or disable faceting; one of:\n\n- *auto* (default) - automatically determine if this mark should be faceted\n- *include* (or true) - draw the subset of the mark’s data in the current facet\n- *exclude* - draw the subset of the mark’s data *not* in the current facet\n- *super* - draw this mark in a single frame that covers all facets\n- null (or false) - repeat this mark’s data across all facets (*i.e.*, no faceting)\n\nWhen a mark uses *super* faceting, it is not allowed to use position scales (*x*, *y*, *fx*, or *fy*); *super* faceting is intended for decorations, such as labels and legends.\n\nWhen top-level faceting is used, the default *auto* setting is equivalent to *include* when the mark data is strictly equal to the top-level facet data; otherwise it is equivalent to null. When the *include* or *exclude* facet mode is chosen, the mark data must be parallel to the top-level facet data: the data must have the same length and order. If the data are not parallel, then the wrong data may be shown in each facet. The default\n*auto* therefore requires strict equality (`===`) for safety, and using the facet data as mark data is recommended when using the *exclude* facet mode. (To construct parallel data safely, consider using [*array*.map][1] on the facet data.)\n\nWhen mark-level faceting is used, the default *auto* setting is equivalent to *include*: the mark will be faceted if either the **fx** or **fy** channel option (or both) is specified. The null or false option will disable faceting, while *exclude* draws the subset of the mark’s data *not* in the current facet.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map" + }, + "facetAnchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "right", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "const": "left", + "type": "string" + }, + { + "const": "top-left", + "type": "string" + }, + { + "const": "top-right", + "type": "string" + }, + { + "const": "bottom-left", + "type": "string" + }, + { + "const": "bottom-right", + "type": "string" + }, + { + "const": "top-empty", + "type": "string" + }, + { + "const": "right-empty", + "type": "string" + }, + { + "const": "bottom-empty", + "type": "string" + }, + { + "const": "left-empty", + "type": "string" + }, + { + "const": "empty", + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to place the mark with respect to facets; one of:\n\n- null (default for most marks) - display the mark in each non-empty facet\n- *top*, *right*, *bottom*, or *left* - display the mark only in facets on the given side\n- *top-empty*, *right-empty*, *bottom-empty*, or *left-empty* (default for axis marks) - display the mark only in facets that have empty space on the given side: either the margin, or an empty facet\n- *empty* - display the mark in empty facets only" + }, + "fill": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill" + }, + "fillOpacity": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill-opacity][1]; a constant number between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill-opacity" + }, + "filter": { + "$ref": "#/definitions/ChannelValue", + "description": "Applies a transform to filter the mark’s index according to the given channel values; only truthy values are retained.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "fx": { + "$ref": "#/definitions/ChannelValue", + "description": "The horizontal facet position channel, for mark-level faceting, bound to the *fx* scale." + }, + "fy": { + "$ref": "#/definitions/ChannelValue", + "description": "The vertical facet position channel, for mark-level faceting, bound to the\n*fy* scale." + }, + "href": { + "$ref": "#/definitions/ChannelValue", + "description": "The [href][1]; a channel specifying URLs for clickable links. May be used in conjunction with the **target** option to open links in another window.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/href" + }, + "imageFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A CSS [filter][1]; a constant string used to adjust the rendering of images, such as *blur(5px)*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/filter" + }, + "margin": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four mark margins: **marginTop**,\n**marginRight**, **marginBottom**, and **marginLeft**; typically defaults to 0, except for axis marks." + }, + "marginBottom": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s bottom margin; the minimum distance in pixels between the bottom edges of the inner and outer plot area." + }, + "marginLeft": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s left margin; the minimum distance in pixels between the left edges of the inner and outer plot area." + }, + "marginRight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s right margin; the minimum distance in pixels between the right edges of the mark’s inner and outer plot area." + }, + "marginTop": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s top margin; the minimum distance in pixels between the top edges of the inner and outer plot area." + }, + "mark": { + "const": "densityY", + "description": "A densityY mark that visualizes smoothed point cloud densities along the\n**y** dimension. The mark bins the data, counts the number of records that fall into each bin, smooths the resulting counts, and then plots the smoothed distribution, by default using an areaY mark.\n\nSet the *type* property to use a different base mark type.", + "type": "string" + }, + "mixBlendMode": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [mix-blend-mode][1]; a constant string specifying how to blend content such as *multiply*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode" + }, + "offset": { + "anyOf": [ + { + "$ref": "#/definitions/StackOffset" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "After stacking, an optional **offset** can be applied to translate and scale stacks, say to produce a streamgraph; defaults to null for a zero baseline (**y** = 0 for stackY, and **x** = 0 for stackX). If the *wiggle* offset is used, the default **order** changes to *inside-out*." + }, + "opacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally. For faster rendering, prefer the **strokeOpacity** or **fillOpacity** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/opacity" + }, + "order": { + "anyOf": [ + { + "$ref": "#/definitions/StackOrder" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The order in which stacks are layered; one of:\n\n- null (default) for input order\n- a named stack order method such as *inside-out* or *sum*\n- a field name, for natural order of the corresponding values\n- a function of data, for natural order of the corresponding values\n- an array of explicit **z** values in the desired order\n\nIf the *wiggle* **offset** is used, as for a streamgraph, the default changes to *inside-out*." + }, + "paintOrder": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [paint-order][1]; a constant string specifying the order in which the\n**fill**, **stroke**, and any markers are drawn; defaults to *normal*, which draws the fill, then stroke, then markers; defaults to *stroke* for the text mark to create a “halo” around text to improve legibility.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/paint-order" + }, + "pointerEvents": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [pointer-events][1] property; a constant string such as *none*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/pointer-events" + }, + "reverse": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Applies a transform to reverse the order of the mark’s index, say for reverse input order." + }, + "select": { + "$ref": "#/definitions/SelectFilter", + "description": "Applies a filter transform after data is loaded to highlight selected values only. For example, `first` and `last` select the first or last values of series only (using the *z* channel to separate series). Meanwhile, `nearestX` and `nearestY` select the point nearest to the pointer along the *x* or *y* channel dimension. Unlike Mosaic selections, a mark level *select* is internal to the mark only, and does not populate a param or selection value to be shared across clients.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "shapeRendering": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [shape-rendering][1]; a constant string such as *crispEdges*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/shape-rendering" + }, + "sort": { + "anyOf": [ + { + "$ref": "#/definitions/SortOrder" + }, + { + "$ref": "#/definitions/ChannelDomainSort" + } + ], + "description": "Either applies a transform to sort the mark’s index by the specified channel values, or imputes ordinal scale domains from this mark’s channels.\n\nWhen imputing ordinal scale domains from channel values, the **sort** option is an object whose keys are ordinal scale names such as *x* or *fx*, and whose values are channel names such as *y*, *y1*, or *y2*. For example, to impute the *y* scale’s domain from the associated *x* channel values in ascending order:\n\n```js sort: {y: \"x\"} ```\n\nFor different sort options for different scales, replace the channel name with a *value* object and per-scale options:\n\n```js sort: {y: {value: \"-x\"}} ```\n\nWhen sorting the mark’s index, the **sort** option is instead one of:\n\n- a channel value definition for sorting given values in ascending order\n- a {value, order} object for sorting given values\n- a {channel, order} object for sorting the named channel’s values" + }, + "stroke": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke" + }, + "strokeDasharray": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dasharray][1]; a constant number indicating the length in pixels of alternating dashes and gaps, or a constant string of numbers separated by spaces or commas (_e.g._, *10 2* for dashes of 10 pixels separated by gaps of 2 pixels), or *none* (the default) for no dashing\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dasharray" + }, + "strokeDashoffset": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dashoffset][1]; a constant indicating the offset in pixels of the first dash along the stroke; defaults to zero.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dashoffset" + }, + "strokeLinecap": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linecap][1]; a constant specifying how to cap stroked paths, such as *butt*, *round*, or *square*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linecap" + }, + "strokeLinejoin": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linejoin][1]; a constant specifying how to join stroked paths, such as *bevel*, *miter*, *miter-clip*, or *round*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linejoin" + }, + "strokeMiterlimit": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-miterlimit][1]; a constant number specifying how to limit the length of *miter* joins on stroked paths.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-miterlimit" + }, + "strokeOpacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-opacity" + }, + "strokeWidth": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-width][1]; a constant number in pixels, or a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-width" + }, + "target": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [target][1]; a constant string specifying the target window (_e.g._,\n*_blank*) for clickable links; used in conjunction with the **href** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/target" + }, + "tension": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The tension option only has an effect on bundle, cardinal and Catmull–Rom splines (*bundle*, *cardinal*, *cardinal-open*, *cardinal-closed*,\n*catmull-rom*, *catmull-rom-open*, and *catmull-rom-closed*). For bundle splines, it corresponds to [beta][1]; for cardinal splines, [tension][2]; for Catmull–Rom splines, [alpha][3].\n\n[1]: https://d3js.org/d3-shape/curve#curveBundle_beta [2]: https://d3js.org/d3-shape/curve#curveCardinal_tension [3]: https://d3js.org/d3-shape/curve#curveCatmullRom_alpha" + }, + "tip": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/TipPointer" + }, + { + "properties": { + "anchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The tip anchor specifies how to orient the tip box relative to its anchor position; it refers to the part of the tip box that is attached to the anchor point. For example, the *top-left* anchor places the top-left corner of tip box near the anchor position, hence placing the tip box below and to the right of the anchor position." + }, + "fontFamily": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font-family][1]; a constant; defaults to the plot’s font family, which is typically [*system-ui*][2].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-family [2]: https://drafts.csswg.org/css-fonts-4/#valdef-font-family-system-ui" + }, + "fontSize": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font size][1] in pixels; either a constant or a channel; defaults to the plot’s font size, which is typically 10. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-size" + }, + "fontStyle": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font style][1]; a constant; defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-style" + }, + "fontVariant": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font variant][1]; a constant; if the **text** channel contains numbers or dates, defaults to *tabular-nums* to facilitate comparing numbers; otherwise defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant" + }, + "fontWeight": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font weight][1]; a constant; defaults to the plot’s font weight, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight" + }, + "format": { + "additionalProperties": false, + "description": "How channel values are formatted for display. If a format is a string, it is interpreted as a (UTC) time format for temporal channels, and otherwise a number format.", + "properties": { + "ariaLabel": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fill": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fillOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fontSize": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fx": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fy": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "geometry": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "height": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "href": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "length": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "opacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "path": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "r": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "rotate": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "src": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "stroke": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeWidth": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "symbol": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "text": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "title": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "weight": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "width": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "z": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + } + }, + "type": "object" + }, + "frameAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The frame anchor specifies defaults for **x** and **y** based on the plot’s frame; it may be one of the four sides (*top*, *right*, *bottom*, *left*), one of the four corners (*top-left*, *top-right*, *bottom-right*,\n*bottom-left*), or the *middle* of the frame. For example, for tips distributed horizontally at the top of the frame:\n\n```js Plot.tip(data, {x: \"date\", frameAnchor: \"top\"}) ```" + }, + "lineHeight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line height in ems; defaults to 1. The line height affects the (typically vertical) separation between adjacent baselines of text, as well as the separation between the text and its anchor point." + }, + "lineWidth": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line width in ems (e.g., 10 for about 20 characters); defaults to infinity, disabling wrapping and clipping.\n\nIf **textOverflow** is null, lines will be wrapped at the specified length. If a line is split at a soft hyphen (\\xad), a hyphen (-) will be displayed at the end of the line. If **textOverflow** is not null, lines will be clipped according to the given strategy." + }, + "monospace": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, changes the default **fontFamily** to *monospace*, and uses simplified monospaced text metrics calculations." + }, + "pathFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The image filter for the tip’s box; defaults to a drop shadow." + }, + "pointer": { + "$ref": "#/definitions/TipPointer" + }, + "pointerSize": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The size of the tip’s pointer in pixels; defaults to 12." + }, + "preferredAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If an explicit tip anchor is not specified, an anchor is chosen automatically such that the tip fits within the plot’s frame; if the preferred anchor fits, it is chosen." + }, + "textAnchor": { + "anyOf": [ + { + "const": "start", + "type": "string" + }, + { + "const": "middle", + "type": "string" + }, + { + "const": "end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [text anchor][1] controls how text is aligned (typically horizontally) relative to its anchor point; it is one of *start*, *end*, or *middle*. If the frame anchor is *left*, *top-left*, or *bottom-left*, the default text anchor is *start*; if the frame anchor is *right*, *top-right*, or\n*bottom-right*, the default is *end*; otherwise it is *middle*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/text-anchor" + }, + "textOverflow": { + "anyOf": [ + { + "type": "null" + }, + { + "const": "clip", + "type": "string" + }, + { + "const": "ellipsis", + "type": "string" + }, + { + "const": "clip-start", + "type": "string" + }, + { + "const": "clip-end", + "type": "string" + }, + { + "const": "ellipsis-start", + "type": "string" + }, + { + "const": "ellipsis-middle", + "type": "string" + }, + { + "const": "ellipsis-end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How truncate (or wrap) lines of text longer than the given **lineWidth**; one of:\n\n- null (default) - preserve overflowing characters (and wrap if needed)\n- *clip* or *clip-end* - remove characters from the end\n- *clip-start* - remove characters from the start\n- *ellipsis* or *ellipsis-end* - replace characters from the end with an ellipsis (…)\n- *ellipsis-start* - replace characters from the start with an ellipsis (…)\n- *ellipsis-middle* - replace characters from the middle with an ellipsis (…)\n\nIf no **title** was specified, if text requires truncation, a title containing the non-truncated text will be implicitly added." + }, + "textPadding": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The padding around the text in pixels; defaults to 8." + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + } + }, + "type": "object" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to generate a tooltip for this mark, and any tip options." + }, + "title": { + "$ref": "#/definitions/ChannelValue", + "description": "The title; a channel specifying accessible, short textual descriptions as strings (possibly with newlines). If the tip option is specified, the title will be displayed with an interactive tooltip instead of using the SVG [title element][1].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/title" + }, + "type": { + "const": "areaY", + "description": "The basic mark type to use to render 1D density values. Defaults to an areaY mark; lineY, dot, and text marks are also supported.", + "type": "string" + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel, typically bound to the *x* scale; defaults to the zero-based index of the data [0, 1, 2, …]." + }, + "z": { + "$ref": "#/definitions/ChannelValue", + "description": "An optional ordinal channel for grouping data into (possibly stacked) series to be drawn as separate areas; defaults to **fill** if a channel, or\n**stroke** if a channel." + } + }, + "required": [ + "data", + "mark" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "ariaDescription": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-description][1]; a constant textual description.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-description" + }, + "ariaHidden": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-hidden][1] state; a constant indicating whether the element is exposed to an accessibility API.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-hidden" + }, + "ariaLabel": { + "$ref": "#/definitions/ChannelValue", + "description": "The [aria-label][1]; a channel specifying short textual labels representing the value in the accessibility tree.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-label" + }, + "bandwidth": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The kernel density bandwidth for smoothing, in pixels. Defaults to 20." + }, + "bins": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The number of bins over which to discretize the data prior to smoothing. Defaults to 1024." + }, + "clip": { + "anyOf": [ + { + "const": "frame", + "type": "string" + }, + { + "const": "sphere", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to clip the mark; one of:\n\n- *frame* or true - clip to the plot’s frame (inner area)\n- *sphere* - clip to the projected sphere (*e.g.*, front hemisphere)\n- null or false - do not clip\n\nThe *sphere* clip option requires a geographic projection." + }, + "curve": { + "anyOf": [ + { + "$ref": "#/definitions/Curve" + }, + { + "const": "auto", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The curve (interpolation) method for connecting adjacent points. One of:\n\n- *basis* - a cubic basis spline (repeating the end points)\n- *basis-open* - an open cubic basis spline\n- *basis-closed* - a closed cubic basis spline\n- *bump-x* - a Bézier curve with horizontal tangents\n- *bump-y* - a Bézier curve with vertical tangents\n- *bundle* - a straightened cubic basis spline (suitable for lines only, not areas)\n- *cardinal* - a cubic cardinal spline (with one-sided differences at the ends)\n- *cardinal-open* - an open cubic cardinal spline\n- *cardinal-closed* - an closed cubic cardinal spline\n- *catmull-rom* - a cubic Catmull–Rom spline (with one-sided differences at the ends)\n- *catmull-rom-open* - an open cubic Catmull–Rom spline\n- *catmull-rom-closed* - a closed cubic Catmull–Rom spline\n- *linear* - a piecewise linear curve (*i.e.*, straight line segments)\n- *linear-closed* - a closed piecewise linear curve (*i.e.*, straight line segments)\n- *monotone-x* - a cubic spline that preserves monotonicity in *x*\n- *monotone-y* - a cubic spline that preserves monotonicity in *y*\n- *natural* - a natural cubic spline\n- *step* - a piecewise constant function where *y* changes at the midpoint of *x*\n- *step-after* - a piecewise constant function where *y* changes after *x*\n- *step-before* - a piecewise constant function where *x* changes after *y*\n- *auto* (default) - like *linear*, but use the (possibly spherical) projection, if any\n\nThe *auto* curve is typically used in conjunction with a spherical projection to interpolate along geodesics." + }, + "data": { + "$ref": "#/definitions/PlotMarkData", + "description": "The data source for the mark." + }, + "dx": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The horizontal offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "dy": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The vertical offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "facet": { + "anyOf": [ + { + "const": "auto", + "type": "string" + }, + { + "const": "include", + "type": "string" + }, + { + "const": "exclude", + "type": "string" + }, + { + "const": "super", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to enable or disable faceting; one of:\n\n- *auto* (default) - automatically determine if this mark should be faceted\n- *include* (or true) - draw the subset of the mark’s data in the current facet\n- *exclude* - draw the subset of the mark’s data *not* in the current facet\n- *super* - draw this mark in a single frame that covers all facets\n- null (or false) - repeat this mark’s data across all facets (*i.e.*, no faceting)\n\nWhen a mark uses *super* faceting, it is not allowed to use position scales (*x*, *y*, *fx*, or *fy*); *super* faceting is intended for decorations, such as labels and legends.\n\nWhen top-level faceting is used, the default *auto* setting is equivalent to *include* when the mark data is strictly equal to the top-level facet data; otherwise it is equivalent to null. When the *include* or *exclude* facet mode is chosen, the mark data must be parallel to the top-level facet data: the data must have the same length and order. If the data are not parallel, then the wrong data may be shown in each facet. The default\n*auto* therefore requires strict equality (`===`) for safety, and using the facet data as mark data is recommended when using the *exclude* facet mode. (To construct parallel data safely, consider using [*array*.map][1] on the facet data.)\n\nWhen mark-level faceting is used, the default *auto* setting is equivalent to *include*: the mark will be faceted if either the **fx** or **fy** channel option (or both) is specified. The null or false option will disable faceting, while *exclude* draws the subset of the mark’s data *not* in the current facet.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map" + }, + "facetAnchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "right", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "const": "left", + "type": "string" + }, + { + "const": "top-left", + "type": "string" + }, + { + "const": "top-right", + "type": "string" + }, + { + "const": "bottom-left", + "type": "string" + }, + { + "const": "bottom-right", + "type": "string" + }, + { + "const": "top-empty", + "type": "string" + }, + { + "const": "right-empty", + "type": "string" + }, + { + "const": "bottom-empty", + "type": "string" + }, + { + "const": "left-empty", + "type": "string" + }, + { + "const": "empty", + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to place the mark with respect to facets; one of:\n\n- null (default for most marks) - display the mark in each non-empty facet\n- *top*, *right*, *bottom*, or *left* - display the mark only in facets on the given side\n- *top-empty*, *right-empty*, *bottom-empty*, or *left-empty* (default for axis marks) - display the mark only in facets that have empty space on the given side: either the margin, or an empty facet\n- *empty* - display the mark in empty facets only" + }, + "fill": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill" + }, + "fillOpacity": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill-opacity][1]; a constant number between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill-opacity" + }, + "filter": { + "$ref": "#/definitions/ChannelValue", + "description": "Applies a transform to filter the mark’s index according to the given channel values; only truthy values are retained.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "fx": { + "$ref": "#/definitions/ChannelValue", + "description": "The horizontal facet position channel, for mark-level faceting, bound to the *fx* scale." + }, + "fy": { + "$ref": "#/definitions/ChannelValue", + "description": "The vertical facet position channel, for mark-level faceting, bound to the\n*fy* scale." + }, + "href": { + "$ref": "#/definitions/ChannelValue", + "description": "The [href][1]; a channel specifying URLs for clickable links. May be used in conjunction with the **target** option to open links in another window.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/href" + }, + "imageFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A CSS [filter][1]; a constant string used to adjust the rendering of images, such as *blur(5px)*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/filter" + }, + "margin": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four mark margins: **marginTop**,\n**marginRight**, **marginBottom**, and **marginLeft**; typically defaults to 0, except for axis marks." + }, + "marginBottom": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s bottom margin; the minimum distance in pixels between the bottom edges of the inner and outer plot area." + }, + "marginLeft": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s left margin; the minimum distance in pixels between the left edges of the inner and outer plot area." + }, + "marginRight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s right margin; the minimum distance in pixels between the right edges of the mark’s inner and outer plot area." + }, + "marginTop": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s top margin; the minimum distance in pixels between the top edges of the inner and outer plot area." + }, + "mark": { + "const": "densityY", + "description": "A densityY mark that visualizes smoothed point cloud densities along the\n**y** dimension. The mark bins the data, counts the number of records that fall into each bin, smooths the resulting counts, and then plots the smoothed distribution, by default using an areaY mark.\n\nSet the *type* property to use a different base mark type.", + "type": "string" + }, + "marker": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for markerStart, markerMid, and markerEnd; one of:\n\n- a marker name such as *arrow* or *circle*\n- *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*" + }, + "markerEnd": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The marker for the ending point of a line segment; one of:\n\n- a marker name such as *arrow* or *circle*\n* *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*" + }, + "markerMid": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The marker for any middle (interior) points of a line segment. If the line segment only has a start and end point, this option has no effect. One of:\n\n- a marker name such as *arrow* or *circle*\n* *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*\n* a function - a custom marker function; see below" + }, + "markerStart": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The marker for the starting point of a line segment; one of:\n\n- a marker name such as *arrow* or *circle*\n* *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*" + }, + "mixBlendMode": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [mix-blend-mode][1]; a constant string specifying how to blend content such as *multiply*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode" + }, + "opacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally. For faster rendering, prefer the **strokeOpacity** or **fillOpacity** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/opacity" + }, + "paintOrder": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [paint-order][1]; a constant string specifying the order in which the\n**fill**, **stroke**, and any markers are drawn; defaults to *normal*, which draws the fill, then stroke, then markers; defaults to *stroke* for the text mark to create a “halo” around text to improve legibility.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/paint-order" + }, + "pointerEvents": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [pointer-events][1] property; a constant string such as *none*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/pointer-events" + }, + "reverse": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Applies a transform to reverse the order of the mark’s index, say for reverse input order." + }, + "select": { + "$ref": "#/definitions/SelectFilter", + "description": "Applies a filter transform after data is loaded to highlight selected values only. For example, `first` and `last` select the first or last values of series only (using the *z* channel to separate series). Meanwhile, `nearestX` and `nearestY` select the point nearest to the pointer along the *x* or *y* channel dimension. Unlike Mosaic selections, a mark level *select* is internal to the mark only, and does not populate a param or selection value to be shared across clients.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "shapeRendering": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [shape-rendering][1]; a constant string such as *crispEdges*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/shape-rendering" + }, + "sort": { + "anyOf": [ + { + "$ref": "#/definitions/SortOrder" + }, + { + "$ref": "#/definitions/ChannelDomainSort" + } + ], + "description": "Either applies a transform to sort the mark’s index by the specified channel values, or imputes ordinal scale domains from this mark’s channels.\n\nWhen imputing ordinal scale domains from channel values, the **sort** option is an object whose keys are ordinal scale names such as *x* or *fx*, and whose values are channel names such as *y*, *y1*, or *y2*. For example, to impute the *y* scale’s domain from the associated *x* channel values in ascending order:\n\n```js sort: {y: \"x\"} ```\n\nFor different sort options for different scales, replace the channel name with a *value* object and per-scale options:\n\n```js sort: {y: {value: \"-x\"}} ```\n\nWhen sorting the mark’s index, the **sort** option is instead one of:\n\n- a channel value definition for sorting given values in ascending order\n- a {value, order} object for sorting given values\n- a {channel, order} object for sorting the named channel’s values" + }, + "stroke": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke" + }, + "strokeDasharray": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dasharray][1]; a constant number indicating the length in pixels of alternating dashes and gaps, or a constant string of numbers separated by spaces or commas (_e.g._, *10 2* for dashes of 10 pixels separated by gaps of 2 pixels), or *none* (the default) for no dashing\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dasharray" + }, + "strokeDashoffset": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dashoffset][1]; a constant indicating the offset in pixels of the first dash along the stroke; defaults to zero.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dashoffset" + }, + "strokeLinecap": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linecap][1]; a constant specifying how to cap stroked paths, such as *butt*, *round*, or *square*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linecap" + }, + "strokeLinejoin": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linejoin][1]; a constant specifying how to join stroked paths, such as *bevel*, *miter*, *miter-clip*, or *round*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linejoin" + }, + "strokeMiterlimit": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-miterlimit][1]; a constant number specifying how to limit the length of *miter* joins on stroked paths.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-miterlimit" + }, + "strokeOpacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-opacity" + }, + "strokeWidth": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-width][1]; a constant number in pixels, or a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-width" + }, + "target": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [target][1]; a constant string specifying the target window (_e.g._,\n*_blank*) for clickable links; used in conjunction with the **href** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/target" + }, + "tension": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The tension option only has an effect on bundle, cardinal and Catmull–Rom splines (*bundle*, *cardinal*, *cardinal-open*, *cardinal-closed*,\n*catmull-rom*, *catmull-rom-open*, and *catmull-rom-closed*). For bundle splines, it corresponds to [beta][1]; for cardinal splines, [tension][2]; for Catmull–Rom splines, [alpha][3].\n\n[1]: https://d3js.org/d3-shape/curve#curveBundle_beta [2]: https://d3js.org/d3-shape/curve#curveCardinal_tension [3]: https://d3js.org/d3-shape/curve#curveCatmullRom_alpha" + }, + "tip": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/TipPointer" + }, + { + "properties": { + "anchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The tip anchor specifies how to orient the tip box relative to its anchor position; it refers to the part of the tip box that is attached to the anchor point. For example, the *top-left* anchor places the top-left corner of tip box near the anchor position, hence placing the tip box below and to the right of the anchor position." + }, + "fontFamily": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font-family][1]; a constant; defaults to the plot’s font family, which is typically [*system-ui*][2].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-family [2]: https://drafts.csswg.org/css-fonts-4/#valdef-font-family-system-ui" + }, + "fontSize": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font size][1] in pixels; either a constant or a channel; defaults to the plot’s font size, which is typically 10. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-size" + }, + "fontStyle": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font style][1]; a constant; defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-style" + }, + "fontVariant": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font variant][1]; a constant; if the **text** channel contains numbers or dates, defaults to *tabular-nums* to facilitate comparing numbers; otherwise defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant" + }, + "fontWeight": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font weight][1]; a constant; defaults to the plot’s font weight, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight" + }, + "format": { + "additionalProperties": false, + "description": "How channel values are formatted for display. If a format is a string, it is interpreted as a (UTC) time format for temporal channels, and otherwise a number format.", + "properties": { + "ariaLabel": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fill": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fillOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fontSize": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fx": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fy": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "geometry": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "height": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "href": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "length": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "opacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "path": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "r": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "rotate": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "src": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "stroke": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeWidth": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "symbol": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "text": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "title": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "weight": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "width": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "z": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + } + }, + "type": "object" + }, + "frameAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The frame anchor specifies defaults for **x** and **y** based on the plot’s frame; it may be one of the four sides (*top*, *right*, *bottom*, *left*), one of the four corners (*top-left*, *top-right*, *bottom-right*,\n*bottom-left*), or the *middle* of the frame. For example, for tips distributed horizontally at the top of the frame:\n\n```js Plot.tip(data, {x: \"date\", frameAnchor: \"top\"}) ```" + }, + "lineHeight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line height in ems; defaults to 1. The line height affects the (typically vertical) separation between adjacent baselines of text, as well as the separation between the text and its anchor point." + }, + "lineWidth": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line width in ems (e.g., 10 for about 20 characters); defaults to infinity, disabling wrapping and clipping.\n\nIf **textOverflow** is null, lines will be wrapped at the specified length. If a line is split at a soft hyphen (\\xad), a hyphen (-) will be displayed at the end of the line. If **textOverflow** is not null, lines will be clipped according to the given strategy." + }, + "monospace": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, changes the default **fontFamily** to *monospace*, and uses simplified monospaced text metrics calculations." + }, + "pathFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The image filter for the tip’s box; defaults to a drop shadow." + }, + "pointer": { + "$ref": "#/definitions/TipPointer" + }, + "pointerSize": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The size of the tip’s pointer in pixels; defaults to 12." + }, + "preferredAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If an explicit tip anchor is not specified, an anchor is chosen automatically such that the tip fits within the plot’s frame; if the preferred anchor fits, it is chosen." + }, + "textAnchor": { + "anyOf": [ + { + "const": "start", + "type": "string" + }, + { + "const": "middle", + "type": "string" + }, + { + "const": "end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [text anchor][1] controls how text is aligned (typically horizontally) relative to its anchor point; it is one of *start*, *end*, or *middle*. If the frame anchor is *left*, *top-left*, or *bottom-left*, the default text anchor is *start*; if the frame anchor is *right*, *top-right*, or\n*bottom-right*, the default is *end*; otherwise it is *middle*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/text-anchor" + }, + "textOverflow": { + "anyOf": [ + { + "type": "null" + }, + { + "const": "clip", + "type": "string" + }, + { + "const": "ellipsis", + "type": "string" + }, + { + "const": "clip-start", + "type": "string" + }, + { + "const": "clip-end", + "type": "string" + }, + { + "const": "ellipsis-start", + "type": "string" + }, + { + "const": "ellipsis-middle", + "type": "string" + }, + { + "const": "ellipsis-end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How truncate (or wrap) lines of text longer than the given **lineWidth**; one of:\n\n- null (default) - preserve overflowing characters (and wrap if needed)\n- *clip* or *clip-end* - remove characters from the end\n- *clip-start* - remove characters from the start\n- *ellipsis* or *ellipsis-end* - replace characters from the end with an ellipsis (…)\n- *ellipsis-start* - replace characters from the start with an ellipsis (…)\n- *ellipsis-middle* - replace characters from the middle with an ellipsis (…)\n\nIf no **title** was specified, if text requires truncation, a title containing the non-truncated text will be implicitly added." + }, + "textPadding": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The padding around the text in pixels; defaults to 8." + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + } + }, + "type": "object" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to generate a tooltip for this mark, and any tip options." + }, + "title": { + "$ref": "#/definitions/ChannelValue", + "description": "The title; a channel specifying accessible, short textual descriptions as strings (possibly with newlines). If the tip option is specified, the title will be displayed with an interactive tooltip instead of using the SVG [title element][1].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/title" + }, + "type": { + "const": "lineY", + "description": "The basic mark type to use to render 1D density values. Defaults to an areaY mark; lineY, dot, and text marks are also supported.", + "type": "string" + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel, typically bound to the *x* scale; defaults to the zero-based index of the data [0, 1, 2, …]." + }, + "z": { + "$ref": "#/definitions/ChannelValue", + "description": "An optional ordinal channel for grouping data into (possibly stacked) series to be drawn as separate lines. If not specified, it defaults to\n**fill** if a channel, or **stroke** if a channel." + } + }, + "required": [ + "data", + "mark", + "type" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "ariaDescription": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-description][1]; a constant textual description.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-description" + }, + "ariaHidden": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-hidden][1] state; a constant indicating whether the element is exposed to an accessibility API.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-hidden" + }, + "ariaLabel": { + "$ref": "#/definitions/ChannelValue", + "description": "The [aria-label][1]; a channel specifying short textual labels representing the value in the accessibility tree.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-label" + }, + "bandwidth": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The kernel density bandwidth for smoothing, in pixels. Defaults to 20." + }, + "bins": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The number of bins over which to discretize the data prior to smoothing. Defaults to 1024." + }, + "clip": { + "anyOf": [ + { + "const": "frame", + "type": "string" + }, + { + "const": "sphere", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to clip the mark; one of:\n\n- *frame* or true - clip to the plot’s frame (inner area)\n- *sphere* - clip to the projected sphere (*e.g.*, front hemisphere)\n- null or false - do not clip\n\nThe *sphere* clip option requires a geographic projection." + }, + "data": { + "$ref": "#/definitions/PlotMarkData", + "description": "The data source for the mark." + }, + "dx": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The horizontal offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "dy": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The vertical offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "facet": { + "anyOf": [ + { + "const": "auto", + "type": "string" + }, + { + "const": "include", + "type": "string" + }, + { + "const": "exclude", + "type": "string" + }, + { + "const": "super", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to enable or disable faceting; one of:\n\n- *auto* (default) - automatically determine if this mark should be faceted\n- *include* (or true) - draw the subset of the mark’s data in the current facet\n- *exclude* - draw the subset of the mark’s data *not* in the current facet\n- *super* - draw this mark in a single frame that covers all facets\n- null (or false) - repeat this mark’s data across all facets (*i.e.*, no faceting)\n\nWhen a mark uses *super* faceting, it is not allowed to use position scales (*x*, *y*, *fx*, or *fy*); *super* faceting is intended for decorations, such as labels and legends.\n\nWhen top-level faceting is used, the default *auto* setting is equivalent to *include* when the mark data is strictly equal to the top-level facet data; otherwise it is equivalent to null. When the *include* or *exclude* facet mode is chosen, the mark data must be parallel to the top-level facet data: the data must have the same length and order. If the data are not parallel, then the wrong data may be shown in each facet. The default\n*auto* therefore requires strict equality (`===`) for safety, and using the facet data as mark data is recommended when using the *exclude* facet mode. (To construct parallel data safely, consider using [*array*.map][1] on the facet data.)\n\nWhen mark-level faceting is used, the default *auto* setting is equivalent to *include*: the mark will be faceted if either the **fx** or **fy** channel option (or both) is specified. The null or false option will disable faceting, while *exclude* draws the subset of the mark’s data *not* in the current facet.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map" + }, + "facetAnchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "right", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "const": "left", + "type": "string" + }, + { + "const": "top-left", + "type": "string" + }, + { + "const": "top-right", + "type": "string" + }, + { + "const": "bottom-left", + "type": "string" + }, + { + "const": "bottom-right", + "type": "string" + }, + { + "const": "top-empty", + "type": "string" + }, + { + "const": "right-empty", + "type": "string" + }, + { + "const": "bottom-empty", + "type": "string" + }, + { + "const": "left-empty", + "type": "string" + }, + { + "const": "empty", + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to place the mark with respect to facets; one of:\n\n- null (default for most marks) - display the mark in each non-empty facet\n- *top*, *right*, *bottom*, or *left* - display the mark only in facets on the given side\n- *top-empty*, *right-empty*, *bottom-empty*, or *left-empty* (default for axis marks) - display the mark only in facets that have empty space on the given side: either the margin, or an empty facet\n- *empty* - display the mark in empty facets only" + }, + "fill": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill" + }, + "fillOpacity": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill-opacity][1]; a constant number between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill-opacity" + }, + "filter": { + "$ref": "#/definitions/ChannelValue", + "description": "Applies a transform to filter the mark’s index according to the given channel values; only truthy values are retained.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "frameAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The frame anchor specifies defaults for **x** and **y** based on the plot’s frame; it may be one of the four sides (*top*, *right*, *bottom*, *left*), one of the four corners (*top-left*, *top-right*, *bottom-right*,\n*bottom-left*), or the *middle* of the frame. For example, for dots distributed horizontally at the top of the frame:\n\n```js Plot.dot(data, {x: \"date\", frameAnchor: \"top\"}) ```" + }, + "fx": { + "$ref": "#/definitions/ChannelValue", + "description": "The horizontal facet position channel, for mark-level faceting, bound to the *fx* scale." + }, + "fy": { + "$ref": "#/definitions/ChannelValue", + "description": "The vertical facet position channel, for mark-level faceting, bound to the\n*fy* scale." + }, + "href": { + "$ref": "#/definitions/ChannelValue", + "description": "The [href][1]; a channel specifying URLs for clickable links. May be used in conjunction with the **target** option to open links in another window.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/href" + }, + "imageFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A CSS [filter][1]; a constant string used to adjust the rendering of images, such as *blur(5px)*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/filter" + }, + "margin": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four mark margins: **marginTop**,\n**marginRight**, **marginBottom**, and **marginLeft**; typically defaults to 0, except for axis marks." + }, + "marginBottom": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s bottom margin; the minimum distance in pixels between the bottom edges of the inner and outer plot area." + }, + "marginLeft": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s left margin; the minimum distance in pixels between the left edges of the inner and outer plot area." + }, + "marginRight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s right margin; the minimum distance in pixels between the right edges of the mark’s inner and outer plot area." + }, + "marginTop": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s top margin; the minimum distance in pixels between the top edges of the inner and outer plot area." + }, + "mark": { + "const": "densityY", + "description": "A densityY mark that visualizes smoothed point cloud densities along the\n**y** dimension. The mark bins the data, counts the number of records that fall into each bin, smooths the resulting counts, and then plots the smoothed distribution, by default using an areaY mark.\n\nSet the *type* property to use a different base mark type.", + "type": "string" + }, + "mixBlendMode": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [mix-blend-mode][1]; a constant string specifying how to blend content such as *multiply*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode" + }, + "opacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally. For faster rendering, prefer the **strokeOpacity** or **fillOpacity** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/opacity" + }, + "paintOrder": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [paint-order][1]; a constant string specifying the order in which the\n**fill**, **stroke**, and any markers are drawn; defaults to *normal*, which draws the fill, then stroke, then markers; defaults to *stroke* for the text mark to create a “halo” around text to improve legibility.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/paint-order" + }, + "pointerEvents": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [pointer-events][1] property; a constant string such as *none*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/pointer-events" + }, + "r": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The radius of dots; either a channel or constant. When a number, it is interpreted as a constant radius in pixels. Otherwise it is interpreted as a channel, typically bound to the *r* channel, which defaults to the *sqrt* type for proportional symbols. The radius defaults to 4.5 pixels when using the **symbol** channel, and otherwise 3 pixels. Dots with a nonpositive radius are not drawn." + }, + "reverse": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Applies a transform to reverse the order of the mark’s index, say for reverse input order." + }, + "rotate": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The rotation angle of dots in degrees clockwise; either a channel or a constant. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel. Defaults to 0°, pointing up." + }, + "select": { + "$ref": "#/definitions/SelectFilter", + "description": "Applies a filter transform after data is loaded to highlight selected values only. For example, `first` and `last` select the first or last values of series only (using the *z* channel to separate series). Meanwhile, `nearestX` and `nearestY` select the point nearest to the pointer along the *x* or *y* channel dimension. Unlike Mosaic selections, a mark level *select* is internal to the mark only, and does not populate a param or selection value to be shared across clients.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "shapeRendering": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [shape-rendering][1]; a constant string such as *crispEdges*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/shape-rendering" + }, + "sort": { + "anyOf": [ + { + "$ref": "#/definitions/SortOrder" + }, + { + "$ref": "#/definitions/ChannelDomainSort" + } + ], + "description": "Either applies a transform to sort the mark’s index by the specified channel values, or imputes ordinal scale domains from this mark’s channels.\n\nWhen imputing ordinal scale domains from channel values, the **sort** option is an object whose keys are ordinal scale names such as *x* or *fx*, and whose values are channel names such as *y*, *y1*, or *y2*. For example, to impute the *y* scale’s domain from the associated *x* channel values in ascending order:\n\n```js sort: {y: \"x\"} ```\n\nFor different sort options for different scales, replace the channel name with a *value* object and per-scale options:\n\n```js sort: {y: {value: \"-x\"}} ```\n\nWhen sorting the mark’s index, the **sort** option is instead one of:\n\n- a channel value definition for sorting given values in ascending order\n- a {value, order} object for sorting given values\n- a {channel, order} object for sorting the named channel’s values" + }, + "stroke": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke" + }, + "strokeDasharray": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dasharray][1]; a constant number indicating the length in pixels of alternating dashes and gaps, or a constant string of numbers separated by spaces or commas (_e.g._, *10 2* for dashes of 10 pixels separated by gaps of 2 pixels), or *none* (the default) for no dashing\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dasharray" + }, + "strokeDashoffset": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dashoffset][1]; a constant indicating the offset in pixels of the first dash along the stroke; defaults to zero.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dashoffset" + }, + "strokeLinecap": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linecap][1]; a constant specifying how to cap stroked paths, such as *butt*, *round*, or *square*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linecap" + }, + "strokeLinejoin": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linejoin][1]; a constant specifying how to join stroked paths, such as *bevel*, *miter*, *miter-clip*, or *round*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linejoin" + }, + "strokeMiterlimit": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-miterlimit][1]; a constant number specifying how to limit the length of *miter* joins on stroked paths.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-miterlimit" + }, + "strokeOpacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-opacity" + }, + "strokeWidth": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-width][1]; a constant number in pixels, or a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-width" + }, + "symbol": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/SymbolType" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The categorical symbol; either a channel or a constant. A constant symbol can be specified by a valid symbol name such as *star*, or a symbol object (implementing the draw method); otherwise it is interpreted as a channel. Defaults to *circle* for the **dot** mark, and *hexagon* for the\n**hexagon** mark.\n\nIf the **symbol** channel’s values are all symbols, symbol names, or nullish, the channel is unscaled (values are interpreted literally); otherwise, the channel is bound to the *symbol* scale." + }, + "target": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [target][1]; a constant string specifying the target window (_e.g._,\n*_blank*) for clickable links; used in conjunction with the **href** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/target" + }, + "tip": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/TipPointer" + }, + { + "properties": { + "anchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The tip anchor specifies how to orient the tip box relative to its anchor position; it refers to the part of the tip box that is attached to the anchor point. For example, the *top-left* anchor places the top-left corner of tip box near the anchor position, hence placing the tip box below and to the right of the anchor position." + }, + "fontFamily": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font-family][1]; a constant; defaults to the plot’s font family, which is typically [*system-ui*][2].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-family [2]: https://drafts.csswg.org/css-fonts-4/#valdef-font-family-system-ui" + }, + "fontSize": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font size][1] in pixels; either a constant or a channel; defaults to the plot’s font size, which is typically 10. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-size" + }, + "fontStyle": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font style][1]; a constant; defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-style" + }, + "fontVariant": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font variant][1]; a constant; if the **text** channel contains numbers or dates, defaults to *tabular-nums* to facilitate comparing numbers; otherwise defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant" + }, + "fontWeight": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font weight][1]; a constant; defaults to the plot’s font weight, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight" + }, + "format": { + "additionalProperties": false, + "description": "How channel values are formatted for display. If a format is a string, it is interpreted as a (UTC) time format for temporal channels, and otherwise a number format.", + "properties": { + "ariaLabel": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fill": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fillOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fontSize": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fx": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fy": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "geometry": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "height": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "href": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "length": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "opacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "path": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "r": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "rotate": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "src": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "stroke": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeWidth": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "symbol": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "text": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "title": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "weight": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "width": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "z": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + } + }, + "type": "object" + }, + "frameAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The frame anchor specifies defaults for **x** and **y** based on the plot’s frame; it may be one of the four sides (*top*, *right*, *bottom*, *left*), one of the four corners (*top-left*, *top-right*, *bottom-right*,\n*bottom-left*), or the *middle* of the frame. For example, for tips distributed horizontally at the top of the frame:\n\n```js Plot.tip(data, {x: \"date\", frameAnchor: \"top\"}) ```" + }, + "lineHeight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line height in ems; defaults to 1. The line height affects the (typically vertical) separation between adjacent baselines of text, as well as the separation between the text and its anchor point." + }, + "lineWidth": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line width in ems (e.g., 10 for about 20 characters); defaults to infinity, disabling wrapping and clipping.\n\nIf **textOverflow** is null, lines will be wrapped at the specified length. If a line is split at a soft hyphen (\\xad), a hyphen (-) will be displayed at the end of the line. If **textOverflow** is not null, lines will be clipped according to the given strategy." + }, + "monospace": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, changes the default **fontFamily** to *monospace*, and uses simplified monospaced text metrics calculations." + }, + "pathFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The image filter for the tip’s box; defaults to a drop shadow." + }, + "pointer": { + "$ref": "#/definitions/TipPointer" + }, + "pointerSize": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The size of the tip’s pointer in pixels; defaults to 12." + }, + "preferredAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If an explicit tip anchor is not specified, an anchor is chosen automatically such that the tip fits within the plot’s frame; if the preferred anchor fits, it is chosen." + }, + "textAnchor": { + "anyOf": [ + { + "const": "start", + "type": "string" + }, + { + "const": "middle", + "type": "string" + }, + { + "const": "end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [text anchor][1] controls how text is aligned (typically horizontally) relative to its anchor point; it is one of *start*, *end*, or *middle*. If the frame anchor is *left*, *top-left*, or *bottom-left*, the default text anchor is *start*; if the frame anchor is *right*, *top-right*, or\n*bottom-right*, the default is *end*; otherwise it is *middle*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/text-anchor" + }, + "textOverflow": { + "anyOf": [ + { + "type": "null" + }, + { + "const": "clip", + "type": "string" + }, + { + "const": "ellipsis", + "type": "string" + }, + { + "const": "clip-start", + "type": "string" + }, + { + "const": "clip-end", + "type": "string" + }, + { + "const": "ellipsis-start", + "type": "string" + }, + { + "const": "ellipsis-middle", + "type": "string" + }, + { + "const": "ellipsis-end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How truncate (or wrap) lines of text longer than the given **lineWidth**; one of:\n\n- null (default) - preserve overflowing characters (and wrap if needed)\n- *clip* or *clip-end* - remove characters from the end\n- *clip-start* - remove characters from the start\n- *ellipsis* or *ellipsis-end* - replace characters from the end with an ellipsis (…)\n- *ellipsis-start* - replace characters from the start with an ellipsis (…)\n- *ellipsis-middle* - replace characters from the middle with an ellipsis (…)\n\nIf no **title** was specified, if text requires truncation, a title containing the non-truncated text will be implicitly added." + }, + "textPadding": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The padding around the text in pixels; defaults to 8." + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + } + }, + "type": "object" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to generate a tooltip for this mark, and any tip options." + }, + "title": { + "$ref": "#/definitions/ChannelValue", + "description": "The title; a channel specifying accessible, short textual descriptions as strings (possibly with newlines). If the tip option is specified, the title will be displayed with an interactive tooltip instead of using the SVG [title element][1].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/title" + }, + "type": { + "description": "The basic mark type to use to render 1D density values. Defaults to an areaY mark; lineY, dot, and text marks are also supported.", + "enum": [ + "dot", + "dotY", + "circle", + "hexagon" + ], + "type": "string" + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel specifying the dot’s center, typically bound to the *x* scale." + }, + "z": { + "$ref": "#/definitions/ChannelValue", + "description": "An optional ordinal channel for grouping data into series." + } + }, + "required": [ + "data", + "mark", + "type" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "ariaDescription": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-description][1]; a constant textual description.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-description" + }, + "ariaHidden": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-hidden][1] state; a constant indicating whether the element is exposed to an accessibility API.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-hidden" + }, + "ariaLabel": { + "$ref": "#/definitions/ChannelValue", + "description": "The [aria-label][1]; a channel specifying short textual labels representing the value in the accessibility tree.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-label" + }, + "bandwidth": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The kernel density bandwidth for smoothing, in pixels. Defaults to 20." + }, + "bins": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The number of bins over which to discretize the data prior to smoothing. Defaults to 1024." + }, + "clip": { + "anyOf": [ + { + "const": "frame", + "type": "string" + }, + { + "const": "sphere", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to clip the mark; one of:\n\n- *frame* or true - clip to the plot’s frame (inner area)\n- *sphere* - clip to the projected sphere (*e.g.*, front hemisphere)\n- null or false - do not clip\n\nThe *sphere* clip option requires a geographic projection." + }, + "data": { + "$ref": "#/definitions/PlotMarkData", + "description": "The data source for the mark." + }, + "dx": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The horizontal offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "dy": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The vertical offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "facet": { + "anyOf": [ + { + "const": "auto", + "type": "string" + }, + { + "const": "include", + "type": "string" + }, + { + "const": "exclude", + "type": "string" + }, + { + "const": "super", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to enable or disable faceting; one of:\n\n- *auto* (default) - automatically determine if this mark should be faceted\n- *include* (or true) - draw the subset of the mark’s data in the current facet\n- *exclude* - draw the subset of the mark’s data *not* in the current facet\n- *super* - draw this mark in a single frame that covers all facets\n- null (or false) - repeat this mark’s data across all facets (*i.e.*, no faceting)\n\nWhen a mark uses *super* faceting, it is not allowed to use position scales (*x*, *y*, *fx*, or *fy*); *super* faceting is intended for decorations, such as labels and legends.\n\nWhen top-level faceting is used, the default *auto* setting is equivalent to *include* when the mark data is strictly equal to the top-level facet data; otherwise it is equivalent to null. When the *include* or *exclude* facet mode is chosen, the mark data must be parallel to the top-level facet data: the data must have the same length and order. If the data are not parallel, then the wrong data may be shown in each facet. The default\n*auto* therefore requires strict equality (`===`) for safety, and using the facet data as mark data is recommended when using the *exclude* facet mode. (To construct parallel data safely, consider using [*array*.map][1] on the facet data.)\n\nWhen mark-level faceting is used, the default *auto* setting is equivalent to *include*: the mark will be faceted if either the **fx** or **fy** channel option (or both) is specified. The null or false option will disable faceting, while *exclude* draws the subset of the mark’s data *not* in the current facet.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map" + }, + "facetAnchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "right", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "const": "left", + "type": "string" + }, + { + "const": "top-left", + "type": "string" + }, + { + "const": "top-right", + "type": "string" + }, + { + "const": "bottom-left", + "type": "string" + }, + { + "const": "bottom-right", + "type": "string" + }, + { + "const": "top-empty", + "type": "string" + }, + { + "const": "right-empty", + "type": "string" + }, + { + "const": "bottom-empty", + "type": "string" + }, + { + "const": "left-empty", + "type": "string" + }, + { + "const": "empty", + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to place the mark with respect to facets; one of:\n\n- null (default for most marks) - display the mark in each non-empty facet\n- *top*, *right*, *bottom*, or *left* - display the mark only in facets on the given side\n- *top-empty*, *right-empty*, *bottom-empty*, or *left-empty* (default for axis marks) - display the mark only in facets that have empty space on the given side: either the margin, or an empty facet\n- *empty* - display the mark in empty facets only" + }, + "fill": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill" + }, + "fillOpacity": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill-opacity][1]; a constant number between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill-opacity" + }, + "filter": { + "$ref": "#/definitions/ChannelValue", + "description": "Applies a transform to filter the mark’s index according to the given channel values; only truthy values are retained.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "fontFamily": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font-family][1]; a constant; defaults to the plot’s font family, which is typically [*system-ui*][2].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-family [2]: https://drafts.csswg.org/css-fonts-4/#valdef-font-family-system-ui" + }, + "fontSize": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font size][1] in pixels; either a constant or a channel; defaults to the plot’s font size, which is typically 10. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-size" + }, + "fontStyle": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font style][1]; a constant; defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-style" + }, + "fontVariant": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font variant][1]; a constant; if the **text** channel contains numbers or dates, defaults to *tabular-nums* to facilitate comparing numbers; otherwise defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant" + }, + "fontWeight": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font weight][1]; a constant; defaults to the plot’s font weight, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight" + }, + "frameAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The frame anchor specifies defaults for **x** and **y**, along with\n**textAnchor** and **lineAnchor**, based on the plot’s frame; it may be one of the four sides (*top*, *right*, *bottom*, *left*), one of the four corners (*top-left*, *top-right*, *bottom-right*, *bottom-left*), or the\n*middle* of the frame." + }, + "fx": { + "$ref": "#/definitions/ChannelValue", + "description": "The horizontal facet position channel, for mark-level faceting, bound to the *fx* scale." + }, + "fy": { + "$ref": "#/definitions/ChannelValue", + "description": "The vertical facet position channel, for mark-level faceting, bound to the\n*fy* scale." + }, + "href": { + "$ref": "#/definitions/ChannelValue", + "description": "The [href][1]; a channel specifying URLs for clickable links. May be used in conjunction with the **target** option to open links in another window.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/href" + }, + "imageFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A CSS [filter][1]; a constant string used to adjust the rendering of images, such as *blur(5px)*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/filter" + }, + "lineAnchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "middle", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line anchor controls how text is aligned (typically vertically) relative to its anchor point; it is one of *top*, *bottom*, or *middle*. If the frame anchor is *top*, *top-left*, or *top-right*, the default line anchor is *top*; if the frame anchor is *bottom*, *bottom-right*, or\n*bottom-left*, the default is *bottom*; otherwise it is *middle*." + }, + "lineHeight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line height in ems; defaults to 1. The line height affects the (typically vertical) separation between adjacent baselines of text, as well as the separation between the text and its anchor point." + }, + "lineWidth": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line width in ems (e.g., 10 for about 20 characters); defaults to infinity, disabling wrapping and clipping.\n\nIf **textOverflow** is null, lines will be wrapped at the specified length. If a line is split at a soft hyphen (\\xad), a hyphen (-) will be displayed at the end of the line. If **textOverflow** is not null, lines will be clipped according to the given strategy." + }, + "margin": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four mark margins: **marginTop**,\n**marginRight**, **marginBottom**, and **marginLeft**; typically defaults to 0, except for axis marks." + }, + "marginBottom": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s bottom margin; the minimum distance in pixels between the bottom edges of the inner and outer plot area." + }, + "marginLeft": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s left margin; the minimum distance in pixels between the left edges of the inner and outer plot area." + }, + "marginRight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s right margin; the minimum distance in pixels between the right edges of the mark’s inner and outer plot area." + }, + "marginTop": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s top margin; the minimum distance in pixels between the top edges of the inner and outer plot area." + }, + "mark": { + "const": "densityY", + "description": "A densityY mark that visualizes smoothed point cloud densities along the\n**y** dimension. The mark bins the data, counts the number of records that fall into each bin, smooths the resulting counts, and then plots the smoothed distribution, by default using an areaY mark.\n\nSet the *type* property to use a different base mark type.", + "type": "string" + }, + "mixBlendMode": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [mix-blend-mode][1]; a constant string specifying how to blend content such as *multiply*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode" + }, + "monospace": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, changes the default **fontFamily** to *monospace*, and uses simplified monospaced text metrics calculations." + }, + "opacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally. For faster rendering, prefer the **strokeOpacity** or **fillOpacity** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/opacity" + }, + "paintOrder": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [paint-order][1]; a constant string specifying the order in which the\n**fill**, **stroke**, and any markers are drawn; defaults to *normal*, which draws the fill, then stroke, then markers; defaults to *stroke* for the text mark to create a “halo” around text to improve legibility.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/paint-order" + }, + "pointerEvents": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [pointer-events][1] property; a constant string such as *none*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/pointer-events" + }, + "reverse": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Applies a transform to reverse the order of the mark’s index, say for reverse input order." + }, + "rotate": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The rotation angle in degrees clockwise; a constant or a channel; defaults to 0°. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel." + }, + "select": { + "$ref": "#/definitions/SelectFilter", + "description": "Applies a filter transform after data is loaded to highlight selected values only. For example, `first` and `last` select the first or last values of series only (using the *z* channel to separate series). Meanwhile, `nearestX` and `nearestY` select the point nearest to the pointer along the *x* or *y* channel dimension. Unlike Mosaic selections, a mark level *select* is internal to the mark only, and does not populate a param or selection value to be shared across clients.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "shapeRendering": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [shape-rendering][1]; a constant string such as *crispEdges*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/shape-rendering" + }, + "sort": { + "anyOf": [ + { + "$ref": "#/definitions/SortOrder" + }, + { + "$ref": "#/definitions/ChannelDomainSort" + } + ], + "description": "Either applies a transform to sort the mark’s index by the specified channel values, or imputes ordinal scale domains from this mark’s channels.\n\nWhen imputing ordinal scale domains from channel values, the **sort** option is an object whose keys are ordinal scale names such as *x* or *fx*, and whose values are channel names such as *y*, *y1*, or *y2*. For example, to impute the *y* scale’s domain from the associated *x* channel values in ascending order:\n\n```js sort: {y: \"x\"} ```\n\nFor different sort options for different scales, replace the channel name with a *value* object and per-scale options:\n\n```js sort: {y: {value: \"-x\"}} ```\n\nWhen sorting the mark’s index, the **sort** option is instead one of:\n\n- a channel value definition for sorting given values in ascending order\n- a {value, order} object for sorting given values\n- a {channel, order} object for sorting the named channel’s values" + }, + "stroke": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke" + }, + "strokeDasharray": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dasharray][1]; a constant number indicating the length in pixels of alternating dashes and gaps, or a constant string of numbers separated by spaces or commas (_e.g._, *10 2* for dashes of 10 pixels separated by gaps of 2 pixels), or *none* (the default) for no dashing\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dasharray" + }, + "strokeDashoffset": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dashoffset][1]; a constant indicating the offset in pixels of the first dash along the stroke; defaults to zero.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dashoffset" + }, + "strokeLinecap": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linecap][1]; a constant specifying how to cap stroked paths, such as *butt*, *round*, or *square*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linecap" + }, + "strokeLinejoin": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linejoin][1]; a constant specifying how to join stroked paths, such as *bevel*, *miter*, *miter-clip*, or *round*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linejoin" + }, + "strokeMiterlimit": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-miterlimit][1]; a constant number specifying how to limit the length of *miter* joins on stroked paths.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-miterlimit" + }, + "strokeOpacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-opacity" + }, + "strokeWidth": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-width][1]; a constant number in pixels, or a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-width" + }, + "target": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [target][1]; a constant string specifying the target window (_e.g._,\n*_blank*) for clickable links; used in conjunction with the **href** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/target" + }, + "text": { + "$ref": "#/definitions/ChannelValue", + "description": "The text contents channel, possibly with line breaks (\\n, \\r\\n, or \\r). If not specified, defaults to the zero-based index [0, 1, 2, …]." + }, + "textAnchor": { + "anyOf": [ + { + "const": "start", + "type": "string" + }, + { + "const": "middle", + "type": "string" + }, + { + "const": "end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [text anchor][1] controls how text is aligned (typically horizontally) relative to its anchor point; it is one of *start*, *end*, or *middle*. If the frame anchor is *left*, *top-left*, or *bottom-left*, the default text anchor is *start*; if the frame anchor is *right*, *top-right*, or\n*bottom-right*, the default is *end*; otherwise it is *middle*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/text-anchor" + }, + "textOverflow": { + "anyOf": [ + { + "type": "null" + }, + { + "const": "clip", + "type": "string" + }, + { + "const": "ellipsis", + "type": "string" + }, + { + "const": "clip-start", + "type": "string" + }, + { + "const": "clip-end", + "type": "string" + }, + { + "const": "ellipsis-start", + "type": "string" + }, + { + "const": "ellipsis-middle", + "type": "string" + }, + { + "const": "ellipsis-end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How truncate (or wrap) lines of text longer than the given **lineWidth**; one of:\n\n- null (default) - preserve overflowing characters (and wrap if needed)\n- *clip* or *clip-end* - remove characters from the end\n- *clip-start* - remove characters from the start\n- *ellipsis* or *ellipsis-end* - replace characters from the end with an ellipsis (…)\n- *ellipsis-start* - replace characters from the start with an ellipsis (…)\n- *ellipsis-middle* - replace characters from the middle with an ellipsis (…)\n\nIf no **title** was specified, if text requires truncation, a title containing the non-truncated text will be implicitly added." + }, + "tip": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/TipPointer" + }, + { + "properties": { + "anchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The tip anchor specifies how to orient the tip box relative to its anchor position; it refers to the part of the tip box that is attached to the anchor point. For example, the *top-left* anchor places the top-left corner of tip box near the anchor position, hence placing the tip box below and to the right of the anchor position." + }, + "fontFamily": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font-family][1]; a constant; defaults to the plot’s font family, which is typically [*system-ui*][2].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-family [2]: https://drafts.csswg.org/css-fonts-4/#valdef-font-family-system-ui" + }, + "fontSize": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font size][1] in pixels; either a constant or a channel; defaults to the plot’s font size, which is typically 10. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-size" + }, + "fontStyle": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font style][1]; a constant; defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-style" + }, + "fontVariant": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font variant][1]; a constant; if the **text** channel contains numbers or dates, defaults to *tabular-nums* to facilitate comparing numbers; otherwise defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant" + }, + "fontWeight": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font weight][1]; a constant; defaults to the plot’s font weight, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight" + }, + "format": { + "additionalProperties": false, + "description": "How channel values are formatted for display. If a format is a string, it is interpreted as a (UTC) time format for temporal channels, and otherwise a number format.", + "properties": { + "ariaLabel": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fill": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fillOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fontSize": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fx": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fy": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "geometry": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "height": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "href": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "length": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "opacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "path": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "r": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "rotate": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "src": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "stroke": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeWidth": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "symbol": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "text": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "title": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "weight": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "width": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "z": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + } + }, + "type": "object" + }, + "frameAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The frame anchor specifies defaults for **x** and **y** based on the plot’s frame; it may be one of the four sides (*top*, *right*, *bottom*, *left*), one of the four corners (*top-left*, *top-right*, *bottom-right*,\n*bottom-left*), or the *middle* of the frame. For example, for tips distributed horizontally at the top of the frame:\n\n```js Plot.tip(data, {x: \"date\", frameAnchor: \"top\"}) ```" + }, + "lineHeight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line height in ems; defaults to 1. The line height affects the (typically vertical) separation between adjacent baselines of text, as well as the separation between the text and its anchor point." + }, + "lineWidth": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line width in ems (e.g., 10 for about 20 characters); defaults to infinity, disabling wrapping and clipping.\n\nIf **textOverflow** is null, lines will be wrapped at the specified length. If a line is split at a soft hyphen (\\xad), a hyphen (-) will be displayed at the end of the line. If **textOverflow** is not null, lines will be clipped according to the given strategy." + }, + "monospace": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, changes the default **fontFamily** to *monospace*, and uses simplified monospaced text metrics calculations." + }, + "pathFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The image filter for the tip’s box; defaults to a drop shadow." + }, + "pointer": { + "$ref": "#/definitions/TipPointer" + }, + "pointerSize": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The size of the tip’s pointer in pixels; defaults to 12." + }, + "preferredAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If an explicit tip anchor is not specified, an anchor is chosen automatically such that the tip fits within the plot’s frame; if the preferred anchor fits, it is chosen." + }, + "textAnchor": { + "anyOf": [ + { + "const": "start", + "type": "string" + }, + { + "const": "middle", + "type": "string" + }, + { + "const": "end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [text anchor][1] controls how text is aligned (typically horizontally) relative to its anchor point; it is one of *start*, *end*, or *middle*. If the frame anchor is *left*, *top-left*, or *bottom-left*, the default text anchor is *start*; if the frame anchor is *right*, *top-right*, or\n*bottom-right*, the default is *end*; otherwise it is *middle*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/text-anchor" + }, + "textOverflow": { + "anyOf": [ + { + "type": "null" + }, + { + "const": "clip", + "type": "string" + }, + { + "const": "ellipsis", + "type": "string" + }, + { + "const": "clip-start", + "type": "string" + }, + { + "const": "clip-end", + "type": "string" + }, + { + "const": "ellipsis-start", + "type": "string" + }, + { + "const": "ellipsis-middle", + "type": "string" + }, + { + "const": "ellipsis-end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How truncate (or wrap) lines of text longer than the given **lineWidth**; one of:\n\n- null (default) - preserve overflowing characters (and wrap if needed)\n- *clip* or *clip-end* - remove characters from the end\n- *clip-start* - remove characters from the start\n- *ellipsis* or *ellipsis-end* - replace characters from the end with an ellipsis (…)\n- *ellipsis-start* - replace characters from the start with an ellipsis (…)\n- *ellipsis-middle* - replace characters from the middle with an ellipsis (…)\n\nIf no **title** was specified, if text requires truncation, a title containing the non-truncated text will be implicitly added." + }, + "textPadding": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The padding around the text in pixels; defaults to 8." + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + } + }, + "type": "object" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to generate a tooltip for this mark, and any tip options." + }, + "title": { + "$ref": "#/definitions/ChannelValue", + "description": "The title; a channel specifying accessible, short textual descriptions as strings (possibly with newlines). If the tip option is specified, the title will be displayed with an interactive tooltip instead of using the SVG [title element][1].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/title" + }, + "type": { + "description": "The basic mark type to use to render 1D density values. Defaults to an areaY mark; lineY, dot, and text marks are also supported.", + "enum": [ + "text", + "textY" + ], + "type": "string" + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel specifying the text’s anchor point, typically bound to the *x* scale." + }, + "z": { + "$ref": "#/definitions/ChannelValue", + "description": "An optional ordinal channel for grouping data into series." + } + }, + "required": [ + "data", + "mark", + "type" + ], + "type": "object" + } + ], + "description": "The densityY mark." + }, + "DiscreteScaleType": { + "description": "The supported scale types for discrete encoding channels. One of:\n\n- *ordinal* - from discrete inputs to discrete outputs\n- *identity* - do not transform values when encoding", + "enum": [ + "ordinal", + "identity" + ], + "type": "string" + }, + "Dot": { + "additionalProperties": false, + "description": "The dot mark.", + "properties": { + "ariaDescription": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-description][1]; a constant textual description.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-description" + }, + "ariaHidden": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-hidden][1] state; a constant indicating whether the element is exposed to an accessibility API.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-hidden" + }, + "ariaLabel": { + "$ref": "#/definitions/ChannelValue", + "description": "The [aria-label][1]; a channel specifying short textual labels representing the value in the accessibility tree.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-label" + }, + "clip": { + "anyOf": [ + { + "const": "frame", + "type": "string" + }, + { + "const": "sphere", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to clip the mark; one of:\n\n- *frame* or true - clip to the plot’s frame (inner area)\n- *sphere* - clip to the projected sphere (*e.g.*, front hemisphere)\n- null or false - do not clip\n\nThe *sphere* clip option requires a geographic projection." + }, + "data": { + "$ref": "#/definitions/PlotMarkData", + "description": "The data source for the mark." + }, + "dx": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The horizontal offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "dy": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The vertical offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "facet": { + "anyOf": [ + { + "const": "auto", + "type": "string" + }, + { + "const": "include", + "type": "string" + }, + { + "const": "exclude", + "type": "string" + }, + { + "const": "super", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to enable or disable faceting; one of:\n\n- *auto* (default) - automatically determine if this mark should be faceted\n- *include* (or true) - draw the subset of the mark’s data in the current facet\n- *exclude* - draw the subset of the mark’s data *not* in the current facet\n- *super* - draw this mark in a single frame that covers all facets\n- null (or false) - repeat this mark’s data across all facets (*i.e.*, no faceting)\n\nWhen a mark uses *super* faceting, it is not allowed to use position scales (*x*, *y*, *fx*, or *fy*); *super* faceting is intended for decorations, such as labels and legends.\n\nWhen top-level faceting is used, the default *auto* setting is equivalent to *include* when the mark data is strictly equal to the top-level facet data; otherwise it is equivalent to null. When the *include* or *exclude* facet mode is chosen, the mark data must be parallel to the top-level facet data: the data must have the same length and order. If the data are not parallel, then the wrong data may be shown in each facet. The default\n*auto* therefore requires strict equality (`===`) for safety, and using the facet data as mark data is recommended when using the *exclude* facet mode. (To construct parallel data safely, consider using [*array*.map][1] on the facet data.)\n\nWhen mark-level faceting is used, the default *auto* setting is equivalent to *include*: the mark will be faceted if either the **fx** or **fy** channel option (or both) is specified. The null or false option will disable faceting, while *exclude* draws the subset of the mark’s data *not* in the current facet.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map" + }, + "facetAnchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "right", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "const": "left", + "type": "string" + }, + { + "const": "top-left", + "type": "string" + }, + { + "const": "top-right", + "type": "string" + }, + { + "const": "bottom-left", + "type": "string" + }, + { + "const": "bottom-right", + "type": "string" + }, + { + "const": "top-empty", + "type": "string" + }, + { + "const": "right-empty", + "type": "string" + }, + { + "const": "bottom-empty", + "type": "string" + }, + { + "const": "left-empty", + "type": "string" + }, + { + "const": "empty", + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to place the mark with respect to facets; one of:\n\n- null (default for most marks) - display the mark in each non-empty facet\n- *top*, *right*, *bottom*, or *left* - display the mark only in facets on the given side\n- *top-empty*, *right-empty*, *bottom-empty*, or *left-empty* (default for axis marks) - display the mark only in facets that have empty space on the given side: either the margin, or an empty facet\n- *empty* - display the mark in empty facets only" + }, + "fill": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill" + }, + "fillOpacity": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill-opacity][1]; a constant number between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill-opacity" + }, + "filter": { + "$ref": "#/definitions/ChannelValue", + "description": "Applies a transform to filter the mark’s index according to the given channel values; only truthy values are retained.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "frameAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The frame anchor specifies defaults for **x** and **y** based on the plot’s frame; it may be one of the four sides (*top*, *right*, *bottom*, *left*), one of the four corners (*top-left*, *top-right*, *bottom-right*,\n*bottom-left*), or the *middle* of the frame. For example, for dots distributed horizontally at the top of the frame:\n\n```js Plot.dot(data, {x: \"date\", frameAnchor: \"top\"}) ```" + }, + "fx": { + "$ref": "#/definitions/ChannelValue", + "description": "The horizontal facet position channel, for mark-level faceting, bound to the *fx* scale." + }, + "fy": { + "$ref": "#/definitions/ChannelValue", + "description": "The vertical facet position channel, for mark-level faceting, bound to the\n*fy* scale." + }, + "href": { + "$ref": "#/definitions/ChannelValue", + "description": "The [href][1]; a channel specifying URLs for clickable links. May be used in conjunction with the **target** option to open links in another window.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/href" + }, + "imageFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A CSS [filter][1]; a constant string used to adjust the rendering of images, such as *blur(5px)*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/filter" + }, + "margin": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four mark margins: **marginTop**,\n**marginRight**, **marginBottom**, and **marginLeft**; typically defaults to 0, except for axis marks." + }, + "marginBottom": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s bottom margin; the minimum distance in pixels between the bottom edges of the inner and outer plot area." + }, + "marginLeft": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s left margin; the minimum distance in pixels between the left edges of the inner and outer plot area." + }, + "marginRight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s right margin; the minimum distance in pixels between the right edges of the mark’s inner and outer plot area." + }, + "marginTop": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s top margin; the minimum distance in pixels between the top edges of the inner and outer plot area." + }, + "mark": { + "const": "dot", + "description": "A dot mark that draws circles, or other symbols, as in a scatterplot.\n\nIf either **x** or **y** is not specified, the default is determined by the\n**frameAnchor** option. If none of **x**, **y**, and **frameAnchor** are specified, *data* is assumed to be an array of pairs [[*x₀*, *y₀*], [*x₁*,\n*y₁*], [*x₂*, *y₂*], …] such that **x** = [*x₀*, *x₁*, *x₂*, …] and **y** = [*y₀*, *y₁*, *y₂*, …].\n\nDots are sorted by descending radius **r** by default to mitigate overplotting; set the **sort** option to null to draw them in input order.", + "type": "string" + }, + "mixBlendMode": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [mix-blend-mode][1]; a constant string specifying how to blend content such as *multiply*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode" + }, + "opacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally. For faster rendering, prefer the **strokeOpacity** or **fillOpacity** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/opacity" + }, + "paintOrder": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [paint-order][1]; a constant string specifying the order in which the\n**fill**, **stroke**, and any markers are drawn; defaults to *normal*, which draws the fill, then stroke, then markers; defaults to *stroke* for the text mark to create a “halo” around text to improve legibility.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/paint-order" + }, + "pointerEvents": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [pointer-events][1] property; a constant string such as *none*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/pointer-events" + }, + "r": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The radius of dots; either a channel or constant. When a number, it is interpreted as a constant radius in pixels. Otherwise it is interpreted as a channel, typically bound to the *r* channel, which defaults to the *sqrt* type for proportional symbols. The radius defaults to 4.5 pixels when using the **symbol** channel, and otherwise 3 pixels. Dots with a nonpositive radius are not drawn." + }, + "reverse": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Applies a transform to reverse the order of the mark’s index, say for reverse input order." + }, + "rotate": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The rotation angle of dots in degrees clockwise; either a channel or a constant. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel. Defaults to 0°, pointing up." + }, + "select": { + "$ref": "#/definitions/SelectFilter", + "description": "Applies a filter transform after data is loaded to highlight selected values only. For example, `first` and `last` select the first or last values of series only (using the *z* channel to separate series). Meanwhile, `nearestX` and `nearestY` select the point nearest to the pointer along the *x* or *y* channel dimension. Unlike Mosaic selections, a mark level *select* is internal to the mark only, and does not populate a param or selection value to be shared across clients.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "shapeRendering": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [shape-rendering][1]; a constant string such as *crispEdges*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/shape-rendering" + }, + "sort": { + "anyOf": [ + { + "$ref": "#/definitions/SortOrder" + }, + { + "$ref": "#/definitions/ChannelDomainSort" + } + ], + "description": "Either applies a transform to sort the mark’s index by the specified channel values, or imputes ordinal scale domains from this mark’s channels.\n\nWhen imputing ordinal scale domains from channel values, the **sort** option is an object whose keys are ordinal scale names such as *x* or *fx*, and whose values are channel names such as *y*, *y1*, or *y2*. For example, to impute the *y* scale’s domain from the associated *x* channel values in ascending order:\n\n```js sort: {y: \"x\"} ```\n\nFor different sort options for different scales, replace the channel name with a *value* object and per-scale options:\n\n```js sort: {y: {value: \"-x\"}} ```\n\nWhen sorting the mark’s index, the **sort** option is instead one of:\n\n- a channel value definition for sorting given values in ascending order\n- a {value, order} object for sorting given values\n- a {channel, order} object for sorting the named channel’s values" + }, + "stroke": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke" + }, + "strokeDasharray": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dasharray][1]; a constant number indicating the length in pixels of alternating dashes and gaps, or a constant string of numbers separated by spaces or commas (_e.g._, *10 2* for dashes of 10 pixels separated by gaps of 2 pixels), or *none* (the default) for no dashing\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dasharray" + }, + "strokeDashoffset": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dashoffset][1]; a constant indicating the offset in pixels of the first dash along the stroke; defaults to zero.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dashoffset" + }, + "strokeLinecap": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linecap][1]; a constant specifying how to cap stroked paths, such as *butt*, *round*, or *square*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linecap" + }, + "strokeLinejoin": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linejoin][1]; a constant specifying how to join stroked paths, such as *bevel*, *miter*, *miter-clip*, or *round*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linejoin" + }, + "strokeMiterlimit": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-miterlimit][1]; a constant number specifying how to limit the length of *miter* joins on stroked paths.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-miterlimit" + }, + "strokeOpacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-opacity" + }, + "strokeWidth": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-width][1]; a constant number in pixels, or a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-width" + }, + "symbol": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/SymbolType" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The categorical symbol; either a channel or a constant. A constant symbol can be specified by a valid symbol name such as *star*, or a symbol object (implementing the draw method); otherwise it is interpreted as a channel. Defaults to *circle* for the **dot** mark, and *hexagon* for the\n**hexagon** mark.\n\nIf the **symbol** channel’s values are all symbols, symbol names, or nullish, the channel is unscaled (values are interpreted literally); otherwise, the channel is bound to the *symbol* scale." + }, + "target": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [target][1]; a constant string specifying the target window (_e.g._,\n*_blank*) for clickable links; used in conjunction with the **href** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/target" + }, + "tip": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/TipPointer" + }, + { + "properties": { + "anchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The tip anchor specifies how to orient the tip box relative to its anchor position; it refers to the part of the tip box that is attached to the anchor point. For example, the *top-left* anchor places the top-left corner of tip box near the anchor position, hence placing the tip box below and to the right of the anchor position." + }, + "fontFamily": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font-family][1]; a constant; defaults to the plot’s font family, which is typically [*system-ui*][2].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-family [2]: https://drafts.csswg.org/css-fonts-4/#valdef-font-family-system-ui" + }, + "fontSize": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font size][1] in pixels; either a constant or a channel; defaults to the plot’s font size, which is typically 10. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-size" + }, + "fontStyle": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font style][1]; a constant; defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-style" + }, + "fontVariant": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font variant][1]; a constant; if the **text** channel contains numbers or dates, defaults to *tabular-nums* to facilitate comparing numbers; otherwise defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant" + }, + "fontWeight": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font weight][1]; a constant; defaults to the plot’s font weight, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight" + }, + "format": { + "additionalProperties": false, + "description": "How channel values are formatted for display. If a format is a string, it is interpreted as a (UTC) time format for temporal channels, and otherwise a number format.", + "properties": { + "ariaLabel": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fill": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fillOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fontSize": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fx": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fy": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "geometry": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "height": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "href": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "length": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "opacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "path": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "r": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "rotate": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "src": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "stroke": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeWidth": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "symbol": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "text": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "title": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "weight": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "width": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "z": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + } + }, + "type": "object" + }, + "frameAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The frame anchor specifies defaults for **x** and **y** based on the plot’s frame; it may be one of the four sides (*top*, *right*, *bottom*, *left*), one of the four corners (*top-left*, *top-right*, *bottom-right*,\n*bottom-left*), or the *middle* of the frame. For example, for tips distributed horizontally at the top of the frame:\n\n```js Plot.tip(data, {x: \"date\", frameAnchor: \"top\"}) ```" + }, + "lineHeight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line height in ems; defaults to 1. The line height affects the (typically vertical) separation between adjacent baselines of text, as well as the separation between the text and its anchor point." + }, + "lineWidth": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line width in ems (e.g., 10 for about 20 characters); defaults to infinity, disabling wrapping and clipping.\n\nIf **textOverflow** is null, lines will be wrapped at the specified length. If a line is split at a soft hyphen (\\xad), a hyphen (-) will be displayed at the end of the line. If **textOverflow** is not null, lines will be clipped according to the given strategy." + }, + "monospace": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, changes the default **fontFamily** to *monospace*, and uses simplified monospaced text metrics calculations." + }, + "pathFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The image filter for the tip’s box; defaults to a drop shadow." + }, + "pointer": { + "$ref": "#/definitions/TipPointer" + }, + "pointerSize": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The size of the tip’s pointer in pixels; defaults to 12." + }, + "preferredAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If an explicit tip anchor is not specified, an anchor is chosen automatically such that the tip fits within the plot’s frame; if the preferred anchor fits, it is chosen." + }, + "textAnchor": { + "anyOf": [ + { + "const": "start", + "type": "string" + }, + { + "const": "middle", + "type": "string" + }, + { + "const": "end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [text anchor][1] controls how text is aligned (typically horizontally) relative to its anchor point; it is one of *start*, *end*, or *middle*. If the frame anchor is *left*, *top-left*, or *bottom-left*, the default text anchor is *start*; if the frame anchor is *right*, *top-right*, or\n*bottom-right*, the default is *end*; otherwise it is *middle*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/text-anchor" + }, + "textOverflow": { + "anyOf": [ + { + "type": "null" + }, + { + "const": "clip", + "type": "string" + }, + { + "const": "ellipsis", + "type": "string" + }, + { + "const": "clip-start", + "type": "string" + }, + { + "const": "clip-end", + "type": "string" + }, + { + "const": "ellipsis-start", + "type": "string" + }, + { + "const": "ellipsis-middle", + "type": "string" + }, + { + "const": "ellipsis-end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How truncate (or wrap) lines of text longer than the given **lineWidth**; one of:\n\n- null (default) - preserve overflowing characters (and wrap if needed)\n- *clip* or *clip-end* - remove characters from the end\n- *clip-start* - remove characters from the start\n- *ellipsis* or *ellipsis-end* - replace characters from the end with an ellipsis (…)\n- *ellipsis-start* - replace characters from the start with an ellipsis (…)\n- *ellipsis-middle* - replace characters from the middle with an ellipsis (…)\n\nIf no **title** was specified, if text requires truncation, a title containing the non-truncated text will be implicitly added." + }, + "textPadding": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The padding around the text in pixels; defaults to 8." + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + } + }, + "type": "object" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to generate a tooltip for this mark, and any tip options." + }, + "title": { + "$ref": "#/definitions/ChannelValue", + "description": "The title; a channel specifying accessible, short textual descriptions as strings (possibly with newlines). If the tip option is specified, the title will be displayed with an interactive tooltip instead of using the SVG [title element][1].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/title" + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel specifying the dot’s center, typically bound to the *x* scale." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel specifying the dot’s center, typically bound to the *y* scale." + }, + "z": { + "$ref": "#/definitions/ChannelValue", + "description": "An optional ordinal channel for grouping data into series." + } + }, + "required": [ + "data", + "mark" + ], + "type": "object" + }, + "DotX": { + "additionalProperties": false, + "description": "The dotX mark.", + "properties": { + "ariaDescription": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-description][1]; a constant textual description.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-description" + }, + "ariaHidden": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-hidden][1] state; a constant indicating whether the element is exposed to an accessibility API.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-hidden" + }, + "ariaLabel": { + "$ref": "#/definitions/ChannelValue", + "description": "The [aria-label][1]; a channel specifying short textual labels representing the value in the accessibility tree.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-label" + }, + "clip": { + "anyOf": [ + { + "const": "frame", + "type": "string" + }, + { + "const": "sphere", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to clip the mark; one of:\n\n- *frame* or true - clip to the plot’s frame (inner area)\n- *sphere* - clip to the projected sphere (*e.g.*, front hemisphere)\n- null or false - do not clip\n\nThe *sphere* clip option requires a geographic projection." + }, + "data": { + "$ref": "#/definitions/PlotMarkData", + "description": "The data source for the mark." + }, + "dx": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The horizontal offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "dy": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The vertical offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "facet": { + "anyOf": [ + { + "const": "auto", + "type": "string" + }, + { + "const": "include", + "type": "string" + }, + { + "const": "exclude", + "type": "string" + }, + { + "const": "super", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to enable or disable faceting; one of:\n\n- *auto* (default) - automatically determine if this mark should be faceted\n- *include* (or true) - draw the subset of the mark’s data in the current facet\n- *exclude* - draw the subset of the mark’s data *not* in the current facet\n- *super* - draw this mark in a single frame that covers all facets\n- null (or false) - repeat this mark’s data across all facets (*i.e.*, no faceting)\n\nWhen a mark uses *super* faceting, it is not allowed to use position scales (*x*, *y*, *fx*, or *fy*); *super* faceting is intended for decorations, such as labels and legends.\n\nWhen top-level faceting is used, the default *auto* setting is equivalent to *include* when the mark data is strictly equal to the top-level facet data; otherwise it is equivalent to null. When the *include* or *exclude* facet mode is chosen, the mark data must be parallel to the top-level facet data: the data must have the same length and order. If the data are not parallel, then the wrong data may be shown in each facet. The default\n*auto* therefore requires strict equality (`===`) for safety, and using the facet data as mark data is recommended when using the *exclude* facet mode. (To construct parallel data safely, consider using [*array*.map][1] on the facet data.)\n\nWhen mark-level faceting is used, the default *auto* setting is equivalent to *include*: the mark will be faceted if either the **fx** or **fy** channel option (or both) is specified. The null or false option will disable faceting, while *exclude* draws the subset of the mark’s data *not* in the current facet.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map" + }, + "facetAnchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "right", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "const": "left", + "type": "string" + }, + { + "const": "top-left", + "type": "string" + }, + { + "const": "top-right", + "type": "string" + }, + { + "const": "bottom-left", + "type": "string" + }, + { + "const": "bottom-right", + "type": "string" + }, + { + "const": "top-empty", + "type": "string" + }, + { + "const": "right-empty", + "type": "string" + }, + { + "const": "bottom-empty", + "type": "string" + }, + { + "const": "left-empty", + "type": "string" + }, + { + "const": "empty", + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to place the mark with respect to facets; one of:\n\n- null (default for most marks) - display the mark in each non-empty facet\n- *top*, *right*, *bottom*, or *left* - display the mark only in facets on the given side\n- *top-empty*, *right-empty*, *bottom-empty*, or *left-empty* (default for axis marks) - display the mark only in facets that have empty space on the given side: either the margin, or an empty facet\n- *empty* - display the mark in empty facets only" + }, + "fill": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill" + }, + "fillOpacity": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill-opacity][1]; a constant number between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill-opacity" + }, + "filter": { + "$ref": "#/definitions/ChannelValue", + "description": "Applies a transform to filter the mark’s index according to the given channel values; only truthy values are retained.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "frameAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The frame anchor specifies defaults for **x** and **y** based on the plot’s frame; it may be one of the four sides (*top*, *right*, *bottom*, *left*), one of the four corners (*top-left*, *top-right*, *bottom-right*,\n*bottom-left*), or the *middle* of the frame. For example, for dots distributed horizontally at the top of the frame:\n\n```js Plot.dot(data, {x: \"date\", frameAnchor: \"top\"}) ```" + }, + "fx": { + "$ref": "#/definitions/ChannelValue", + "description": "The horizontal facet position channel, for mark-level faceting, bound to the *fx* scale." + }, + "fy": { + "$ref": "#/definitions/ChannelValue", + "description": "The vertical facet position channel, for mark-level faceting, bound to the\n*fy* scale." + }, + "href": { + "$ref": "#/definitions/ChannelValue", + "description": "The [href][1]; a channel specifying URLs for clickable links. May be used in conjunction with the **target** option to open links in another window.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/href" + }, + "imageFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A CSS [filter][1]; a constant string used to adjust the rendering of images, such as *blur(5px)*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/filter" + }, + "interval": { + "anyOf": [ + { + "$ref": "#/definitions/Interval" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "An interval (such as *day* or a number), to transform **y** values to the middle of the interval." + }, + "margin": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four mark margins: **marginTop**,\n**marginRight**, **marginBottom**, and **marginLeft**; typically defaults to 0, except for axis marks." + }, + "marginBottom": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s bottom margin; the minimum distance in pixels between the bottom edges of the inner and outer plot area." + }, + "marginLeft": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s left margin; the minimum distance in pixels between the left edges of the inner and outer plot area." + }, + "marginRight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s right margin; the minimum distance in pixels between the right edges of the mark’s inner and outer plot area." + }, + "marginTop": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s top margin; the minimum distance in pixels between the top edges of the inner and outer plot area." + }, + "mark": { + "const": "dotX", + "description": "Like dot, except that **x** defaults to the identity function, assuming that\n*data* = [*x₀*, *x₁*, *x₂*, …].\n\nIf an **interval** is specified, such as *day*, **y** is transformed to the middle of the interval.", + "type": "string" + }, + "mixBlendMode": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [mix-blend-mode][1]; a constant string specifying how to blend content such as *multiply*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode" + }, + "opacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally. For faster rendering, prefer the **strokeOpacity** or **fillOpacity** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/opacity" + }, + "paintOrder": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [paint-order][1]; a constant string specifying the order in which the\n**fill**, **stroke**, and any markers are drawn; defaults to *normal*, which draws the fill, then stroke, then markers; defaults to *stroke* for the text mark to create a “halo” around text to improve legibility.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/paint-order" + }, + "pointerEvents": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [pointer-events][1] property; a constant string such as *none*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/pointer-events" + }, + "r": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The radius of dots; either a channel or constant. When a number, it is interpreted as a constant radius in pixels. Otherwise it is interpreted as a channel, typically bound to the *r* channel, which defaults to the *sqrt* type for proportional symbols. The radius defaults to 4.5 pixels when using the **symbol** channel, and otherwise 3 pixels. Dots with a nonpositive radius are not drawn." + }, + "reverse": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Applies a transform to reverse the order of the mark’s index, say for reverse input order." + }, + "rotate": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The rotation angle of dots in degrees clockwise; either a channel or a constant. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel. Defaults to 0°, pointing up." + }, + "select": { + "$ref": "#/definitions/SelectFilter", + "description": "Applies a filter transform after data is loaded to highlight selected values only. For example, `first` and `last` select the first or last values of series only (using the *z* channel to separate series). Meanwhile, `nearestX` and `nearestY` select the point nearest to the pointer along the *x* or *y* channel dimension. Unlike Mosaic selections, a mark level *select* is internal to the mark only, and does not populate a param or selection value to be shared across clients.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "shapeRendering": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [shape-rendering][1]; a constant string such as *crispEdges*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/shape-rendering" + }, + "sort": { + "anyOf": [ + { + "$ref": "#/definitions/SortOrder" + }, + { + "$ref": "#/definitions/ChannelDomainSort" + } + ], + "description": "Either applies a transform to sort the mark’s index by the specified channel values, or imputes ordinal scale domains from this mark’s channels.\n\nWhen imputing ordinal scale domains from channel values, the **sort** option is an object whose keys are ordinal scale names such as *x* or *fx*, and whose values are channel names such as *y*, *y1*, or *y2*. For example, to impute the *y* scale’s domain from the associated *x* channel values in ascending order:\n\n```js sort: {y: \"x\"} ```\n\nFor different sort options for different scales, replace the channel name with a *value* object and per-scale options:\n\n```js sort: {y: {value: \"-x\"}} ```\n\nWhen sorting the mark’s index, the **sort** option is instead one of:\n\n- a channel value definition for sorting given values in ascending order\n- a {value, order} object for sorting given values\n- a {channel, order} object for sorting the named channel’s values" + }, + "stroke": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke" + }, + "strokeDasharray": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dasharray][1]; a constant number indicating the length in pixels of alternating dashes and gaps, or a constant string of numbers separated by spaces or commas (_e.g._, *10 2* for dashes of 10 pixels separated by gaps of 2 pixels), or *none* (the default) for no dashing\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dasharray" + }, + "strokeDashoffset": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dashoffset][1]; a constant indicating the offset in pixels of the first dash along the stroke; defaults to zero.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dashoffset" + }, + "strokeLinecap": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linecap][1]; a constant specifying how to cap stroked paths, such as *butt*, *round*, or *square*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linecap" + }, + "strokeLinejoin": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linejoin][1]; a constant specifying how to join stroked paths, such as *bevel*, *miter*, *miter-clip*, or *round*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linejoin" + }, + "strokeMiterlimit": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-miterlimit][1]; a constant number specifying how to limit the length of *miter* joins on stroked paths.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-miterlimit" + }, + "strokeOpacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-opacity" + }, + "strokeWidth": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-width][1]; a constant number in pixels, or a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-width" + }, + "symbol": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/SymbolType" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The categorical symbol; either a channel or a constant. A constant symbol can be specified by a valid symbol name such as *star*, or a symbol object (implementing the draw method); otherwise it is interpreted as a channel. Defaults to *circle* for the **dot** mark, and *hexagon* for the\n**hexagon** mark.\n\nIf the **symbol** channel’s values are all symbols, symbol names, or nullish, the channel is unscaled (values are interpreted literally); otherwise, the channel is bound to the *symbol* scale." + }, + "target": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [target][1]; a constant string specifying the target window (_e.g._,\n*_blank*) for clickable links; used in conjunction with the **href** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/target" + }, + "tip": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/TipPointer" + }, + { + "properties": { + "anchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The tip anchor specifies how to orient the tip box relative to its anchor position; it refers to the part of the tip box that is attached to the anchor point. For example, the *top-left* anchor places the top-left corner of tip box near the anchor position, hence placing the tip box below and to the right of the anchor position." + }, + "fontFamily": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font-family][1]; a constant; defaults to the plot’s font family, which is typically [*system-ui*][2].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-family [2]: https://drafts.csswg.org/css-fonts-4/#valdef-font-family-system-ui" + }, + "fontSize": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font size][1] in pixels; either a constant or a channel; defaults to the plot’s font size, which is typically 10. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-size" + }, + "fontStyle": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font style][1]; a constant; defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-style" + }, + "fontVariant": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font variant][1]; a constant; if the **text** channel contains numbers or dates, defaults to *tabular-nums* to facilitate comparing numbers; otherwise defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant" + }, + "fontWeight": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font weight][1]; a constant; defaults to the plot’s font weight, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight" + }, + "format": { + "additionalProperties": false, + "description": "How channel values are formatted for display. If a format is a string, it is interpreted as a (UTC) time format for temporal channels, and otherwise a number format.", + "properties": { + "ariaLabel": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fill": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fillOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fontSize": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fx": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fy": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "geometry": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "height": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "href": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "length": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "opacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "path": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "r": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "rotate": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "src": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "stroke": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeWidth": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "symbol": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "text": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "title": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "weight": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "width": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "z": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + } + }, + "type": "object" + }, + "frameAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The frame anchor specifies defaults for **x** and **y** based on the plot’s frame; it may be one of the four sides (*top*, *right*, *bottom*, *left*), one of the four corners (*top-left*, *top-right*, *bottom-right*,\n*bottom-left*), or the *middle* of the frame. For example, for tips distributed horizontally at the top of the frame:\n\n```js Plot.tip(data, {x: \"date\", frameAnchor: \"top\"}) ```" + }, + "lineHeight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line height in ems; defaults to 1. The line height affects the (typically vertical) separation between adjacent baselines of text, as well as the separation between the text and its anchor point." + }, + "lineWidth": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line width in ems (e.g., 10 for about 20 characters); defaults to infinity, disabling wrapping and clipping.\n\nIf **textOverflow** is null, lines will be wrapped at the specified length. If a line is split at a soft hyphen (\\xad), a hyphen (-) will be displayed at the end of the line. If **textOverflow** is not null, lines will be clipped according to the given strategy." + }, + "monospace": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, changes the default **fontFamily** to *monospace*, and uses simplified monospaced text metrics calculations." + }, + "pathFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The image filter for the tip’s box; defaults to a drop shadow." + }, + "pointer": { + "$ref": "#/definitions/TipPointer" + }, + "pointerSize": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The size of the tip’s pointer in pixels; defaults to 12." + }, + "preferredAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If an explicit tip anchor is not specified, an anchor is chosen automatically such that the tip fits within the plot’s frame; if the preferred anchor fits, it is chosen." + }, + "textAnchor": { + "anyOf": [ + { + "const": "start", + "type": "string" + }, + { + "const": "middle", + "type": "string" + }, + { + "const": "end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [text anchor][1] controls how text is aligned (typically horizontally) relative to its anchor point; it is one of *start*, *end*, or *middle*. If the frame anchor is *left*, *top-left*, or *bottom-left*, the default text anchor is *start*; if the frame anchor is *right*, *top-right*, or\n*bottom-right*, the default is *end*; otherwise it is *middle*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/text-anchor" + }, + "textOverflow": { + "anyOf": [ + { + "type": "null" + }, + { + "const": "clip", + "type": "string" + }, + { + "const": "ellipsis", + "type": "string" + }, + { + "const": "clip-start", + "type": "string" + }, + { + "const": "clip-end", + "type": "string" + }, + { + "const": "ellipsis-start", + "type": "string" + }, + { + "const": "ellipsis-middle", + "type": "string" + }, + { + "const": "ellipsis-end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How truncate (or wrap) lines of text longer than the given **lineWidth**; one of:\n\n- null (default) - preserve overflowing characters (and wrap if needed)\n- *clip* or *clip-end* - remove characters from the end\n- *clip-start* - remove characters from the start\n- *ellipsis* or *ellipsis-end* - replace characters from the end with an ellipsis (…)\n- *ellipsis-start* - replace characters from the start with an ellipsis (…)\n- *ellipsis-middle* - replace characters from the middle with an ellipsis (…)\n\nIf no **title** was specified, if text requires truncation, a title containing the non-truncated text will be implicitly added." + }, + "textPadding": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The padding around the text in pixels; defaults to 8." + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + } + }, + "type": "object" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to generate a tooltip for this mark, and any tip options." + }, + "title": { + "$ref": "#/definitions/ChannelValue", + "description": "The title; a channel specifying accessible, short textual descriptions as strings (possibly with newlines). If the tip option is specified, the title will be displayed with an interactive tooltip instead of using the SVG [title element][1].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/title" + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel specifying the dot’s center, typically bound to the *x* scale." + }, + "y": { + "$ref": "#/definitions/ChannelValueIntervalSpec", + "description": "The vertical position of the dot’s center, typically bound to the *y* scale." + }, + "z": { + "$ref": "#/definitions/ChannelValue", + "description": "An optional ordinal channel for grouping data into series." + } + }, + "required": [ + "data", + "mark" + ], + "type": "object" + }, + "DotY": { + "additionalProperties": false, + "description": "The dotY mark.", + "properties": { + "ariaDescription": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-description][1]; a constant textual description.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-description" + }, + "ariaHidden": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-hidden][1] state; a constant indicating whether the element is exposed to an accessibility API.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-hidden" + }, + "ariaLabel": { + "$ref": "#/definitions/ChannelValue", + "description": "The [aria-label][1]; a channel specifying short textual labels representing the value in the accessibility tree.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-label" + }, + "clip": { + "anyOf": [ + { + "const": "frame", + "type": "string" + }, + { + "const": "sphere", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to clip the mark; one of:\n\n- *frame* or true - clip to the plot’s frame (inner area)\n- *sphere* - clip to the projected sphere (*e.g.*, front hemisphere)\n- null or false - do not clip\n\nThe *sphere* clip option requires a geographic projection." + }, + "data": { + "$ref": "#/definitions/PlotMarkData", + "description": "The data source for the mark." + }, + "dx": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The horizontal offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "dy": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The vertical offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "facet": { + "anyOf": [ + { + "const": "auto", + "type": "string" + }, + { + "const": "include", + "type": "string" + }, + { + "const": "exclude", + "type": "string" + }, + { + "const": "super", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to enable or disable faceting; one of:\n\n- *auto* (default) - automatically determine if this mark should be faceted\n- *include* (or true) - draw the subset of the mark’s data in the current facet\n- *exclude* - draw the subset of the mark’s data *not* in the current facet\n- *super* - draw this mark in a single frame that covers all facets\n- null (or false) - repeat this mark’s data across all facets (*i.e.*, no faceting)\n\nWhen a mark uses *super* faceting, it is not allowed to use position scales (*x*, *y*, *fx*, or *fy*); *super* faceting is intended for decorations, such as labels and legends.\n\nWhen top-level faceting is used, the default *auto* setting is equivalent to *include* when the mark data is strictly equal to the top-level facet data; otherwise it is equivalent to null. When the *include* or *exclude* facet mode is chosen, the mark data must be parallel to the top-level facet data: the data must have the same length and order. If the data are not parallel, then the wrong data may be shown in each facet. The default\n*auto* therefore requires strict equality (`===`) for safety, and using the facet data as mark data is recommended when using the *exclude* facet mode. (To construct parallel data safely, consider using [*array*.map][1] on the facet data.)\n\nWhen mark-level faceting is used, the default *auto* setting is equivalent to *include*: the mark will be faceted if either the **fx** or **fy** channel option (or both) is specified. The null or false option will disable faceting, while *exclude* draws the subset of the mark’s data *not* in the current facet.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map" + }, + "facetAnchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "right", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "const": "left", + "type": "string" + }, + { + "const": "top-left", + "type": "string" + }, + { + "const": "top-right", + "type": "string" + }, + { + "const": "bottom-left", + "type": "string" + }, + { + "const": "bottom-right", + "type": "string" + }, + { + "const": "top-empty", + "type": "string" + }, + { + "const": "right-empty", + "type": "string" + }, + { + "const": "bottom-empty", + "type": "string" + }, + { + "const": "left-empty", + "type": "string" + }, + { + "const": "empty", + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to place the mark with respect to facets; one of:\n\n- null (default for most marks) - display the mark in each non-empty facet\n- *top*, *right*, *bottom*, or *left* - display the mark only in facets on the given side\n- *top-empty*, *right-empty*, *bottom-empty*, or *left-empty* (default for axis marks) - display the mark only in facets that have empty space on the given side: either the margin, or an empty facet\n- *empty* - display the mark in empty facets only" + }, + "fill": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill" + }, + "fillOpacity": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill-opacity][1]; a constant number between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill-opacity" + }, + "filter": { + "$ref": "#/definitions/ChannelValue", + "description": "Applies a transform to filter the mark’s index according to the given channel values; only truthy values are retained.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "frameAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The frame anchor specifies defaults for **x** and **y** based on the plot’s frame; it may be one of the four sides (*top*, *right*, *bottom*, *left*), one of the four corners (*top-left*, *top-right*, *bottom-right*,\n*bottom-left*), or the *middle* of the frame. For example, for dots distributed horizontally at the top of the frame:\n\n```js Plot.dot(data, {x: \"date\", frameAnchor: \"top\"}) ```" + }, + "fx": { + "$ref": "#/definitions/ChannelValue", + "description": "The horizontal facet position channel, for mark-level faceting, bound to the *fx* scale." + }, + "fy": { + "$ref": "#/definitions/ChannelValue", + "description": "The vertical facet position channel, for mark-level faceting, bound to the\n*fy* scale." + }, + "href": { + "$ref": "#/definitions/ChannelValue", + "description": "The [href][1]; a channel specifying URLs for clickable links. May be used in conjunction with the **target** option to open links in another window.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/href" + }, + "imageFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A CSS [filter][1]; a constant string used to adjust the rendering of images, such as *blur(5px)*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/filter" + }, + "interval": { + "anyOf": [ + { + "$ref": "#/definitions/Interval" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "An interval (such as *day* or a number), to transform **x** values to the middle of the interval." + }, + "margin": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four mark margins: **marginTop**,\n**marginRight**, **marginBottom**, and **marginLeft**; typically defaults to 0, except for axis marks." + }, + "marginBottom": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s bottom margin; the minimum distance in pixels between the bottom edges of the inner and outer plot area." + }, + "marginLeft": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s left margin; the minimum distance in pixels between the left edges of the inner and outer plot area." + }, + "marginRight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s right margin; the minimum distance in pixels between the right edges of the mark’s inner and outer plot area." + }, + "marginTop": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s top margin; the minimum distance in pixels between the top edges of the inner and outer plot area." + }, + "mark": { + "const": "dotY", + "description": "Like dot, except that **y** defaults to the identity function, assuming that\n*data* = [*y₀*, *y₁*, *y₂*, …].\n\nIf an **interval** is specified, such as *day*, **x** is transformed to the middle of the interval.", + "type": "string" + }, + "mixBlendMode": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [mix-blend-mode][1]; a constant string specifying how to blend content such as *multiply*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode" + }, + "opacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally. For faster rendering, prefer the **strokeOpacity** or **fillOpacity** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/opacity" + }, + "paintOrder": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [paint-order][1]; a constant string specifying the order in which the\n**fill**, **stroke**, and any markers are drawn; defaults to *normal*, which draws the fill, then stroke, then markers; defaults to *stroke* for the text mark to create a “halo” around text to improve legibility.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/paint-order" + }, + "pointerEvents": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [pointer-events][1] property; a constant string such as *none*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/pointer-events" + }, + "r": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The radius of dots; either a channel or constant. When a number, it is interpreted as a constant radius in pixels. Otherwise it is interpreted as a channel, typically bound to the *r* channel, which defaults to the *sqrt* type for proportional symbols. The radius defaults to 4.5 pixels when using the **symbol** channel, and otherwise 3 pixels. Dots with a nonpositive radius are not drawn." + }, + "reverse": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Applies a transform to reverse the order of the mark’s index, say for reverse input order." + }, + "rotate": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The rotation angle of dots in degrees clockwise; either a channel or a constant. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel. Defaults to 0°, pointing up." + }, + "select": { + "$ref": "#/definitions/SelectFilter", + "description": "Applies a filter transform after data is loaded to highlight selected values only. For example, `first` and `last` select the first or last values of series only (using the *z* channel to separate series). Meanwhile, `nearestX` and `nearestY` select the point nearest to the pointer along the *x* or *y* channel dimension. Unlike Mosaic selections, a mark level *select* is internal to the mark only, and does not populate a param or selection value to be shared across clients.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "shapeRendering": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [shape-rendering][1]; a constant string such as *crispEdges*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/shape-rendering" + }, + "sort": { + "anyOf": [ + { + "$ref": "#/definitions/SortOrder" + }, + { + "$ref": "#/definitions/ChannelDomainSort" + } + ], + "description": "Either applies a transform to sort the mark’s index by the specified channel values, or imputes ordinal scale domains from this mark’s channels.\n\nWhen imputing ordinal scale domains from channel values, the **sort** option is an object whose keys are ordinal scale names such as *x* or *fx*, and whose values are channel names such as *y*, *y1*, or *y2*. For example, to impute the *y* scale’s domain from the associated *x* channel values in ascending order:\n\n```js sort: {y: \"x\"} ```\n\nFor different sort options for different scales, replace the channel name with a *value* object and per-scale options:\n\n```js sort: {y: {value: \"-x\"}} ```\n\nWhen sorting the mark’s index, the **sort** option is instead one of:\n\n- a channel value definition for sorting given values in ascending order\n- a {value, order} object for sorting given values\n- a {channel, order} object for sorting the named channel’s values" + }, + "stroke": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke" + }, + "strokeDasharray": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dasharray][1]; a constant number indicating the length in pixels of alternating dashes and gaps, or a constant string of numbers separated by spaces or commas (_e.g._, *10 2* for dashes of 10 pixels separated by gaps of 2 pixels), or *none* (the default) for no dashing\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dasharray" + }, + "strokeDashoffset": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dashoffset][1]; a constant indicating the offset in pixels of the first dash along the stroke; defaults to zero.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dashoffset" + }, + "strokeLinecap": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linecap][1]; a constant specifying how to cap stroked paths, such as *butt*, *round*, or *square*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linecap" + }, + "strokeLinejoin": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linejoin][1]; a constant specifying how to join stroked paths, such as *bevel*, *miter*, *miter-clip*, or *round*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linejoin" + }, + "strokeMiterlimit": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-miterlimit][1]; a constant number specifying how to limit the length of *miter* joins on stroked paths.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-miterlimit" + }, + "strokeOpacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-opacity" + }, + "strokeWidth": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-width][1]; a constant number in pixels, or a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-width" + }, + "symbol": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/SymbolType" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The categorical symbol; either a channel or a constant. A constant symbol can be specified by a valid symbol name such as *star*, or a symbol object (implementing the draw method); otherwise it is interpreted as a channel. Defaults to *circle* for the **dot** mark, and *hexagon* for the\n**hexagon** mark.\n\nIf the **symbol** channel’s values are all symbols, symbol names, or nullish, the channel is unscaled (values are interpreted literally); otherwise, the channel is bound to the *symbol* scale." + }, + "target": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [target][1]; a constant string specifying the target window (_e.g._,\n*_blank*) for clickable links; used in conjunction with the **href** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/target" + }, + "tip": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/TipPointer" + }, + { + "properties": { + "anchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The tip anchor specifies how to orient the tip box relative to its anchor position; it refers to the part of the tip box that is attached to the anchor point. For example, the *top-left* anchor places the top-left corner of tip box near the anchor position, hence placing the tip box below and to the right of the anchor position." + }, + "fontFamily": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font-family][1]; a constant; defaults to the plot’s font family, which is typically [*system-ui*][2].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-family [2]: https://drafts.csswg.org/css-fonts-4/#valdef-font-family-system-ui" + }, + "fontSize": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font size][1] in pixels; either a constant or a channel; defaults to the plot’s font size, which is typically 10. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-size" + }, + "fontStyle": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font style][1]; a constant; defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-style" + }, + "fontVariant": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font variant][1]; a constant; if the **text** channel contains numbers or dates, defaults to *tabular-nums* to facilitate comparing numbers; otherwise defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant" + }, + "fontWeight": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font weight][1]; a constant; defaults to the plot’s font weight, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight" + }, + "format": { + "additionalProperties": false, + "description": "How channel values are formatted for display. If a format is a string, it is interpreted as a (UTC) time format for temporal channels, and otherwise a number format.", + "properties": { + "ariaLabel": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fill": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fillOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fontSize": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fx": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fy": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "geometry": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "height": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "href": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "length": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "opacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "path": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "r": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "rotate": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "src": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "stroke": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeWidth": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "symbol": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "text": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "title": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "weight": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "width": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "z": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + } + }, + "type": "object" + }, + "frameAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The frame anchor specifies defaults for **x** and **y** based on the plot’s frame; it may be one of the four sides (*top*, *right*, *bottom*, *left*), one of the four corners (*top-left*, *top-right*, *bottom-right*,\n*bottom-left*), or the *middle* of the frame. For example, for tips distributed horizontally at the top of the frame:\n\n```js Plot.tip(data, {x: \"date\", frameAnchor: \"top\"}) ```" + }, + "lineHeight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line height in ems; defaults to 1. The line height affects the (typically vertical) separation between adjacent baselines of text, as well as the separation between the text and its anchor point." + }, + "lineWidth": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line width in ems (e.g., 10 for about 20 characters); defaults to infinity, disabling wrapping and clipping.\n\nIf **textOverflow** is null, lines will be wrapped at the specified length. If a line is split at a soft hyphen (\\xad), a hyphen (-) will be displayed at the end of the line. If **textOverflow** is not null, lines will be clipped according to the given strategy." + }, + "monospace": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, changes the default **fontFamily** to *monospace*, and uses simplified monospaced text metrics calculations." + }, + "pathFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The image filter for the tip’s box; defaults to a drop shadow." + }, + "pointer": { + "$ref": "#/definitions/TipPointer" + }, + "pointerSize": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The size of the tip’s pointer in pixels; defaults to 12." + }, + "preferredAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If an explicit tip anchor is not specified, an anchor is chosen automatically such that the tip fits within the plot’s frame; if the preferred anchor fits, it is chosen." + }, + "textAnchor": { + "anyOf": [ + { + "const": "start", + "type": "string" + }, + { + "const": "middle", + "type": "string" + }, + { + "const": "end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [text anchor][1] controls how text is aligned (typically horizontally) relative to its anchor point; it is one of *start*, *end*, or *middle*. If the frame anchor is *left*, *top-left*, or *bottom-left*, the default text anchor is *start*; if the frame anchor is *right*, *top-right*, or\n*bottom-right*, the default is *end*; otherwise it is *middle*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/text-anchor" + }, + "textOverflow": { + "anyOf": [ + { + "type": "null" + }, + { + "const": "clip", + "type": "string" + }, + { + "const": "ellipsis", + "type": "string" + }, + { + "const": "clip-start", + "type": "string" + }, + { + "const": "clip-end", + "type": "string" + }, + { + "const": "ellipsis-start", + "type": "string" + }, + { + "const": "ellipsis-middle", + "type": "string" + }, + { + "const": "ellipsis-end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How truncate (or wrap) lines of text longer than the given **lineWidth**; one of:\n\n- null (default) - preserve overflowing characters (and wrap if needed)\n- *clip* or *clip-end* - remove characters from the end\n- *clip-start* - remove characters from the start\n- *ellipsis* or *ellipsis-end* - replace characters from the end with an ellipsis (…)\n- *ellipsis-start* - replace characters from the start with an ellipsis (…)\n- *ellipsis-middle* - replace characters from the middle with an ellipsis (…)\n\nIf no **title** was specified, if text requires truncation, a title containing the non-truncated text will be implicitly added." + }, + "textPadding": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The padding around the text in pixels; defaults to 8." + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + } + }, + "type": "object" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to generate a tooltip for this mark, and any tip options." + }, + "title": { + "$ref": "#/definitions/ChannelValue", + "description": "The title; a channel specifying accessible, short textual descriptions as strings (possibly with newlines). If the tip option is specified, the title will be displayed with an interactive tooltip instead of using the SVG [title element][1].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/title" + }, + "x": { + "$ref": "#/definitions/ChannelValueIntervalSpec", + "description": "The horizontal position of the dot’s center, typically bound to the *x* scale." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel specifying the dot’s center, typically bound to the *y* scale." + }, + "z": { + "$ref": "#/definitions/ChannelValue", + "description": "An optional ordinal channel for grouping data into series." + } + }, + "required": [ + "data", + "mark" + ], + "type": "object" + }, + "ErrorBarX": { + "additionalProperties": false, + "description": "The errorbarX mark.", + "properties": { + "ariaDescription": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-description][1]; a constant textual description.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-description" + }, + "ariaHidden": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-hidden][1] state; a constant indicating whether the element is exposed to an accessibility API.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-hidden" + }, + "ariaLabel": { + "$ref": "#/definitions/ChannelValue", + "description": "The [aria-label][1]; a channel specifying short textual labels representing the value in the accessibility tree.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-label" + }, + "ci": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The confidence interval in (0, 1); defaults to 0.95." + }, + "clip": { + "anyOf": [ + { + "const": "frame", + "type": "string" + }, + { + "const": "sphere", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to clip the mark; one of:\n\n- *frame* or true - clip to the plot’s frame (inner area)\n- *sphere* - clip to the projected sphere (*e.g.*, front hemisphere)\n- null or false - do not clip\n\nThe *sphere* clip option requires a geographic projection." + }, + "data": { + "$ref": "#/definitions/PlotMarkData", + "description": "The data source for the mark." + }, + "dx": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The horizontal offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "dy": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The vertical offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "facet": { + "anyOf": [ + { + "const": "auto", + "type": "string" + }, + { + "const": "include", + "type": "string" + }, + { + "const": "exclude", + "type": "string" + }, + { + "const": "super", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to enable or disable faceting; one of:\n\n- *auto* (default) - automatically determine if this mark should be faceted\n- *include* (or true) - draw the subset of the mark’s data in the current facet\n- *exclude* - draw the subset of the mark’s data *not* in the current facet\n- *super* - draw this mark in a single frame that covers all facets\n- null (or false) - repeat this mark’s data across all facets (*i.e.*, no faceting)\n\nWhen a mark uses *super* faceting, it is not allowed to use position scales (*x*, *y*, *fx*, or *fy*); *super* faceting is intended for decorations, such as labels and legends.\n\nWhen top-level faceting is used, the default *auto* setting is equivalent to *include* when the mark data is strictly equal to the top-level facet data; otherwise it is equivalent to null. When the *include* or *exclude* facet mode is chosen, the mark data must be parallel to the top-level facet data: the data must have the same length and order. If the data are not parallel, then the wrong data may be shown in each facet. The default\n*auto* therefore requires strict equality (`===`) for safety, and using the facet data as mark data is recommended when using the *exclude* facet mode. (To construct parallel data safely, consider using [*array*.map][1] on the facet data.)\n\nWhen mark-level faceting is used, the default *auto* setting is equivalent to *include*: the mark will be faceted if either the **fx** or **fy** channel option (or both) is specified. The null or false option will disable faceting, while *exclude* draws the subset of the mark’s data *not* in the current facet.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map" + }, + "facetAnchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "right", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "const": "left", + "type": "string" + }, + { + "const": "top-left", + "type": "string" + }, + { + "const": "top-right", + "type": "string" + }, + { + "const": "bottom-left", + "type": "string" + }, + { + "const": "bottom-right", + "type": "string" + }, + { + "const": "top-empty", + "type": "string" + }, + { + "const": "right-empty", + "type": "string" + }, + { + "const": "bottom-empty", + "type": "string" + }, + { + "const": "left-empty", + "type": "string" + }, + { + "const": "empty", + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to place the mark with respect to facets; one of:\n\n- null (default for most marks) - display the mark in each non-empty facet\n- *top*, *right*, *bottom*, or *left* - display the mark only in facets on the given side\n- *top-empty*, *right-empty*, *bottom-empty*, or *left-empty* (default for axis marks) - display the mark only in facets that have empty space on the given side: either the margin, or an empty facet\n- *empty* - display the mark in empty facets only" + }, + "fill": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill" + }, + "fillOpacity": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill-opacity][1]; a constant number between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill-opacity" + }, + "filter": { + "$ref": "#/definitions/ChannelValue", + "description": "Applies a transform to filter the mark’s index according to the given channel values; only truthy values are retained.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "fx": { + "$ref": "#/definitions/ChannelValue", + "description": "The horizontal facet position channel, for mark-level faceting, bound to the *fx* scale." + }, + "fy": { + "$ref": "#/definitions/ChannelValue", + "description": "The vertical facet position channel, for mark-level faceting, bound to the\n*fy* scale." + }, + "href": { + "$ref": "#/definitions/ChannelValue", + "description": "The [href][1]; a channel specifying URLs for clickable links. May be used in conjunction with the **target** option to open links in another window.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/href" + }, + "imageFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A CSS [filter][1]; a constant string used to adjust the rendering of images, such as *blur(5px)*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/filter" + }, + "margin": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four mark margins: **marginTop**,\n**marginRight**, **marginBottom**, and **marginLeft**; typically defaults to 0, except for axis marks." + }, + "marginBottom": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s bottom margin; the minimum distance in pixels between the bottom edges of the inner and outer plot area." + }, + "marginLeft": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s left margin; the minimum distance in pixels between the left edges of the inner and outer plot area." + }, + "marginRight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s right margin; the minimum distance in pixels between the right edges of the mark’s inner and outer plot area." + }, + "marginTop": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s top margin; the minimum distance in pixels between the top edges of the inner and outer plot area." + }, + "mark": { + "const": "errorbarX", + "description": "A mark that draws error bars for a calculated parametric confidence interval for a dependent variable (*x*), potentially grouped by an independent variable (*y*).\n\nThis mark aggregates raw values to produce a [parametric confidence interval][1] of the mean, assuming a normal distribution. To instead visualize pre-computeted interval values or custom aggregations, use a **ruleY** mark with specified **x1** and **x2** channels.\n\nMultiple error bars can be produced by specifying a **z** or **stroke** channel. Set the **marker** option to `'tick'` to add small perpendicular lines at the start and end of the error interval.\n\n[1]: https://en.wikipedia.org/wiki/Normal_distribution#Confidence_intervals", + "type": "string" + }, + "marker": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for markerStart, markerMid, and markerEnd; one of:\n\n- a marker name such as *arrow* or *circle*\n- *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*" + }, + "markerEnd": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The marker for the ending point of a line segment; one of:\n\n- a marker name such as *arrow* or *circle*\n* *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*" + }, + "markerMid": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The marker for any middle (interior) points of a line segment. If the line segment only has a start and end point, this option has no effect. One of:\n\n- a marker name such as *arrow* or *circle*\n* *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*\n* a function - a custom marker function; see below" + }, + "markerStart": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The marker for the starting point of a line segment; one of:\n\n- a marker name such as *arrow* or *circle*\n* *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*" + }, + "mixBlendMode": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [mix-blend-mode][1]; a constant string specifying how to blend content such as *multiply*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode" + }, + "opacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally. For faster rendering, prefer the **strokeOpacity** or **fillOpacity** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/opacity" + }, + "paintOrder": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [paint-order][1]; a constant string specifying the order in which the\n**fill**, **stroke**, and any markers are drawn; defaults to *normal*, which draws the fill, then stroke, then markers; defaults to *stroke* for the text mark to create a “halo” around text to improve legibility.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/paint-order" + }, + "pointerEvents": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [pointer-events][1] property; a constant string such as *none*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/pointer-events" + }, + "reverse": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Applies a transform to reverse the order of the mark’s index, say for reverse input order." + }, + "select": { + "$ref": "#/definitions/SelectFilter", + "description": "Applies a filter transform after data is loaded to highlight selected values only. For example, `first` and `last` select the first or last values of series only (using the *z* channel to separate series). Meanwhile, `nearestX` and `nearestY` select the point nearest to the pointer along the *x* or *y* channel dimension. Unlike Mosaic selections, a mark level *select* is internal to the mark only, and does not populate a param or selection value to be shared across clients.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "shapeRendering": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [shape-rendering][1]; a constant string such as *crispEdges*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/shape-rendering" + }, + "sort": { + "anyOf": [ + { + "$ref": "#/definitions/SortOrder" + }, + { + "$ref": "#/definitions/ChannelDomainSort" + } + ], + "description": "Either applies a transform to sort the mark’s index by the specified channel values, or imputes ordinal scale domains from this mark’s channels.\n\nWhen imputing ordinal scale domains from channel values, the **sort** option is an object whose keys are ordinal scale names such as *x* or *fx*, and whose values are channel names such as *y*, *y1*, or *y2*. For example, to impute the *y* scale’s domain from the associated *x* channel values in ascending order:\n\n```js sort: {y: \"x\"} ```\n\nFor different sort options for different scales, replace the channel name with a *value* object and per-scale options:\n\n```js sort: {y: {value: \"-x\"}} ```\n\nWhen sorting the mark’s index, the **sort** option is instead one of:\n\n- a channel value definition for sorting given values in ascending order\n- a {value, order} object for sorting given values\n- a {channel, order} object for sorting the named channel’s values" + }, + "stroke": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke" + }, + "strokeDasharray": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dasharray][1]; a constant number indicating the length in pixels of alternating dashes and gaps, or a constant string of numbers separated by spaces or commas (_e.g._, *10 2* for dashes of 10 pixels separated by gaps of 2 pixels), or *none* (the default) for no dashing\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dasharray" + }, + "strokeDashoffset": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dashoffset][1]; a constant indicating the offset in pixels of the first dash along the stroke; defaults to zero.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dashoffset" + }, + "strokeLinecap": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linecap][1]; a constant specifying how to cap stroked paths, such as *butt*, *round*, or *square*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linecap" + }, + "strokeLinejoin": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linejoin][1]; a constant specifying how to join stroked paths, such as *bevel*, *miter*, *miter-clip*, or *round*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linejoin" + }, + "strokeMiterlimit": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-miterlimit][1]; a constant number specifying how to limit the length of *miter* joins on stroked paths.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-miterlimit" + }, + "strokeOpacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-opacity" + }, + "strokeWidth": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-width][1]; a constant number in pixels, or a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-width" + }, + "target": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [target][1]; a constant string specifying the target window (_e.g._,\n*_blank*) for clickable links; used in conjunction with the **href** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/target" + }, + "tip": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/TipPointer" + }, + { + "properties": { + "anchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The tip anchor specifies how to orient the tip box relative to its anchor position; it refers to the part of the tip box that is attached to the anchor point. For example, the *top-left* anchor places the top-left corner of tip box near the anchor position, hence placing the tip box below and to the right of the anchor position." + }, + "fontFamily": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font-family][1]; a constant; defaults to the plot’s font family, which is typically [*system-ui*][2].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-family [2]: https://drafts.csswg.org/css-fonts-4/#valdef-font-family-system-ui" + }, + "fontSize": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font size][1] in pixels; either a constant or a channel; defaults to the plot’s font size, which is typically 10. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-size" + }, + "fontStyle": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font style][1]; a constant; defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-style" + }, + "fontVariant": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font variant][1]; a constant; if the **text** channel contains numbers or dates, defaults to *tabular-nums* to facilitate comparing numbers; otherwise defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant" + }, + "fontWeight": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font weight][1]; a constant; defaults to the plot’s font weight, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight" + }, + "format": { + "additionalProperties": false, + "description": "How channel values are formatted for display. If a format is a string, it is interpreted as a (UTC) time format for temporal channels, and otherwise a number format.", + "properties": { + "ariaLabel": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fill": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fillOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fontSize": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fx": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fy": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "geometry": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "height": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "href": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "length": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "opacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "path": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "r": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "rotate": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "src": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "stroke": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeWidth": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "symbol": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "text": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "title": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "weight": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "width": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "z": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + } + }, + "type": "object" + }, + "frameAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The frame anchor specifies defaults for **x** and **y** based on the plot’s frame; it may be one of the four sides (*top*, *right*, *bottom*, *left*), one of the four corners (*top-left*, *top-right*, *bottom-right*,\n*bottom-left*), or the *middle* of the frame. For example, for tips distributed horizontally at the top of the frame:\n\n```js Plot.tip(data, {x: \"date\", frameAnchor: \"top\"}) ```" + }, + "lineHeight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line height in ems; defaults to 1. The line height affects the (typically vertical) separation between adjacent baselines of text, as well as the separation between the text and its anchor point." + }, + "lineWidth": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line width in ems (e.g., 10 for about 20 characters); defaults to infinity, disabling wrapping and clipping.\n\nIf **textOverflow** is null, lines will be wrapped at the specified length. If a line is split at a soft hyphen (\\xad), a hyphen (-) will be displayed at the end of the line. If **textOverflow** is not null, lines will be clipped according to the given strategy." + }, + "monospace": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, changes the default **fontFamily** to *monospace*, and uses simplified monospaced text metrics calculations." + }, + "pathFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The image filter for the tip’s box; defaults to a drop shadow." + }, + "pointer": { + "$ref": "#/definitions/TipPointer" + }, + "pointerSize": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The size of the tip’s pointer in pixels; defaults to 12." + }, + "preferredAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If an explicit tip anchor is not specified, an anchor is chosen automatically such that the tip fits within the plot’s frame; if the preferred anchor fits, it is chosen." + }, + "textAnchor": { + "anyOf": [ + { + "const": "start", + "type": "string" + }, + { + "const": "middle", + "type": "string" + }, + { + "const": "end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [text anchor][1] controls how text is aligned (typically horizontally) relative to its anchor point; it is one of *start*, *end*, or *middle*. If the frame anchor is *left*, *top-left*, or *bottom-left*, the default text anchor is *start*; if the frame anchor is *right*, *top-right*, or\n*bottom-right*, the default is *end*; otherwise it is *middle*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/text-anchor" + }, + "textOverflow": { + "anyOf": [ + { + "type": "null" + }, + { + "const": "clip", + "type": "string" + }, + { + "const": "ellipsis", + "type": "string" + }, + { + "const": "clip-start", + "type": "string" + }, + { + "const": "clip-end", + "type": "string" + }, + { + "const": "ellipsis-start", + "type": "string" + }, + { + "const": "ellipsis-middle", + "type": "string" + }, + { + "const": "ellipsis-end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How truncate (or wrap) lines of text longer than the given **lineWidth**; one of:\n\n- null (default) - preserve overflowing characters (and wrap if needed)\n- *clip* or *clip-end* - remove characters from the end\n- *clip-start* - remove characters from the start\n- *ellipsis* or *ellipsis-end* - replace characters from the end with an ellipsis (…)\n- *ellipsis-start* - replace characters from the start with an ellipsis (…)\n- *ellipsis-middle* - replace characters from the middle with an ellipsis (…)\n\nIf no **title** was specified, if text requires truncation, a title containing the non-truncated text will be implicitly added." + }, + "textPadding": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The padding around the text in pixels; defaults to 8." + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + } + }, + "type": "object" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to generate a tooltip for this mark, and any tip options." + }, + "title": { + "$ref": "#/definitions/ChannelValue", + "description": "The title; a channel specifying accessible, short textual descriptions as strings (possibly with newlines). If the tip option is specified, the title will be displayed with an interactive tooltip instead of using the SVG [title element][1].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/title" + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The dependent variable horizontal position channel, typically bound to the\n*x* scale." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The independent variable vertical position channel, typically bound to the *y* scale; defaults to the zero-based index of the data [0, 1, 2, …]." + }, + "z": { + "$ref": "#/definitions/ChannelValue", + "description": "An optional ordinal channel for grouping data, producing an independent error bar for each group. If not specified, it defaults to **stroke** if a channel." + } + }, + "required": [ + "data", + "mark", + "x" + ], + "type": "object" + }, + "ErrorBarY": { + "additionalProperties": false, + "description": "The errorbarY mark.", + "properties": { + "ariaDescription": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-description][1]; a constant textual description.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-description" + }, + "ariaHidden": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-hidden][1] state; a constant indicating whether the element is exposed to an accessibility API.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-hidden" + }, + "ariaLabel": { + "$ref": "#/definitions/ChannelValue", + "description": "The [aria-label][1]; a channel specifying short textual labels representing the value in the accessibility tree.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-label" + }, + "ci": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The confidence interval in (0, 1); defaults to 0.95." + }, + "clip": { + "anyOf": [ + { + "const": "frame", + "type": "string" + }, + { + "const": "sphere", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to clip the mark; one of:\n\n- *frame* or true - clip to the plot’s frame (inner area)\n- *sphere* - clip to the projected sphere (*e.g.*, front hemisphere)\n- null or false - do not clip\n\nThe *sphere* clip option requires a geographic projection." + }, + "data": { + "$ref": "#/definitions/PlotMarkData", + "description": "The data source for the mark." + }, + "dx": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The horizontal offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "dy": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The vertical offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "facet": { + "anyOf": [ + { + "const": "auto", + "type": "string" + }, + { + "const": "include", + "type": "string" + }, + { + "const": "exclude", + "type": "string" + }, + { + "const": "super", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to enable or disable faceting; one of:\n\n- *auto* (default) - automatically determine if this mark should be faceted\n- *include* (or true) - draw the subset of the mark’s data in the current facet\n- *exclude* - draw the subset of the mark’s data *not* in the current facet\n- *super* - draw this mark in a single frame that covers all facets\n- null (or false) - repeat this mark’s data across all facets (*i.e.*, no faceting)\n\nWhen a mark uses *super* faceting, it is not allowed to use position scales (*x*, *y*, *fx*, or *fy*); *super* faceting is intended for decorations, such as labels and legends.\n\nWhen top-level faceting is used, the default *auto* setting is equivalent to *include* when the mark data is strictly equal to the top-level facet data; otherwise it is equivalent to null. When the *include* or *exclude* facet mode is chosen, the mark data must be parallel to the top-level facet data: the data must have the same length and order. If the data are not parallel, then the wrong data may be shown in each facet. The default\n*auto* therefore requires strict equality (`===`) for safety, and using the facet data as mark data is recommended when using the *exclude* facet mode. (To construct parallel data safely, consider using [*array*.map][1] on the facet data.)\n\nWhen mark-level faceting is used, the default *auto* setting is equivalent to *include*: the mark will be faceted if either the **fx** or **fy** channel option (or both) is specified. The null or false option will disable faceting, while *exclude* draws the subset of the mark’s data *not* in the current facet.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map" + }, + "facetAnchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "right", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "const": "left", + "type": "string" + }, + { + "const": "top-left", + "type": "string" + }, + { + "const": "top-right", + "type": "string" + }, + { + "const": "bottom-left", + "type": "string" + }, + { + "const": "bottom-right", + "type": "string" + }, + { + "const": "top-empty", + "type": "string" + }, + { + "const": "right-empty", + "type": "string" + }, + { + "const": "bottom-empty", + "type": "string" + }, + { + "const": "left-empty", + "type": "string" + }, + { + "const": "empty", + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to place the mark with respect to facets; one of:\n\n- null (default for most marks) - display the mark in each non-empty facet\n- *top*, *right*, *bottom*, or *left* - display the mark only in facets on the given side\n- *top-empty*, *right-empty*, *bottom-empty*, or *left-empty* (default for axis marks) - display the mark only in facets that have empty space on the given side: either the margin, or an empty facet\n- *empty* - display the mark in empty facets only" + }, + "fill": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill" + }, + "fillOpacity": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill-opacity][1]; a constant number between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill-opacity" + }, + "filter": { + "$ref": "#/definitions/ChannelValue", + "description": "Applies a transform to filter the mark’s index according to the given channel values; only truthy values are retained.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "fx": { + "$ref": "#/definitions/ChannelValue", + "description": "The horizontal facet position channel, for mark-level faceting, bound to the *fx* scale." + }, + "fy": { + "$ref": "#/definitions/ChannelValue", + "description": "The vertical facet position channel, for mark-level faceting, bound to the\n*fy* scale." + }, + "href": { + "$ref": "#/definitions/ChannelValue", + "description": "The [href][1]; a channel specifying URLs for clickable links. May be used in conjunction with the **target** option to open links in another window.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/href" + }, + "imageFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A CSS [filter][1]; a constant string used to adjust the rendering of images, such as *blur(5px)*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/filter" + }, + "margin": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four mark margins: **marginTop**,\n**marginRight**, **marginBottom**, and **marginLeft**; typically defaults to 0, except for axis marks." + }, + "marginBottom": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s bottom margin; the minimum distance in pixels between the bottom edges of the inner and outer plot area." + }, + "marginLeft": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s left margin; the minimum distance in pixels between the left edges of the inner and outer plot area." + }, + "marginRight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s right margin; the minimum distance in pixels between the right edges of the mark’s inner and outer plot area." + }, + "marginTop": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s top margin; the minimum distance in pixels between the top edges of the inner and outer plot area." + }, + "mark": { + "const": "errorbarY", + "description": "A mark that draws error bars for a calculated parametric confidence interval for a dependent variable (*y*), potentially grouped by an independent variable (*x*).\n\nThis mark aggregates raw values to produce a [parametric confidence interval][1] of the mean, assuming a normal distribution. To instead visualize pre-computeted interval values or custom aggregations, use a **ruleX** mark with specified **y1** and **y2** channels.\n\nMultiple error bars can be produced by specifying a **z** or **stroke** channel. Set the **marker** option to `'tick'` to add small perpendicular lines at the start and end of the error interval.\n\n[1]: https://en.wikipedia.org/wiki/Normal_distribution#Confidence_intervals", + "type": "string" + }, + "marker": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for markerStart, markerMid, and markerEnd; one of:\n\n- a marker name such as *arrow* or *circle*\n- *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*" + }, + "markerEnd": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The marker for the ending point of a line segment; one of:\n\n- a marker name such as *arrow* or *circle*\n* *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*" + }, + "markerMid": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The marker for any middle (interior) points of a line segment. If the line segment only has a start and end point, this option has no effect. One of:\n\n- a marker name such as *arrow* or *circle*\n* *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*\n* a function - a custom marker function; see below" + }, + "markerStart": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The marker for the starting point of a line segment; one of:\n\n- a marker name such as *arrow* or *circle*\n* *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*" + }, + "mixBlendMode": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [mix-blend-mode][1]; a constant string specifying how to blend content such as *multiply*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode" + }, + "opacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally. For faster rendering, prefer the **strokeOpacity** or **fillOpacity** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/opacity" + }, + "paintOrder": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [paint-order][1]; a constant string specifying the order in which the\n**fill**, **stroke**, and any markers are drawn; defaults to *normal*, which draws the fill, then stroke, then markers; defaults to *stroke* for the text mark to create a “halo” around text to improve legibility.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/paint-order" + }, + "pointerEvents": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [pointer-events][1] property; a constant string such as *none*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/pointer-events" + }, + "reverse": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Applies a transform to reverse the order of the mark’s index, say for reverse input order." + }, + "select": { + "$ref": "#/definitions/SelectFilter", + "description": "Applies a filter transform after data is loaded to highlight selected values only. For example, `first` and `last` select the first or last values of series only (using the *z* channel to separate series). Meanwhile, `nearestX` and `nearestY` select the point nearest to the pointer along the *x* or *y* channel dimension. Unlike Mosaic selections, a mark level *select* is internal to the mark only, and does not populate a param or selection value to be shared across clients.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "shapeRendering": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [shape-rendering][1]; a constant string such as *crispEdges*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/shape-rendering" + }, + "sort": { + "anyOf": [ + { + "$ref": "#/definitions/SortOrder" + }, + { + "$ref": "#/definitions/ChannelDomainSort" + } + ], + "description": "Either applies a transform to sort the mark’s index by the specified channel values, or imputes ordinal scale domains from this mark’s channels.\n\nWhen imputing ordinal scale domains from channel values, the **sort** option is an object whose keys are ordinal scale names such as *x* or *fx*, and whose values are channel names such as *y*, *y1*, or *y2*. For example, to impute the *y* scale’s domain from the associated *x* channel values in ascending order:\n\n```js sort: {y: \"x\"} ```\n\nFor different sort options for different scales, replace the channel name with a *value* object and per-scale options:\n\n```js sort: {y: {value: \"-x\"}} ```\n\nWhen sorting the mark’s index, the **sort** option is instead one of:\n\n- a channel value definition for sorting given values in ascending order\n- a {value, order} object for sorting given values\n- a {channel, order} object for sorting the named channel’s values" + }, + "stroke": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke" + }, + "strokeDasharray": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dasharray][1]; a constant number indicating the length in pixels of alternating dashes and gaps, or a constant string of numbers separated by spaces or commas (_e.g._, *10 2* for dashes of 10 pixels separated by gaps of 2 pixels), or *none* (the default) for no dashing\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dasharray" + }, + "strokeDashoffset": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dashoffset][1]; a constant indicating the offset in pixels of the first dash along the stroke; defaults to zero.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dashoffset" + }, + "strokeLinecap": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linecap][1]; a constant specifying how to cap stroked paths, such as *butt*, *round*, or *square*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linecap" + }, + "strokeLinejoin": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linejoin][1]; a constant specifying how to join stroked paths, such as *bevel*, *miter*, *miter-clip*, or *round*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linejoin" + }, + "strokeMiterlimit": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-miterlimit][1]; a constant number specifying how to limit the length of *miter* joins on stroked paths.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-miterlimit" + }, + "strokeOpacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-opacity" + }, + "strokeWidth": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-width][1]; a constant number in pixels, or a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-width" + }, + "target": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [target][1]; a constant string specifying the target window (_e.g._,\n*_blank*) for clickable links; used in conjunction with the **href** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/target" + }, + "tip": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/TipPointer" + }, + { + "properties": { + "anchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The tip anchor specifies how to orient the tip box relative to its anchor position; it refers to the part of the tip box that is attached to the anchor point. For example, the *top-left* anchor places the top-left corner of tip box near the anchor position, hence placing the tip box below and to the right of the anchor position." + }, + "fontFamily": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font-family][1]; a constant; defaults to the plot’s font family, which is typically [*system-ui*][2].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-family [2]: https://drafts.csswg.org/css-fonts-4/#valdef-font-family-system-ui" + }, + "fontSize": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font size][1] in pixels; either a constant or a channel; defaults to the plot’s font size, which is typically 10. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-size" + }, + "fontStyle": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font style][1]; a constant; defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-style" + }, + "fontVariant": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font variant][1]; a constant; if the **text** channel contains numbers or dates, defaults to *tabular-nums* to facilitate comparing numbers; otherwise defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant" + }, + "fontWeight": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font weight][1]; a constant; defaults to the plot’s font weight, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight" + }, + "format": { + "additionalProperties": false, + "description": "How channel values are formatted for display. If a format is a string, it is interpreted as a (UTC) time format for temporal channels, and otherwise a number format.", + "properties": { + "ariaLabel": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fill": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fillOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fontSize": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fx": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fy": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "geometry": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "height": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "href": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "length": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "opacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "path": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "r": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "rotate": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "src": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "stroke": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeWidth": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "symbol": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "text": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "title": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "weight": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "width": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "z": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + } + }, + "type": "object" + }, + "frameAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The frame anchor specifies defaults for **x** and **y** based on the plot’s frame; it may be one of the four sides (*top*, *right*, *bottom*, *left*), one of the four corners (*top-left*, *top-right*, *bottom-right*,\n*bottom-left*), or the *middle* of the frame. For example, for tips distributed horizontally at the top of the frame:\n\n```js Plot.tip(data, {x: \"date\", frameAnchor: \"top\"}) ```" + }, + "lineHeight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line height in ems; defaults to 1. The line height affects the (typically vertical) separation between adjacent baselines of text, as well as the separation between the text and its anchor point." + }, + "lineWidth": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line width in ems (e.g., 10 for about 20 characters); defaults to infinity, disabling wrapping and clipping.\n\nIf **textOverflow** is null, lines will be wrapped at the specified length. If a line is split at a soft hyphen (\\xad), a hyphen (-) will be displayed at the end of the line. If **textOverflow** is not null, lines will be clipped according to the given strategy." + }, + "monospace": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, changes the default **fontFamily** to *monospace*, and uses simplified monospaced text metrics calculations." + }, + "pathFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The image filter for the tip’s box; defaults to a drop shadow." + }, + "pointer": { + "$ref": "#/definitions/TipPointer" + }, + "pointerSize": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The size of the tip’s pointer in pixels; defaults to 12." + }, + "preferredAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If an explicit tip anchor is not specified, an anchor is chosen automatically such that the tip fits within the plot’s frame; if the preferred anchor fits, it is chosen." + }, + "textAnchor": { + "anyOf": [ + { + "const": "start", + "type": "string" + }, + { + "const": "middle", + "type": "string" + }, + { + "const": "end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [text anchor][1] controls how text is aligned (typically horizontally) relative to its anchor point; it is one of *start*, *end*, or *middle*. If the frame anchor is *left*, *top-left*, or *bottom-left*, the default text anchor is *start*; if the frame anchor is *right*, *top-right*, or\n*bottom-right*, the default is *end*; otherwise it is *middle*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/text-anchor" + }, + "textOverflow": { + "anyOf": [ + { + "type": "null" + }, + { + "const": "clip", + "type": "string" + }, + { + "const": "ellipsis", + "type": "string" + }, + { + "const": "clip-start", + "type": "string" + }, + { + "const": "clip-end", + "type": "string" + }, + { + "const": "ellipsis-start", + "type": "string" + }, + { + "const": "ellipsis-middle", + "type": "string" + }, + { + "const": "ellipsis-end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How truncate (or wrap) lines of text longer than the given **lineWidth**; one of:\n\n- null (default) - preserve overflowing characters (and wrap if needed)\n- *clip* or *clip-end* - remove characters from the end\n- *clip-start* - remove characters from the start\n- *ellipsis* or *ellipsis-end* - replace characters from the end with an ellipsis (…)\n- *ellipsis-start* - replace characters from the start with an ellipsis (…)\n- *ellipsis-middle* - replace characters from the middle with an ellipsis (…)\n\nIf no **title** was specified, if text requires truncation, a title containing the non-truncated text will be implicitly added." + }, + "textPadding": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The padding around the text in pixels; defaults to 8." + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + } + }, + "type": "object" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to generate a tooltip for this mark, and any tip options." + }, + "title": { + "$ref": "#/definitions/ChannelValue", + "description": "The title; a channel specifying accessible, short textual descriptions as strings (possibly with newlines). If the tip option is specified, the title will be displayed with an interactive tooltip instead of using the SVG [title element][1].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/title" + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The independent variable horizontal position channel, typically bound to the *x* scale; defaults to the zero-based index of the data [0, 1, 2, …]." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The dependent variable vertical position channel, typically bound to the\n*y* scale." + }, + "z": { + "$ref": "#/definitions/ChannelValue", + "description": "An optional ordinal channel for grouping data, producing an independent error bar for each group. If not specified, it defaults to **stroke** if a channel." + } + }, + "required": [ + "data", + "mark", + "y" + ], + "type": "object" + }, + "First": { + "additionalProperties": false, + "properties": { + "distinct": { + "type": "boolean" + }, + "first": { + "anyOf": [ + { + "description": "A transform argument.", + "type": [ + "string", + "number", + "boolean" + ] + }, + { + "items": { + "description": "A transform argument.", + "type": [ + "string", + "number", + "boolean" + ] + }, + "maxItems": 1, + "minItems": 1, + "type": "array" + } + ], + "description": "Return the first column value found in an aggregation group." + }, + "orderby": { + "anyOf": [ + { + "$ref": "#/definitions/TransformField" + }, + { + "items": { + "$ref": "#/definitions/TransformField" + }, + "type": "array" + } + ] + }, + "partitionby": { + "anyOf": [ + { + "$ref": "#/definitions/TransformField" + }, + { + "items": { + "$ref": "#/definitions/TransformField" + }, + "type": "array" + } + ] + }, + "range": { + "anyOf": [ + { + "items": { + "type": [ + "number", + "null" + ] + }, + "type": "array" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "rows": { + "anyOf": [ + { + "items": { + "type": [ + "number", + "null" + ] + }, + "type": "array" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + } + }, + "required": [ + "first" + ], + "type": "object" + }, + "FirstValue": { + "additionalProperties": false, + "properties": { + "first_value": { + "anyOf": [ + { + "description": "A transform argument.", + "type": [ + "string", + "number", + "boolean" + ] + }, + { + "items": { + "description": "A transform argument.", + "type": [ + "string", + "number", + "boolean" + ] + }, + "maxItems": 1, + "minItems": 1, + "type": "array" + } + ], + "description": "Get the first value of the given column in the current window frame." + }, + "orderby": { + "anyOf": [ + { + "$ref": "#/definitions/TransformField" + }, + { + "items": { + "$ref": "#/definitions/TransformField" + }, + "type": "array" + } + ] + }, + "partitionby": { + "anyOf": [ + { + "$ref": "#/definitions/TransformField" + }, + { + "items": { + "$ref": "#/definitions/TransformField" + }, + "type": "array" + } + ] + }, + "range": { + "anyOf": [ + { + "items": { + "type": [ + "number", + "null" + ] + }, + "type": "array" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "rows": { + "anyOf": [ + { + "items": { + "type": [ + "number", + "null" + ] + }, + "type": "array" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + } + }, + "required": [ + "first_value" + ], + "type": "object" + }, + "Fixed": { + "const": "Fixed", + "description": "A symbol indicating a fixed scale domain. A fixed domain is initially determined from data as usual, but subsequently \"fixed\" so that it does not change over subsequent interactive filtering, ensring stable comparisons.", + "type": "string" + }, + "Frame": { + "additionalProperties": false, + "description": "The frame mark.", + "properties": { + "anchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "right", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "const": "left", + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If null (default), the rectangular outline of the frame is drawn; otherwise the frame is drawn as a line only on the given side, and the\n**rx**, **ry**, **fill**, and **fillOpacity** options are ignored." + }, + "ariaDescription": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-description][1]; a constant textual description.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-description" + }, + "ariaHidden": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-hidden][1] state; a constant indicating whether the element is exposed to an accessibility API.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-hidden" + }, + "ariaLabel": { + "$ref": "#/definitions/ChannelValue", + "description": "The [aria-label][1]; a channel specifying short textual labels representing the value in the accessibility tree.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-label" + }, + "clip": { + "anyOf": [ + { + "const": "frame", + "type": "string" + }, + { + "const": "sphere", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to clip the mark; one of:\n\n- *frame* or true - clip to the plot’s frame (inner area)\n- *sphere* - clip to the projected sphere (*e.g.*, front hemisphere)\n- null or false - do not clip\n\nThe *sphere* clip option requires a geographic projection." + }, + "dx": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The horizontal offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "dy": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The vertical offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "facet": { + "anyOf": [ + { + "const": "auto", + "type": "string" + }, + { + "const": "include", + "type": "string" + }, + { + "const": "exclude", + "type": "string" + }, + { + "const": "super", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to enable or disable faceting; one of:\n\n- *auto* (default) - automatically determine if this mark should be faceted\n- *include* (or true) - draw the subset of the mark’s data in the current facet\n- *exclude* - draw the subset of the mark’s data *not* in the current facet\n- *super* - draw this mark in a single frame that covers all facets\n- null (or false) - repeat this mark’s data across all facets (*i.e.*, no faceting)\n\nWhen a mark uses *super* faceting, it is not allowed to use position scales (*x*, *y*, *fx*, or *fy*); *super* faceting is intended for decorations, such as labels and legends.\n\nWhen top-level faceting is used, the default *auto* setting is equivalent to *include* when the mark data is strictly equal to the top-level facet data; otherwise it is equivalent to null. When the *include* or *exclude* facet mode is chosen, the mark data must be parallel to the top-level facet data: the data must have the same length and order. If the data are not parallel, then the wrong data may be shown in each facet. The default\n*auto* therefore requires strict equality (`===`) for safety, and using the facet data as mark data is recommended when using the *exclude* facet mode. (To construct parallel data safely, consider using [*array*.map][1] on the facet data.)\n\nWhen mark-level faceting is used, the default *auto* setting is equivalent to *include*: the mark will be faceted if either the **fx** or **fy** channel option (or both) is specified. The null or false option will disable faceting, while *exclude* draws the subset of the mark’s data *not* in the current facet.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map" + }, + "facetAnchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "right", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "const": "left", + "type": "string" + }, + { + "const": "top-left", + "type": "string" + }, + { + "const": "top-right", + "type": "string" + }, + { + "const": "bottom-left", + "type": "string" + }, + { + "const": "bottom-right", + "type": "string" + }, + { + "const": "top-empty", + "type": "string" + }, + { + "const": "right-empty", + "type": "string" + }, + { + "const": "bottom-empty", + "type": "string" + }, + { + "const": "left-empty", + "type": "string" + }, + { + "const": "empty", + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to place the mark with respect to facets; one of:\n\n- null (default for most marks) - display the mark in each non-empty facet\n- *top*, *right*, *bottom*, or *left* - display the mark only in facets on the given side\n- *top-empty*, *right-empty*, *bottom-empty*, or *left-empty* (default for axis marks) - display the mark only in facets that have empty space on the given side: either the margin, or an empty facet\n- *empty* - display the mark in empty facets only" + }, + "fill": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill" + }, + "fillOpacity": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill-opacity][1]; a constant number between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill-opacity" + }, + "filter": { + "$ref": "#/definitions/ChannelValue", + "description": "Applies a transform to filter the mark’s index according to the given channel values; only truthy values are retained.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "fx": { + "$ref": "#/definitions/ChannelValue", + "description": "The horizontal facet position channel, for mark-level faceting, bound to the *fx* scale." + }, + "fy": { + "$ref": "#/definitions/ChannelValue", + "description": "The vertical facet position channel, for mark-level faceting, bound to the\n*fy* scale." + }, + "href": { + "$ref": "#/definitions/ChannelValue", + "description": "The [href][1]; a channel specifying URLs for clickable links. May be used in conjunction with the **target** option to open links in another window.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/href" + }, + "imageFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A CSS [filter][1]; a constant string used to adjust the rendering of images, such as *blur(5px)*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/filter" + }, + "inset": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four insets: **insetTop**,\n**insetRight**, **insetBottom**, and **insetLeft**. All insets typically default to zero, though not always (say when using bin transform). A positive inset reduces effective area, while a negative inset increases it." + }, + "insetBottom": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Insets the bottom edge by the specified number of pixels. A positive value insets towards the top edge (reducing effective area), while a negative value insets away from the top edge (increasing it)." + }, + "insetLeft": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Insets the left edge by the specified number of pixels. A positive value insets towards the right edge (reducing effective area), while a negative value insets away from the right edge (increasing it)." + }, + "insetRight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Insets the right edge by the specified number of pixels. A positive value insets towards the left edge (reducing effective area), while a negative value insets away from the left edge (increasing it)." + }, + "insetTop": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Insets the top edge by the specified number of pixels. A positive value insets towards the bottom edge (reducing effective area), while a negative value insets away from the bottom edge (increasing it)." + }, + "margin": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four mark margins: **marginTop**,\n**marginRight**, **marginBottom**, and **marginLeft**; typically defaults to 0, except for axis marks." + }, + "marginBottom": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s bottom margin; the minimum distance in pixels between the bottom edges of the inner and outer plot area." + }, + "marginLeft": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s left margin; the minimum distance in pixels between the left edges of the inner and outer plot area." + }, + "marginRight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s right margin; the minimum distance in pixels between the right edges of the mark’s inner and outer plot area." + }, + "marginTop": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s top margin; the minimum distance in pixels between the top edges of the inner and outer plot area." + }, + "mark": { + "const": "frame", + "description": "Draws a rectangle around the plot’s frame, or if an **anchor** is given, a line on the given side. Useful for visual separation of facets, or in conjunction with axes and grids to fill the frame’s background.", + "type": "string" + }, + "mixBlendMode": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [mix-blend-mode][1]; a constant string specifying how to blend content such as *multiply*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode" + }, + "opacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally. For faster rendering, prefer the **strokeOpacity** or **fillOpacity** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/opacity" + }, + "paintOrder": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [paint-order][1]; a constant string specifying the order in which the\n**fill**, **stroke**, and any markers are drawn; defaults to *normal*, which draws the fill, then stroke, then markers; defaults to *stroke* for the text mark to create a “halo” around text to improve legibility.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/paint-order" + }, + "pointerEvents": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [pointer-events][1] property; a constant string such as *none*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/pointer-events" + }, + "reverse": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Applies a transform to reverse the order of the mark’s index, say for reverse input order." + }, + "rx": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The rounded corner [*x*-radius][1], either in pixels or as a percentage of the rect width. If **rx** is not specified, it defaults to **ry** if present, and otherwise draws square corners.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/rx" + }, + "ry": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The rounded corner [*y*-radius][1], either in pixels or as a percentage of the rect height. If **ry** is not specified, it defaults to **rx** if present, and otherwise draws square corners.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/ry" + }, + "select": { + "$ref": "#/definitions/SelectFilter", + "description": "Applies a filter transform after data is loaded to highlight selected values only. For example, `first` and `last` select the first or last values of series only (using the *z* channel to separate series). Meanwhile, `nearestX` and `nearestY` select the point nearest to the pointer along the *x* or *y* channel dimension. Unlike Mosaic selections, a mark level *select* is internal to the mark only, and does not populate a param or selection value to be shared across clients.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "shapeRendering": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [shape-rendering][1]; a constant string such as *crispEdges*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/shape-rendering" + }, + "sort": { + "anyOf": [ + { + "$ref": "#/definitions/SortOrder" + }, + { + "$ref": "#/definitions/ChannelDomainSort" + } + ], + "description": "Either applies a transform to sort the mark’s index by the specified channel values, or imputes ordinal scale domains from this mark’s channels.\n\nWhen imputing ordinal scale domains from channel values, the **sort** option is an object whose keys are ordinal scale names such as *x* or *fx*, and whose values are channel names such as *y*, *y1*, or *y2*. For example, to impute the *y* scale’s domain from the associated *x* channel values in ascending order:\n\n```js sort: {y: \"x\"} ```\n\nFor different sort options for different scales, replace the channel name with a *value* object and per-scale options:\n\n```js sort: {y: {value: \"-x\"}} ```\n\nWhen sorting the mark’s index, the **sort** option is instead one of:\n\n- a channel value definition for sorting given values in ascending order\n- a {value, order} object for sorting given values\n- a {channel, order} object for sorting the named channel’s values" + }, + "stroke": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke" + }, + "strokeDasharray": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dasharray][1]; a constant number indicating the length in pixels of alternating dashes and gaps, or a constant string of numbers separated by spaces or commas (_e.g._, *10 2* for dashes of 10 pixels separated by gaps of 2 pixels), or *none* (the default) for no dashing\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dasharray" + }, + "strokeDashoffset": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dashoffset][1]; a constant indicating the offset in pixels of the first dash along the stroke; defaults to zero.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dashoffset" + }, + "strokeLinecap": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linecap][1]; a constant specifying how to cap stroked paths, such as *butt*, *round*, or *square*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linecap" + }, + "strokeLinejoin": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linejoin][1]; a constant specifying how to join stroked paths, such as *bevel*, *miter*, *miter-clip*, or *round*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linejoin" + }, + "strokeMiterlimit": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-miterlimit][1]; a constant number specifying how to limit the length of *miter* joins on stroked paths.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-miterlimit" + }, + "strokeOpacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-opacity" + }, + "strokeWidth": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-width][1]; a constant number in pixels, or a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-width" + }, + "target": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [target][1]; a constant string specifying the target window (_e.g._,\n*_blank*) for clickable links; used in conjunction with the **href** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/target" + }, + "tip": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/TipPointer" + }, + { + "properties": { + "anchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The tip anchor specifies how to orient the tip box relative to its anchor position; it refers to the part of the tip box that is attached to the anchor point. For example, the *top-left* anchor places the top-left corner of tip box near the anchor position, hence placing the tip box below and to the right of the anchor position." + }, + "fontFamily": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font-family][1]; a constant; defaults to the plot’s font family, which is typically [*system-ui*][2].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-family [2]: https://drafts.csswg.org/css-fonts-4/#valdef-font-family-system-ui" + }, + "fontSize": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font size][1] in pixels; either a constant or a channel; defaults to the plot’s font size, which is typically 10. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-size" + }, + "fontStyle": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font style][1]; a constant; defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-style" + }, + "fontVariant": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font variant][1]; a constant; if the **text** channel contains numbers or dates, defaults to *tabular-nums* to facilitate comparing numbers; otherwise defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant" + }, + "fontWeight": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font weight][1]; a constant; defaults to the plot’s font weight, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight" + }, + "format": { + "additionalProperties": false, + "description": "How channel values are formatted for display. If a format is a string, it is interpreted as a (UTC) time format for temporal channels, and otherwise a number format.", + "properties": { + "ariaLabel": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fill": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fillOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fontSize": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fx": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fy": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "geometry": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "height": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "href": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "length": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "opacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "path": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "r": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "rotate": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "src": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "stroke": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeWidth": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "symbol": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "text": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "title": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "weight": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "width": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "z": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + } + }, + "type": "object" + }, + "frameAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The frame anchor specifies defaults for **x** and **y** based on the plot’s frame; it may be one of the four sides (*top*, *right*, *bottom*, *left*), one of the four corners (*top-left*, *top-right*, *bottom-right*,\n*bottom-left*), or the *middle* of the frame. For example, for tips distributed horizontally at the top of the frame:\n\n```js Plot.tip(data, {x: \"date\", frameAnchor: \"top\"}) ```" + }, + "lineHeight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line height in ems; defaults to 1. The line height affects the (typically vertical) separation between adjacent baselines of text, as well as the separation between the text and its anchor point." + }, + "lineWidth": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line width in ems (e.g., 10 for about 20 characters); defaults to infinity, disabling wrapping and clipping.\n\nIf **textOverflow** is null, lines will be wrapped at the specified length. If a line is split at a soft hyphen (\\xad), a hyphen (-) will be displayed at the end of the line. If **textOverflow** is not null, lines will be clipped according to the given strategy." + }, + "monospace": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, changes the default **fontFamily** to *monospace*, and uses simplified monospaced text metrics calculations." + }, + "pathFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The image filter for the tip’s box; defaults to a drop shadow." + }, + "pointer": { + "$ref": "#/definitions/TipPointer" + }, + "pointerSize": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The size of the tip’s pointer in pixels; defaults to 12." + }, + "preferredAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If an explicit tip anchor is not specified, an anchor is chosen automatically such that the tip fits within the plot’s frame; if the preferred anchor fits, it is chosen." + }, + "textAnchor": { + "anyOf": [ + { + "const": "start", + "type": "string" + }, + { + "const": "middle", + "type": "string" + }, + { + "const": "end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [text anchor][1] controls how text is aligned (typically horizontally) relative to its anchor point; it is one of *start*, *end*, or *middle*. If the frame anchor is *left*, *top-left*, or *bottom-left*, the default text anchor is *start*; if the frame anchor is *right*, *top-right*, or\n*bottom-right*, the default is *end*; otherwise it is *middle*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/text-anchor" + }, + "textOverflow": { + "anyOf": [ + { + "type": "null" + }, + { + "const": "clip", + "type": "string" + }, + { + "const": "ellipsis", + "type": "string" + }, + { + "const": "clip-start", + "type": "string" + }, + { + "const": "clip-end", + "type": "string" + }, + { + "const": "ellipsis-start", + "type": "string" + }, + { + "const": "ellipsis-middle", + "type": "string" + }, + { + "const": "ellipsis-end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How truncate (or wrap) lines of text longer than the given **lineWidth**; one of:\n\n- null (default) - preserve overflowing characters (and wrap if needed)\n- *clip* or *clip-end* - remove characters from the end\n- *clip-start* - remove characters from the start\n- *ellipsis* or *ellipsis-end* - replace characters from the end with an ellipsis (…)\n- *ellipsis-start* - replace characters from the start with an ellipsis (…)\n- *ellipsis-middle* - replace characters from the middle with an ellipsis (…)\n\nIf no **title** was specified, if text requires truncation, a title containing the non-truncated text will be implicitly added." + }, + "textPadding": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The padding around the text in pixels; defaults to 8." + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + } + }, + "type": "object" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to generate a tooltip for this mark, and any tip options." + }, + "title": { + "$ref": "#/definitions/ChannelValue", + "description": "The title; a channel specifying accessible, short textual descriptions as strings (possibly with newlines). If the tip option is specified, the title will be displayed with an interactive tooltip instead of using the SVG [title element][1].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/title" + } + }, + "required": [ + "mark" + ], + "type": "object" + }, + "FrameAnchor": { + "description": "How to anchor a mark relative to the plot’s frame; one of:\n\n- *middle* - centered in the middle\n- in the middle of one of the edges: *top*, *right*, *bottom*, *left*\n- in one of the corners: *top-left*, *top-right*, *bottom-right*, *bottom-left*", + "enum": [ + "middle", + "top-left", + "top", + "top-right", + "right", + "bottom-right", + "bottom", + "bottom-left", + "left" + ], + "type": "string" + }, + "Geo": { + "additionalProperties": false, + "description": "The geo mark.", + "properties": { + "ariaDescription": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-description][1]; a constant textual description.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-description" + }, + "ariaHidden": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-hidden][1] state; a constant indicating whether the element is exposed to an accessibility API.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-hidden" + }, + "ariaLabel": { + "$ref": "#/definitions/ChannelValue", + "description": "The [aria-label][1]; a channel specifying short textual labels representing the value in the accessibility tree.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-label" + }, + "clip": { + "anyOf": [ + { + "const": "frame", + "type": "string" + }, + { + "const": "sphere", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to clip the mark; one of:\n\n- *frame* or true - clip to the plot’s frame (inner area)\n- *sphere* - clip to the projected sphere (*e.g.*, front hemisphere)\n- null or false - do not clip\n\nThe *sphere* clip option requires a geographic projection." + }, + "data": { + "$ref": "#/definitions/PlotMarkData", + "description": "The data source for the mark." + }, + "dx": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The horizontal offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "dy": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The vertical offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "facet": { + "anyOf": [ + { + "const": "auto", + "type": "string" + }, + { + "const": "include", + "type": "string" + }, + { + "const": "exclude", + "type": "string" + }, + { + "const": "super", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to enable or disable faceting; one of:\n\n- *auto* (default) - automatically determine if this mark should be faceted\n- *include* (or true) - draw the subset of the mark’s data in the current facet\n- *exclude* - draw the subset of the mark’s data *not* in the current facet\n- *super* - draw this mark in a single frame that covers all facets\n- null (or false) - repeat this mark’s data across all facets (*i.e.*, no faceting)\n\nWhen a mark uses *super* faceting, it is not allowed to use position scales (*x*, *y*, *fx*, or *fy*); *super* faceting is intended for decorations, such as labels and legends.\n\nWhen top-level faceting is used, the default *auto* setting is equivalent to *include* when the mark data is strictly equal to the top-level facet data; otherwise it is equivalent to null. When the *include* or *exclude* facet mode is chosen, the mark data must be parallel to the top-level facet data: the data must have the same length and order. If the data are not parallel, then the wrong data may be shown in each facet. The default\n*auto* therefore requires strict equality (`===`) for safety, and using the facet data as mark data is recommended when using the *exclude* facet mode. (To construct parallel data safely, consider using [*array*.map][1] on the facet data.)\n\nWhen mark-level faceting is used, the default *auto* setting is equivalent to *include*: the mark will be faceted if either the **fx** or **fy** channel option (or both) is specified. The null or false option will disable faceting, while *exclude* draws the subset of the mark’s data *not* in the current facet.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map" + }, + "facetAnchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "right", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "const": "left", + "type": "string" + }, + { + "const": "top-left", + "type": "string" + }, + { + "const": "top-right", + "type": "string" + }, + { + "const": "bottom-left", + "type": "string" + }, + { + "const": "bottom-right", + "type": "string" + }, + { + "const": "top-empty", + "type": "string" + }, + { + "const": "right-empty", + "type": "string" + }, + { + "const": "bottom-empty", + "type": "string" + }, + { + "const": "left-empty", + "type": "string" + }, + { + "const": "empty", + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to place the mark with respect to facets; one of:\n\n- null (default for most marks) - display the mark in each non-empty facet\n- *top*, *right*, *bottom*, or *left* - display the mark only in facets on the given side\n- *top-empty*, *right-empty*, *bottom-empty*, or *left-empty* (default for axis marks) - display the mark only in facets that have empty space on the given side: either the margin, or an empty facet\n- *empty* - display the mark in empty facets only" + }, + "fill": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill" + }, + "fillOpacity": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill-opacity][1]; a constant number between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill-opacity" + }, + "filter": { + "$ref": "#/definitions/ChannelValue", + "description": "Applies a transform to filter the mark’s index according to the given channel values; only truthy values are retained.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "fx": { + "$ref": "#/definitions/ChannelValue", + "description": "The horizontal facet position channel, for mark-level faceting, bound to the *fx* scale." + }, + "fy": { + "$ref": "#/definitions/ChannelValue", + "description": "The vertical facet position channel, for mark-level faceting, bound to the\n*fy* scale." + }, + "geometry": { + "$ref": "#/definitions/ChannelValue", + "description": "A required channel for the geometry to render; defaults to identity, assuming *data* is a GeoJSON object or an iterable of GeoJSON objects." + }, + "href": { + "$ref": "#/definitions/ChannelValue", + "description": "The [href][1]; a channel specifying URLs for clickable links. May be used in conjunction with the **target** option to open links in another window.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/href" + }, + "imageFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A CSS [filter][1]; a constant string used to adjust the rendering of images, such as *blur(5px)*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/filter" + }, + "margin": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four mark margins: **marginTop**,\n**marginRight**, **marginBottom**, and **marginLeft**; typically defaults to 0, except for axis marks." + }, + "marginBottom": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s bottom margin; the minimum distance in pixels between the bottom edges of the inner and outer plot area." + }, + "marginLeft": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s left margin; the minimum distance in pixels between the left edges of the inner and outer plot area." + }, + "marginRight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s right margin; the minimum distance in pixels between the right edges of the mark’s inner and outer plot area." + }, + "marginTop": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s top margin; the minimum distance in pixels between the top edges of the inner and outer plot area." + }, + "mark": { + "const": "geo", + "description": "A geo mark. The **geometry** channel, which defaults to the identity function assuming that *data* is a GeoJSON object or an iterable of GeoJSON objects, is projected to the plane using the plot’s top-level\n**projection**.\n\nIf *data* is a GeoJSON feature collection, then the mark’s data is\n*data*.features; if *data* is a GeoJSON geometry collection, then the mark’s data is *data*.geometries; if *data* is some other GeoJSON object, then the mark’s data is the single-element array [*data*].", + "type": "string" + }, + "mixBlendMode": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [mix-blend-mode][1]; a constant string specifying how to blend content such as *multiply*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode" + }, + "opacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally. For faster rendering, prefer the **strokeOpacity** or **fillOpacity** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/opacity" + }, + "paintOrder": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [paint-order][1]; a constant string specifying the order in which the\n**fill**, **stroke**, and any markers are drawn; defaults to *normal*, which draws the fill, then stroke, then markers; defaults to *stroke* for the text mark to create a “halo” around text to improve legibility.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/paint-order" + }, + "pointerEvents": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [pointer-events][1] property; a constant string such as *none*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/pointer-events" + }, + "r": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The size of Point and MultiPoint geometries, defaulting to a constant 3 pixels. If **r** is a number, it is interpreted as a constant radius in pixels; otherwise it is interpreted as a channel and the effective radius is controlled by the *r* scale, which defaults to a *sqrt* scale such that the visual area of a point is proportional to its associated value.\n\nIf **r** is a channel, geometries will be sorted by descending radius by default, to limit occlusion; use the **sort** transform to control render order. Geometries with a nonpositive radius are not drawn." + }, + "reverse": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Applies a transform to reverse the order of the mark’s index, say for reverse input order." + }, + "select": { + "$ref": "#/definitions/SelectFilter", + "description": "Applies a filter transform after data is loaded to highlight selected values only. For example, `first` and `last` select the first or last values of series only (using the *z* channel to separate series). Meanwhile, `nearestX` and `nearestY` select the point nearest to the pointer along the *x* or *y* channel dimension. Unlike Mosaic selections, a mark level *select* is internal to the mark only, and does not populate a param or selection value to be shared across clients.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "shapeRendering": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [shape-rendering][1]; a constant string such as *crispEdges*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/shape-rendering" + }, + "sort": { + "anyOf": [ + { + "$ref": "#/definitions/SortOrder" + }, + { + "$ref": "#/definitions/ChannelDomainSort" + } + ], + "description": "Either applies a transform to sort the mark’s index by the specified channel values, or imputes ordinal scale domains from this mark’s channels.\n\nWhen imputing ordinal scale domains from channel values, the **sort** option is an object whose keys are ordinal scale names such as *x* or *fx*, and whose values are channel names such as *y*, *y1*, or *y2*. For example, to impute the *y* scale’s domain from the associated *x* channel values in ascending order:\n\n```js sort: {y: \"x\"} ```\n\nFor different sort options for different scales, replace the channel name with a *value* object and per-scale options:\n\n```js sort: {y: {value: \"-x\"}} ```\n\nWhen sorting the mark’s index, the **sort** option is instead one of:\n\n- a channel value definition for sorting given values in ascending order\n- a {value, order} object for sorting given values\n- a {channel, order} object for sorting the named channel’s values" + }, + "stroke": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke" + }, + "strokeDasharray": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dasharray][1]; a constant number indicating the length in pixels of alternating dashes and gaps, or a constant string of numbers separated by spaces or commas (_e.g._, *10 2* for dashes of 10 pixels separated by gaps of 2 pixels), or *none* (the default) for no dashing\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dasharray" + }, + "strokeDashoffset": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dashoffset][1]; a constant indicating the offset in pixels of the first dash along the stroke; defaults to zero.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dashoffset" + }, + "strokeLinecap": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linecap][1]; a constant specifying how to cap stroked paths, such as *butt*, *round*, or *square*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linecap" + }, + "strokeLinejoin": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linejoin][1]; a constant specifying how to join stroked paths, such as *bevel*, *miter*, *miter-clip*, or *round*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linejoin" + }, + "strokeMiterlimit": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-miterlimit][1]; a constant number specifying how to limit the length of *miter* joins on stroked paths.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-miterlimit" + }, + "strokeOpacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-opacity" + }, + "strokeWidth": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-width][1]; a constant number in pixels, or a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-width" + }, + "target": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [target][1]; a constant string specifying the target window (_e.g._,\n*_blank*) for clickable links; used in conjunction with the **href** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/target" + }, + "tip": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/TipPointer" + }, + { + "properties": { + "anchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The tip anchor specifies how to orient the tip box relative to its anchor position; it refers to the part of the tip box that is attached to the anchor point. For example, the *top-left* anchor places the top-left corner of tip box near the anchor position, hence placing the tip box below and to the right of the anchor position." + }, + "fontFamily": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font-family][1]; a constant; defaults to the plot’s font family, which is typically [*system-ui*][2].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-family [2]: https://drafts.csswg.org/css-fonts-4/#valdef-font-family-system-ui" + }, + "fontSize": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font size][1] in pixels; either a constant or a channel; defaults to the plot’s font size, which is typically 10. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-size" + }, + "fontStyle": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font style][1]; a constant; defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-style" + }, + "fontVariant": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font variant][1]; a constant; if the **text** channel contains numbers or dates, defaults to *tabular-nums* to facilitate comparing numbers; otherwise defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant" + }, + "fontWeight": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font weight][1]; a constant; defaults to the plot’s font weight, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight" + }, + "format": { + "additionalProperties": false, + "description": "How channel values are formatted for display. If a format is a string, it is interpreted as a (UTC) time format for temporal channels, and otherwise a number format.", + "properties": { + "ariaLabel": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fill": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fillOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fontSize": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fx": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fy": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "geometry": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "height": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "href": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "length": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "opacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "path": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "r": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "rotate": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "src": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "stroke": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeWidth": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "symbol": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "text": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "title": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "weight": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "width": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "z": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + } + }, + "type": "object" + }, + "frameAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The frame anchor specifies defaults for **x** and **y** based on the plot’s frame; it may be one of the four sides (*top*, *right*, *bottom*, *left*), one of the four corners (*top-left*, *top-right*, *bottom-right*,\n*bottom-left*), or the *middle* of the frame. For example, for tips distributed horizontally at the top of the frame:\n\n```js Plot.tip(data, {x: \"date\", frameAnchor: \"top\"}) ```" + }, + "lineHeight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line height in ems; defaults to 1. The line height affects the (typically vertical) separation between adjacent baselines of text, as well as the separation between the text and its anchor point." + }, + "lineWidth": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line width in ems (e.g., 10 for about 20 characters); defaults to infinity, disabling wrapping and clipping.\n\nIf **textOverflow** is null, lines will be wrapped at the specified length. If a line is split at a soft hyphen (\\xad), a hyphen (-) will be displayed at the end of the line. If **textOverflow** is not null, lines will be clipped according to the given strategy." + }, + "monospace": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, changes the default **fontFamily** to *monospace*, and uses simplified monospaced text metrics calculations." + }, + "pathFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The image filter for the tip’s box; defaults to a drop shadow." + }, + "pointer": { + "$ref": "#/definitions/TipPointer" + }, + "pointerSize": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The size of the tip’s pointer in pixels; defaults to 12." + }, + "preferredAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If an explicit tip anchor is not specified, an anchor is chosen automatically such that the tip fits within the plot’s frame; if the preferred anchor fits, it is chosen." + }, + "textAnchor": { + "anyOf": [ + { + "const": "start", + "type": "string" + }, + { + "const": "middle", + "type": "string" + }, + { + "const": "end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [text anchor][1] controls how text is aligned (typically horizontally) relative to its anchor point; it is one of *start*, *end*, or *middle*. If the frame anchor is *left*, *top-left*, or *bottom-left*, the default text anchor is *start*; if the frame anchor is *right*, *top-right*, or\n*bottom-right*, the default is *end*; otherwise it is *middle*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/text-anchor" + }, + "textOverflow": { + "anyOf": [ + { + "type": "null" + }, + { + "const": "clip", + "type": "string" + }, + { + "const": "ellipsis", + "type": "string" + }, + { + "const": "clip-start", + "type": "string" + }, + { + "const": "clip-end", + "type": "string" + }, + { + "const": "ellipsis-start", + "type": "string" + }, + { + "const": "ellipsis-middle", + "type": "string" + }, + { + "const": "ellipsis-end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How truncate (or wrap) lines of text longer than the given **lineWidth**; one of:\n\n- null (default) - preserve overflowing characters (and wrap if needed)\n- *clip* or *clip-end* - remove characters from the end\n- *clip-start* - remove characters from the start\n- *ellipsis* or *ellipsis-end* - replace characters from the end with an ellipsis (…)\n- *ellipsis-start* - replace characters from the start with an ellipsis (…)\n- *ellipsis-middle* - replace characters from the middle with an ellipsis (…)\n\nIf no **title** was specified, if text requires truncation, a title containing the non-truncated text will be implicitly added." + }, + "textPadding": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The padding around the text in pixels; defaults to 8." + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + } + }, + "type": "object" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to generate a tooltip for this mark, and any tip options." + }, + "title": { + "$ref": "#/definitions/ChannelValue", + "description": "The title; a channel specifying accessible, short textual descriptions as strings (possibly with newlines). If the tip option is specified, the title will be displayed with an interactive tooltip instead of using the SVG [title element][1].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/title" + } + }, + "required": [ + "data", + "mark" + ], + "type": "object" + }, + "GeoJSON": { + "additionalProperties": false, + "properties": { + "geojson": { + "anyOf": [ + { + "description": "A transform argument.", + "type": [ + "string", + "number", + "boolean" + ] + }, + { + "items": { + "description": "A transform argument.", + "type": [ + "string", + "number", + "boolean" + ] + }, + "maxItems": 1, + "minItems": 1, + "type": "array" + } + ], + "description": "Compute a GeoJSON-formatted string from geometry-typed data. This transform requires the DuckDB `spatial` extension." + } + }, + "required": [ + "geojson" + ], + "type": "object" + }, + "Graticule": { + "additionalProperties": false, + "description": "The graticule mark.", + "properties": { + "ariaDescription": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-description][1]; a constant textual description.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-description" + }, + "ariaHidden": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-hidden][1] state; a constant indicating whether the element is exposed to an accessibility API.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-hidden" + }, + "ariaLabel": { + "$ref": "#/definitions/ChannelValue", + "description": "The [aria-label][1]; a channel specifying short textual labels representing the value in the accessibility tree.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-label" + }, + "clip": { + "anyOf": [ + { + "const": "frame", + "type": "string" + }, + { + "const": "sphere", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to clip the mark; one of:\n\n- *frame* or true - clip to the plot’s frame (inner area)\n- *sphere* - clip to the projected sphere (*e.g.*, front hemisphere)\n- null or false - do not clip\n\nThe *sphere* clip option requires a geographic projection." + }, + "dx": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The horizontal offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "dy": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The vertical offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "facet": { + "anyOf": [ + { + "const": "auto", + "type": "string" + }, + { + "const": "include", + "type": "string" + }, + { + "const": "exclude", + "type": "string" + }, + { + "const": "super", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to enable or disable faceting; one of:\n\n- *auto* (default) - automatically determine if this mark should be faceted\n- *include* (or true) - draw the subset of the mark’s data in the current facet\n- *exclude* - draw the subset of the mark’s data *not* in the current facet\n- *super* - draw this mark in a single frame that covers all facets\n- null (or false) - repeat this mark’s data across all facets (*i.e.*, no faceting)\n\nWhen a mark uses *super* faceting, it is not allowed to use position scales (*x*, *y*, *fx*, or *fy*); *super* faceting is intended for decorations, such as labels and legends.\n\nWhen top-level faceting is used, the default *auto* setting is equivalent to *include* when the mark data is strictly equal to the top-level facet data; otherwise it is equivalent to null. When the *include* or *exclude* facet mode is chosen, the mark data must be parallel to the top-level facet data: the data must have the same length and order. If the data are not parallel, then the wrong data may be shown in each facet. The default\n*auto* therefore requires strict equality (`===`) for safety, and using the facet data as mark data is recommended when using the *exclude* facet mode. (To construct parallel data safely, consider using [*array*.map][1] on the facet data.)\n\nWhen mark-level faceting is used, the default *auto* setting is equivalent to *include*: the mark will be faceted if either the **fx** or **fy** channel option (or both) is specified. The null or false option will disable faceting, while *exclude* draws the subset of the mark’s data *not* in the current facet.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map" + }, + "facetAnchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "right", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "const": "left", + "type": "string" + }, + { + "const": "top-left", + "type": "string" + }, + { + "const": "top-right", + "type": "string" + }, + { + "const": "bottom-left", + "type": "string" + }, + { + "const": "bottom-right", + "type": "string" + }, + { + "const": "top-empty", + "type": "string" + }, + { + "const": "right-empty", + "type": "string" + }, + { + "const": "bottom-empty", + "type": "string" + }, + { + "const": "left-empty", + "type": "string" + }, + { + "const": "empty", + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to place the mark with respect to facets; one of:\n\n- null (default for most marks) - display the mark in each non-empty facet\n- *top*, *right*, *bottom*, or *left* - display the mark only in facets on the given side\n- *top-empty*, *right-empty*, *bottom-empty*, or *left-empty* (default for axis marks) - display the mark only in facets that have empty space on the given side: either the margin, or an empty facet\n- *empty* - display the mark in empty facets only" + }, + "fill": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill" + }, + "fillOpacity": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill-opacity][1]; a constant number between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill-opacity" + }, + "filter": { + "$ref": "#/definitions/ChannelValue", + "description": "Applies a transform to filter the mark’s index according to the given channel values; only truthy values are retained.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "fx": { + "$ref": "#/definitions/ChannelValue", + "description": "The horizontal facet position channel, for mark-level faceting, bound to the *fx* scale." + }, + "fy": { + "$ref": "#/definitions/ChannelValue", + "description": "The vertical facet position channel, for mark-level faceting, bound to the\n*fy* scale." + }, + "href": { + "$ref": "#/definitions/ChannelValue", + "description": "The [href][1]; a channel specifying URLs for clickable links. May be used in conjunction with the **target** option to open links in another window.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/href" + }, + "imageFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A CSS [filter][1]; a constant string used to adjust the rendering of images, such as *blur(5px)*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/filter" + }, + "margin": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four mark margins: **marginTop**,\n**marginRight**, **marginBottom**, and **marginLeft**; typically defaults to 0, except for axis marks." + }, + "marginBottom": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s bottom margin; the minimum distance in pixels between the bottom edges of the inner and outer plot area." + }, + "marginLeft": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s left margin; the minimum distance in pixels between the left edges of the inner and outer plot area." + }, + "marginRight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s right margin; the minimum distance in pixels between the right edges of the mark’s inner and outer plot area." + }, + "marginTop": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s top margin; the minimum distance in pixels between the top edges of the inner and outer plot area." + }, + "mark": { + "const": "graticule", + "description": "A geo mark whose *data* is a 10° global graticule. (For use with a spherical **projection** only.)", + "type": "string" + }, + "mixBlendMode": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [mix-blend-mode][1]; a constant string specifying how to blend content such as *multiply*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode" + }, + "opacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally. For faster rendering, prefer the **strokeOpacity** or **fillOpacity** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/opacity" + }, + "paintOrder": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [paint-order][1]; a constant string specifying the order in which the\n**fill**, **stroke**, and any markers are drawn; defaults to *normal*, which draws the fill, then stroke, then markers; defaults to *stroke* for the text mark to create a “halo” around text to improve legibility.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/paint-order" + }, + "pointerEvents": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [pointer-events][1] property; a constant string such as *none*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/pointer-events" + }, + "reverse": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Applies a transform to reverse the order of the mark’s index, say for reverse input order." + }, + "select": { + "$ref": "#/definitions/SelectFilter", + "description": "Applies a filter transform after data is loaded to highlight selected values only. For example, `first` and `last` select the first or last values of series only (using the *z* channel to separate series). Meanwhile, `nearestX` and `nearestY` select the point nearest to the pointer along the *x* or *y* channel dimension. Unlike Mosaic selections, a mark level *select* is internal to the mark only, and does not populate a param or selection value to be shared across clients.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "shapeRendering": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [shape-rendering][1]; a constant string such as *crispEdges*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/shape-rendering" + }, + "sort": { + "anyOf": [ + { + "$ref": "#/definitions/SortOrder" + }, + { + "$ref": "#/definitions/ChannelDomainSort" + } + ], + "description": "Either applies a transform to sort the mark’s index by the specified channel values, or imputes ordinal scale domains from this mark’s channels.\n\nWhen imputing ordinal scale domains from channel values, the **sort** option is an object whose keys are ordinal scale names such as *x* or *fx*, and whose values are channel names such as *y*, *y1*, or *y2*. For example, to impute the *y* scale’s domain from the associated *x* channel values in ascending order:\n\n```js sort: {y: \"x\"} ```\n\nFor different sort options for different scales, replace the channel name with a *value* object and per-scale options:\n\n```js sort: {y: {value: \"-x\"}} ```\n\nWhen sorting the mark’s index, the **sort** option is instead one of:\n\n- a channel value definition for sorting given values in ascending order\n- a {value, order} object for sorting given values\n- a {channel, order} object for sorting the named channel’s values" + }, + "stroke": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke" + }, + "strokeDasharray": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dasharray][1]; a constant number indicating the length in pixels of alternating dashes and gaps, or a constant string of numbers separated by spaces or commas (_e.g._, *10 2* for dashes of 10 pixels separated by gaps of 2 pixels), or *none* (the default) for no dashing\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dasharray" + }, + "strokeDashoffset": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dashoffset][1]; a constant indicating the offset in pixels of the first dash along the stroke; defaults to zero.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dashoffset" + }, + "strokeLinecap": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linecap][1]; a constant specifying how to cap stroked paths, such as *butt*, *round*, or *square*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linecap" + }, + "strokeLinejoin": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linejoin][1]; a constant specifying how to join stroked paths, such as *bevel*, *miter*, *miter-clip*, or *round*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linejoin" + }, + "strokeMiterlimit": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-miterlimit][1]; a constant number specifying how to limit the length of *miter* joins on stroked paths.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-miterlimit" + }, + "strokeOpacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-opacity" + }, + "strokeWidth": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-width][1]; a constant number in pixels, or a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-width" + }, + "target": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [target][1]; a constant string specifying the target window (_e.g._,\n*_blank*) for clickable links; used in conjunction with the **href** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/target" + }, + "tip": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/TipPointer" + }, + { + "properties": { + "anchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The tip anchor specifies how to orient the tip box relative to its anchor position; it refers to the part of the tip box that is attached to the anchor point. For example, the *top-left* anchor places the top-left corner of tip box near the anchor position, hence placing the tip box below and to the right of the anchor position." + }, + "fontFamily": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font-family][1]; a constant; defaults to the plot’s font family, which is typically [*system-ui*][2].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-family [2]: https://drafts.csswg.org/css-fonts-4/#valdef-font-family-system-ui" + }, + "fontSize": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font size][1] in pixels; either a constant or a channel; defaults to the plot’s font size, which is typically 10. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-size" + }, + "fontStyle": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font style][1]; a constant; defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-style" + }, + "fontVariant": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font variant][1]; a constant; if the **text** channel contains numbers or dates, defaults to *tabular-nums* to facilitate comparing numbers; otherwise defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant" + }, + "fontWeight": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font weight][1]; a constant; defaults to the plot’s font weight, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight" + }, + "format": { + "additionalProperties": false, + "description": "How channel values are formatted for display. If a format is a string, it is interpreted as a (UTC) time format for temporal channels, and otherwise a number format.", + "properties": { + "ariaLabel": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fill": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fillOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fontSize": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fx": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fy": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "geometry": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "height": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "href": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "length": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "opacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "path": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "r": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "rotate": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "src": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "stroke": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeWidth": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "symbol": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "text": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "title": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "weight": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "width": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "z": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + } + }, + "type": "object" + }, + "frameAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The frame anchor specifies defaults for **x** and **y** based on the plot’s frame; it may be one of the four sides (*top*, *right*, *bottom*, *left*), one of the four corners (*top-left*, *top-right*, *bottom-right*,\n*bottom-left*), or the *middle* of the frame. For example, for tips distributed horizontally at the top of the frame:\n\n```js Plot.tip(data, {x: \"date\", frameAnchor: \"top\"}) ```" + }, + "lineHeight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line height in ems; defaults to 1. The line height affects the (typically vertical) separation between adjacent baselines of text, as well as the separation between the text and its anchor point." + }, + "lineWidth": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line width in ems (e.g., 10 for about 20 characters); defaults to infinity, disabling wrapping and clipping.\n\nIf **textOverflow** is null, lines will be wrapped at the specified length. If a line is split at a soft hyphen (\\xad), a hyphen (-) will be displayed at the end of the line. If **textOverflow** is not null, lines will be clipped according to the given strategy." + }, + "monospace": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, changes the default **fontFamily** to *monospace*, and uses simplified monospaced text metrics calculations." + }, + "pathFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The image filter for the tip’s box; defaults to a drop shadow." + }, + "pointer": { + "$ref": "#/definitions/TipPointer" + }, + "pointerSize": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The size of the tip’s pointer in pixels; defaults to 12." + }, + "preferredAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If an explicit tip anchor is not specified, an anchor is chosen automatically such that the tip fits within the plot’s frame; if the preferred anchor fits, it is chosen." + }, + "textAnchor": { + "anyOf": [ + { + "const": "start", + "type": "string" + }, + { + "const": "middle", + "type": "string" + }, + { + "const": "end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [text anchor][1] controls how text is aligned (typically horizontally) relative to its anchor point; it is one of *start*, *end*, or *middle*. If the frame anchor is *left*, *top-left*, or *bottom-left*, the default text anchor is *start*; if the frame anchor is *right*, *top-right*, or\n*bottom-right*, the default is *end*; otherwise it is *middle*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/text-anchor" + }, + "textOverflow": { + "anyOf": [ + { + "type": "null" + }, + { + "const": "clip", + "type": "string" + }, + { + "const": "ellipsis", + "type": "string" + }, + { + "const": "clip-start", + "type": "string" + }, + { + "const": "clip-end", + "type": "string" + }, + { + "const": "ellipsis-start", + "type": "string" + }, + { + "const": "ellipsis-middle", + "type": "string" + }, + { + "const": "ellipsis-end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How truncate (or wrap) lines of text longer than the given **lineWidth**; one of:\n\n- null (default) - preserve overflowing characters (and wrap if needed)\n- *clip* or *clip-end* - remove characters from the end\n- *clip-start* - remove characters from the start\n- *ellipsis* or *ellipsis-end* - replace characters from the end with an ellipsis (…)\n- *ellipsis-start* - replace characters from the start with an ellipsis (…)\n- *ellipsis-middle* - replace characters from the middle with an ellipsis (…)\n\nIf no **title** was specified, if text requires truncation, a title containing the non-truncated text will be implicitly added." + }, + "textPadding": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The padding around the text in pixels; defaults to 8." + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + } + }, + "type": "object" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to generate a tooltip for this mark, and any tip options." + }, + "title": { + "$ref": "#/definitions/ChannelValue", + "description": "The title; a channel specifying accessible, short textual descriptions as strings (possibly with newlines). If the tip option is specified, the title will be displayed with an interactive tooltip instead of using the SVG [title element][1].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/title" + } + }, + "required": [ + "mark" + ], + "type": "object" + }, + "GridFx": { + "additionalProperties": false, + "description": "The gridFx mark.", + "properties": { + "anchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "right", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "const": "left", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The side of the frame on which to place the axis: *top* or *bottom* for horizontal axes (axisX and axisFx) and their associated vertical grids (gridX and gridFx), or *left* or *right* for vertical axes (axisY and axisFY) and their associated horizontal grids (gridY and gridFy).\n\nThe default **anchor** depends on the associated scale:\n\n- *x* - *bottom*\n- *y* - *left*\n- *fx* - *top* if there is a *bottom* *x* axis, and otherwise *bottom*\n- *fy* - *right* if there is a *left* *y* axis, and otherwise *right*\n\nFor grids, the **anchor** also affects the extent of grid lines when the opposite dimension is specified (**x** for gridY and **y** for gridX)." + }, + "ariaDescription": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-description][1]; a constant textual description.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-description" + }, + "ariaHidden": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-hidden][1] state; a constant indicating whether the element is exposed to an accessibility API.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-hidden" + }, + "ariaLabel": { + "$ref": "#/definitions/ChannelValue", + "description": "The [aria-label][1]; a channel specifying short textual labels representing the value in the accessibility tree.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-label" + }, + "clip": { + "anyOf": [ + { + "const": "frame", + "type": "string" + }, + { + "const": "sphere", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to clip the mark; one of:\n\n- *frame* or true - clip to the plot’s frame (inner area)\n- *sphere* - clip to the projected sphere (*e.g.*, front hemisphere)\n- null or false - do not clip\n\nThe *sphere* clip option requires a geographic projection." + }, + "color": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A shorthand for setting both **fill** and **stroke**; affects the stroke of tick vectors and grid rules, and the fill of tick texts and axis label texts; defaults to *currentColor*." + }, + "dx": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The horizontal offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "dy": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The vertical offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "facet": { + "anyOf": [ + { + "const": "auto", + "type": "string" + }, + { + "const": "include", + "type": "string" + }, + { + "const": "exclude", + "type": "string" + }, + { + "const": "super", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to enable or disable faceting; one of:\n\n- *auto* (default) - automatically determine if this mark should be faceted\n- *include* (or true) - draw the subset of the mark’s data in the current facet\n- *exclude* - draw the subset of the mark’s data *not* in the current facet\n- *super* - draw this mark in a single frame that covers all facets\n- null (or false) - repeat this mark’s data across all facets (*i.e.*, no faceting)\n\nWhen a mark uses *super* faceting, it is not allowed to use position scales (*x*, *y*, *fx*, or *fy*); *super* faceting is intended for decorations, such as labels and legends.\n\nWhen top-level faceting is used, the default *auto* setting is equivalent to *include* when the mark data is strictly equal to the top-level facet data; otherwise it is equivalent to null. When the *include* or *exclude* facet mode is chosen, the mark data must be parallel to the top-level facet data: the data must have the same length and order. If the data are not parallel, then the wrong data may be shown in each facet. The default\n*auto* therefore requires strict equality (`===`) for safety, and using the facet data as mark data is recommended when using the *exclude* facet mode. (To construct parallel data safely, consider using [*array*.map][1] on the facet data.)\n\nWhen mark-level faceting is used, the default *auto* setting is equivalent to *include*: the mark will be faceted if either the **fx** or **fy** channel option (or both) is specified. The null or false option will disable faceting, while *exclude* draws the subset of the mark’s data *not* in the current facet.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map" + }, + "facetAnchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "right", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "const": "left", + "type": "string" + }, + { + "const": "top-left", + "type": "string" + }, + { + "const": "top-right", + "type": "string" + }, + { + "const": "bottom-left", + "type": "string" + }, + { + "const": "bottom-right", + "type": "string" + }, + { + "const": "top-empty", + "type": "string" + }, + { + "const": "right-empty", + "type": "string" + }, + { + "const": "bottom-empty", + "type": "string" + }, + { + "const": "left-empty", + "type": "string" + }, + { + "const": "empty", + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to place the mark with respect to facets; one of:\n\n- null (default for most marks) - display the mark in each non-empty facet\n- *top*, *right*, *bottom*, or *left* - display the mark only in facets on the given side\n- *top-empty*, *right-empty*, *bottom-empty*, or *left-empty* (default for axis marks) - display the mark only in facets that have empty space on the given side: either the margin, or an empty facet\n- *empty* - display the mark in empty facets only" + }, + "fill": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill" + }, + "fillOpacity": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill-opacity][1]; a constant number between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill-opacity" + }, + "filter": { + "$ref": "#/definitions/ChannelValue", + "description": "Applies a transform to filter the mark’s index according to the given channel values; only truthy values are retained.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "fx": { + "$ref": "#/definitions/ChannelValue", + "description": "The horizontal facet position channel, for mark-level faceting, bound to the *fx* scale." + }, + "fy": { + "$ref": "#/definitions/ChannelValue", + "description": "The vertical facet position channel, for mark-level faceting, bound to the\n*fy* scale." + }, + "href": { + "$ref": "#/definitions/ChannelValue", + "description": "The [href][1]; a channel specifying URLs for clickable links. May be used in conjunction with the **target** option to open links in another window.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/href" + }, + "imageFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A CSS [filter][1]; a constant string used to adjust the rendering of images, such as *blur(5px)*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/filter" + }, + "inset": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four insets: **insetTop**,\n**insetRight**, **insetBottom**, and **insetLeft**. All insets typically default to zero, though not always (say when using bin transform). A positive inset reduces effective area, while a negative inset increases it." + }, + "insetBottom": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Insets the bottom edge by the specified number of pixels. A positive value insets towards the top edge (reducing effective area), while a negative value insets away from the top edge (increasing it)." + }, + "insetTop": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Insets the top edge by the specified number of pixels. A positive value insets towards the bottom edge (reducing effective area), while a negative value insets away from the bottom edge (increasing it)." + }, + "interval": { + "anyOf": [ + { + "$ref": "#/definitions/Interval" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Enforces uniformity for data at regular intervals, such as integer values or daily samples. The interval may be one of:\n\n- a named time interval such as *day* (for date intervals)\n- a number (for number intervals), defining intervals at integer multiples of *n*\n\nThis option sets the internal transform to the given interval’s\n*interval*.floor function. In addition, the default **domain** will align with interval boundaries." + }, + "margin": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four mark margins: **marginTop**,\n**marginRight**, **marginBottom**, and **marginLeft**; typically defaults to 0, except for axis marks." + }, + "marginBottom": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s bottom margin; the minimum distance in pixels between the bottom edges of the inner and outer plot area." + }, + "marginLeft": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s left margin; the minimum distance in pixels between the left edges of the inner and outer plot area." + }, + "marginRight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s right margin; the minimum distance in pixels between the right edges of the mark’s inner and outer plot area." + }, + "marginTop": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s top margin; the minimum distance in pixels between the top edges of the inner and outer plot area." + }, + "mark": { + "const": "gridFx", + "description": "A horizontally-positioned ruleX mark (a vertical line, |) that renders a grid for the *fx* scale. The data defaults to the *fx* scale’s domain; if desired, use the **ticks** option.", + "type": "string" + }, + "marker": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for markerStart, markerMid, and markerEnd; one of:\n\n- a marker name such as *arrow* or *circle*\n- *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*" + }, + "markerEnd": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The marker for the ending point of a line segment; one of:\n\n- a marker name such as *arrow* or *circle*\n* *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*" + }, + "markerMid": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The marker for any middle (interior) points of a line segment. If the line segment only has a start and end point, this option has no effect. One of:\n\n- a marker name such as *arrow* or *circle*\n* *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*\n* a function - a custom marker function; see below" + }, + "markerStart": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The marker for the starting point of a line segment; one of:\n\n- a marker name such as *arrow* or *circle*\n* *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*" + }, + "mixBlendMode": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [mix-blend-mode][1]; a constant string specifying how to blend content such as *multiply*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode" + }, + "opacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "A shorthand for setting both **fillOpacity** and **strokeOpacity**; affects the stroke opacity of tick vectors and grid rules, and the fill opacity of tick texts and axis label texts; defaults to 1 for axes and 0.1 for grids." + }, + "paintOrder": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [paint-order][1]; a constant string specifying the order in which the\n**fill**, **stroke**, and any markers are drawn; defaults to *normal*, which draws the fill, then stroke, then markers; defaults to *stroke* for the text mark to create a “halo” around text to improve legibility.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/paint-order" + }, + "pointerEvents": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [pointer-events][1] property; a constant string such as *none*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/pointer-events" + }, + "reverse": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Applies a transform to reverse the order of the mark’s index, say for reverse input order." + }, + "select": { + "$ref": "#/definitions/SelectFilter", + "description": "Applies a filter transform after data is loaded to highlight selected values only. For example, `first` and `last` select the first or last values of series only (using the *z* channel to separate series). Meanwhile, `nearestX` and `nearestY` select the point nearest to the pointer along the *x* or *y* channel dimension. Unlike Mosaic selections, a mark level *select* is internal to the mark only, and does not populate a param or selection value to be shared across clients.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "shapeRendering": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [shape-rendering][1]; a constant string such as *crispEdges*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/shape-rendering" + }, + "sort": { + "anyOf": [ + { + "$ref": "#/definitions/SortOrder" + }, + { + "$ref": "#/definitions/ChannelDomainSort" + } + ], + "description": "Either applies a transform to sort the mark’s index by the specified channel values, or imputes ordinal scale domains from this mark’s channels.\n\nWhen imputing ordinal scale domains from channel values, the **sort** option is an object whose keys are ordinal scale names such as *x* or *fx*, and whose values are channel names such as *y*, *y1*, or *y2*. For example, to impute the *y* scale’s domain from the associated *x* channel values in ascending order:\n\n```js sort: {y: \"x\"} ```\n\nFor different sort options for different scales, replace the channel name with a *value* object and per-scale options:\n\n```js sort: {y: {value: \"-x\"}} ```\n\nWhen sorting the mark’s index, the **sort** option is instead one of:\n\n- a channel value definition for sorting given values in ascending order\n- a {value, order} object for sorting given values\n- a {channel, order} object for sorting the named channel’s values" + }, + "stroke": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke" + }, + "strokeDasharray": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dasharray][1]; a constant number indicating the length in pixels of alternating dashes and gaps, or a constant string of numbers separated by spaces or commas (_e.g._, *10 2* for dashes of 10 pixels separated by gaps of 2 pixels), or *none* (the default) for no dashing\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dasharray" + }, + "strokeDashoffset": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dashoffset][1]; a constant indicating the offset in pixels of the first dash along the stroke; defaults to zero.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dashoffset" + }, + "strokeLinecap": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linecap][1]; a constant specifying how to cap stroked paths, such as *butt*, *round*, or *square*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linecap" + }, + "strokeLinejoin": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linejoin][1]; a constant specifying how to join stroked paths, such as *bevel*, *miter*, *miter-clip*, or *round*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linejoin" + }, + "strokeMiterlimit": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-miterlimit][1]; a constant number specifying how to limit the length of *miter* joins on stroked paths.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-miterlimit" + }, + "strokeOpacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-opacity" + }, + "strokeWidth": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-width][1]; a constant number in pixels, or a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-width" + }, + "target": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [target][1]; a constant string specifying the target window (_e.g._,\n*_blank*) for clickable links; used in conjunction with the **href** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/target" + }, + "tickSpacing": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The desired approximate spacing between adjacent axis ticks, affecting the default **ticks**; defaults to 80 pixels for *x* and *fx*, and 35 pixels for *y* and *fy*." + }, + "ticks": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/Interval" + }, + { + "items": {}, + "type": "array" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The desired approximate number of axis ticks, or an explicit array of tick values, or an interval such as *day* or *month*." + }, + "tip": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/TipPointer" + }, + { + "properties": { + "anchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The tip anchor specifies how to orient the tip box relative to its anchor position; it refers to the part of the tip box that is attached to the anchor point. For example, the *top-left* anchor places the top-left corner of tip box near the anchor position, hence placing the tip box below and to the right of the anchor position." + }, + "fontFamily": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font-family][1]; a constant; defaults to the plot’s font family, which is typically [*system-ui*][2].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-family [2]: https://drafts.csswg.org/css-fonts-4/#valdef-font-family-system-ui" + }, + "fontSize": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font size][1] in pixels; either a constant or a channel; defaults to the plot’s font size, which is typically 10. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-size" + }, + "fontStyle": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font style][1]; a constant; defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-style" + }, + "fontVariant": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font variant][1]; a constant; if the **text** channel contains numbers or dates, defaults to *tabular-nums* to facilitate comparing numbers; otherwise defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant" + }, + "fontWeight": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font weight][1]; a constant; defaults to the plot’s font weight, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight" + }, + "format": { + "additionalProperties": false, + "description": "How channel values are formatted for display. If a format is a string, it is interpreted as a (UTC) time format for temporal channels, and otherwise a number format.", + "properties": { + "ariaLabel": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fill": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fillOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fontSize": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fx": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fy": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "geometry": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "height": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "href": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "length": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "opacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "path": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "r": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "rotate": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "src": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "stroke": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeWidth": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "symbol": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "text": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "title": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "weight": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "width": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "z": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + } + }, + "type": "object" + }, + "frameAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The frame anchor specifies defaults for **x** and **y** based on the plot’s frame; it may be one of the four sides (*top*, *right*, *bottom*, *left*), one of the four corners (*top-left*, *top-right*, *bottom-right*,\n*bottom-left*), or the *middle* of the frame. For example, for tips distributed horizontally at the top of the frame:\n\n```js Plot.tip(data, {x: \"date\", frameAnchor: \"top\"}) ```" + }, + "lineHeight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line height in ems; defaults to 1. The line height affects the (typically vertical) separation between adjacent baselines of text, as well as the separation between the text and its anchor point." + }, + "lineWidth": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line width in ems (e.g., 10 for about 20 characters); defaults to infinity, disabling wrapping and clipping.\n\nIf **textOverflow** is null, lines will be wrapped at the specified length. If a line is split at a soft hyphen (\\xad), a hyphen (-) will be displayed at the end of the line. If **textOverflow** is not null, lines will be clipped according to the given strategy." + }, + "monospace": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, changes the default **fontFamily** to *monospace*, and uses simplified monospaced text metrics calculations." + }, + "pathFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The image filter for the tip’s box; defaults to a drop shadow." + }, + "pointer": { + "$ref": "#/definitions/TipPointer" + }, + "pointerSize": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The size of the tip’s pointer in pixels; defaults to 12." + }, + "preferredAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If an explicit tip anchor is not specified, an anchor is chosen automatically such that the tip fits within the plot’s frame; if the preferred anchor fits, it is chosen." + }, + "textAnchor": { + "anyOf": [ + { + "const": "start", + "type": "string" + }, + { + "const": "middle", + "type": "string" + }, + { + "const": "end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [text anchor][1] controls how text is aligned (typically horizontally) relative to its anchor point; it is one of *start*, *end*, or *middle*. If the frame anchor is *left*, *top-left*, or *bottom-left*, the default text anchor is *start*; if the frame anchor is *right*, *top-right*, or\n*bottom-right*, the default is *end*; otherwise it is *middle*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/text-anchor" + }, + "textOverflow": { + "anyOf": [ + { + "type": "null" + }, + { + "const": "clip", + "type": "string" + }, + { + "const": "ellipsis", + "type": "string" + }, + { + "const": "clip-start", + "type": "string" + }, + { + "const": "clip-end", + "type": "string" + }, + { + "const": "ellipsis-start", + "type": "string" + }, + { + "const": "ellipsis-middle", + "type": "string" + }, + { + "const": "ellipsis-end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How truncate (or wrap) lines of text longer than the given **lineWidth**; one of:\n\n- null (default) - preserve overflowing characters (and wrap if needed)\n- *clip* or *clip-end* - remove characters from the end\n- *clip-start* - remove characters from the start\n- *ellipsis* or *ellipsis-end* - replace characters from the end with an ellipsis (…)\n- *ellipsis-start* - replace characters from the start with an ellipsis (…)\n- *ellipsis-middle* - replace characters from the middle with an ellipsis (…)\n\nIf no **title** was specified, if text requires truncation, a title containing the non-truncated text will be implicitly added." + }, + "textPadding": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The padding around the text in pixels; defaults to 8." + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + } + }, + "type": "object" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to generate a tooltip for this mark, and any tip options." + }, + "title": { + "$ref": "#/definitions/ChannelValue", + "description": "The title; a channel specifying accessible, short textual descriptions as strings (possibly with newlines). If the tip option is specified, the title will be displayed with an interactive tooltip instead of using the SVG [title element][1].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/title" + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position of the tick; an optional channel bound to the *x* scale. If not specified, the rule will be horizontally centered in the plot’s frame." + }, + "y": { + "$ref": "#/definitions/ChannelValueIntervalSpec", + "description": "Shorthand for specifying both the primary and secondary vertical position of the tick as the bounds of the containing interval; can only be used in conjunction with the **interval** option." + }, + "y1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The primary (starting, often bottom) vertical position of the tick; a channel bound to the *y* scale.\n\nIf *y* represents ordinal values, use a tickX mark instead." + }, + "y2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The secondary (ending, often top) vertical position of the tick; a channel bound to the *y* scale.\n\nIf *y* represents ordinal values, use a tickX mark instead." + } + }, + "required": [ + "mark" + ], + "type": "object" + }, + "GridFy": { + "additionalProperties": false, + "description": "The gridFy mark.", + "properties": { + "anchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "right", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "const": "left", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The side of the frame on which to place the axis: *top* or *bottom* for horizontal axes (axisX and axisFx) and their associated vertical grids (gridX and gridFx), or *left* or *right* for vertical axes (axisY and axisFY) and their associated horizontal grids (gridY and gridFy).\n\nThe default **anchor** depends on the associated scale:\n\n- *x* - *bottom*\n- *y* - *left*\n- *fx* - *top* if there is a *bottom* *x* axis, and otherwise *bottom*\n- *fy* - *right* if there is a *left* *y* axis, and otherwise *right*\n\nFor grids, the **anchor** also affects the extent of grid lines when the opposite dimension is specified (**x** for gridY and **y** for gridX)." + }, + "ariaDescription": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-description][1]; a constant textual description.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-description" + }, + "ariaHidden": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-hidden][1] state; a constant indicating whether the element is exposed to an accessibility API.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-hidden" + }, + "ariaLabel": { + "$ref": "#/definitions/ChannelValue", + "description": "The [aria-label][1]; a channel specifying short textual labels representing the value in the accessibility tree.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-label" + }, + "clip": { + "anyOf": [ + { + "const": "frame", + "type": "string" + }, + { + "const": "sphere", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to clip the mark; one of:\n\n- *frame* or true - clip to the plot’s frame (inner area)\n- *sphere* - clip to the projected sphere (*e.g.*, front hemisphere)\n- null or false - do not clip\n\nThe *sphere* clip option requires a geographic projection." + }, + "color": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A shorthand for setting both **fill** and **stroke**; affects the stroke of tick vectors and grid rules, and the fill of tick texts and axis label texts; defaults to *currentColor*." + }, + "dx": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The horizontal offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "dy": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The vertical offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "facet": { + "anyOf": [ + { + "const": "auto", + "type": "string" + }, + { + "const": "include", + "type": "string" + }, + { + "const": "exclude", + "type": "string" + }, + { + "const": "super", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to enable or disable faceting; one of:\n\n- *auto* (default) - automatically determine if this mark should be faceted\n- *include* (or true) - draw the subset of the mark’s data in the current facet\n- *exclude* - draw the subset of the mark’s data *not* in the current facet\n- *super* - draw this mark in a single frame that covers all facets\n- null (or false) - repeat this mark’s data across all facets (*i.e.*, no faceting)\n\nWhen a mark uses *super* faceting, it is not allowed to use position scales (*x*, *y*, *fx*, or *fy*); *super* faceting is intended for decorations, such as labels and legends.\n\nWhen top-level faceting is used, the default *auto* setting is equivalent to *include* when the mark data is strictly equal to the top-level facet data; otherwise it is equivalent to null. When the *include* or *exclude* facet mode is chosen, the mark data must be parallel to the top-level facet data: the data must have the same length and order. If the data are not parallel, then the wrong data may be shown in each facet. The default\n*auto* therefore requires strict equality (`===`) for safety, and using the facet data as mark data is recommended when using the *exclude* facet mode. (To construct parallel data safely, consider using [*array*.map][1] on the facet data.)\n\nWhen mark-level faceting is used, the default *auto* setting is equivalent to *include*: the mark will be faceted if either the **fx** or **fy** channel option (or both) is specified. The null or false option will disable faceting, while *exclude* draws the subset of the mark’s data *not* in the current facet.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map" + }, + "facetAnchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "right", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "const": "left", + "type": "string" + }, + { + "const": "top-left", + "type": "string" + }, + { + "const": "top-right", + "type": "string" + }, + { + "const": "bottom-left", + "type": "string" + }, + { + "const": "bottom-right", + "type": "string" + }, + { + "const": "top-empty", + "type": "string" + }, + { + "const": "right-empty", + "type": "string" + }, + { + "const": "bottom-empty", + "type": "string" + }, + { + "const": "left-empty", + "type": "string" + }, + { + "const": "empty", + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to place the mark with respect to facets; one of:\n\n- null (default for most marks) - display the mark in each non-empty facet\n- *top*, *right*, *bottom*, or *left* - display the mark only in facets on the given side\n- *top-empty*, *right-empty*, *bottom-empty*, or *left-empty* (default for axis marks) - display the mark only in facets that have empty space on the given side: either the margin, or an empty facet\n- *empty* - display the mark in empty facets only" + }, + "fill": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill" + }, + "fillOpacity": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill-opacity][1]; a constant number between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill-opacity" + }, + "filter": { + "$ref": "#/definitions/ChannelValue", + "description": "Applies a transform to filter the mark’s index according to the given channel values; only truthy values are retained.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "fx": { + "$ref": "#/definitions/ChannelValue", + "description": "The horizontal facet position channel, for mark-level faceting, bound to the *fx* scale." + }, + "fy": { + "$ref": "#/definitions/ChannelValue", + "description": "The vertical facet position channel, for mark-level faceting, bound to the\n*fy* scale." + }, + "href": { + "$ref": "#/definitions/ChannelValue", + "description": "The [href][1]; a channel specifying URLs for clickable links. May be used in conjunction with the **target** option to open links in another window.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/href" + }, + "imageFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A CSS [filter][1]; a constant string used to adjust the rendering of images, such as *blur(5px)*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/filter" + }, + "inset": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four insets: **insetTop**,\n**insetRight**, **insetBottom**, and **insetLeft**. All insets typically default to zero, though not always (say when using bin transform). A positive inset reduces effective area, while a negative inset increases it." + }, + "insetLeft": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Insets the left edge by the specified number of pixels. A positive value insets towards the right edge (reducing effective area), while a negative value insets away from the right edge (increasing it)." + }, + "insetRight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Insets the right edge by the specified number of pixels. A positive value insets towards the left edge (reducing effective area), while a negative value insets away from the left edge (increasing it)." + }, + "interval": { + "anyOf": [ + { + "$ref": "#/definitions/Interval" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Enforces uniformity for data at regular intervals, such as integer values or daily samples. The interval may be one of:\n\n- a named time interval such as *day* (for date intervals)\n- a number (for number intervals), defining intervals at integer multiples of *n*\n\nThis option sets the internal transform to the given interval’s\n*interval*.floor function. In addition, the default **domain** will align with interval boundaries." + }, + "margin": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four mark margins: **marginTop**,\n**marginRight**, **marginBottom**, and **marginLeft**; typically defaults to 0, except for axis marks." + }, + "marginBottom": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s bottom margin; the minimum distance in pixels between the bottom edges of the inner and outer plot area." + }, + "marginLeft": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s left margin; the minimum distance in pixels between the left edges of the inner and outer plot area." + }, + "marginRight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s right margin; the minimum distance in pixels between the right edges of the mark’s inner and outer plot area." + }, + "marginTop": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s top margin; the minimum distance in pixels between the top edges of the inner and outer plot area." + }, + "mark": { + "const": "gridFy", + "description": "A vertically-positioned ruleY mark (a horizontal line, —) that renders a grid for the *fy* scale. The data defaults to the *fy* scale’s domain; if desired, use the **ticks** option.", + "type": "string" + }, + "marker": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for markerStart, markerMid, and markerEnd; one of:\n\n- a marker name such as *arrow* or *circle*\n- *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*" + }, + "markerEnd": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The marker for the ending point of a line segment; one of:\n\n- a marker name such as *arrow* or *circle*\n* *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*" + }, + "markerMid": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The marker for any middle (interior) points of a line segment. If the line segment only has a start and end point, this option has no effect. One of:\n\n- a marker name such as *arrow* or *circle*\n* *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*\n* a function - a custom marker function; see below" + }, + "markerStart": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The marker for the starting point of a line segment; one of:\n\n- a marker name such as *arrow* or *circle*\n* *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*" + }, + "mixBlendMode": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [mix-blend-mode][1]; a constant string specifying how to blend content such as *multiply*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode" + }, + "opacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "A shorthand for setting both **fillOpacity** and **strokeOpacity**; affects the stroke opacity of tick vectors and grid rules, and the fill opacity of tick texts and axis label texts; defaults to 1 for axes and 0.1 for grids." + }, + "paintOrder": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [paint-order][1]; a constant string specifying the order in which the\n**fill**, **stroke**, and any markers are drawn; defaults to *normal*, which draws the fill, then stroke, then markers; defaults to *stroke* for the text mark to create a “halo” around text to improve legibility.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/paint-order" + }, + "pointerEvents": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [pointer-events][1] property; a constant string such as *none*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/pointer-events" + }, + "reverse": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Applies a transform to reverse the order of the mark’s index, say for reverse input order." + }, + "select": { + "$ref": "#/definitions/SelectFilter", + "description": "Applies a filter transform after data is loaded to highlight selected values only. For example, `first` and `last` select the first or last values of series only (using the *z* channel to separate series). Meanwhile, `nearestX` and `nearestY` select the point nearest to the pointer along the *x* or *y* channel dimension. Unlike Mosaic selections, a mark level *select* is internal to the mark only, and does not populate a param or selection value to be shared across clients.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "shapeRendering": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [shape-rendering][1]; a constant string such as *crispEdges*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/shape-rendering" + }, + "sort": { + "anyOf": [ + { + "$ref": "#/definitions/SortOrder" + }, + { + "$ref": "#/definitions/ChannelDomainSort" + } + ], + "description": "Either applies a transform to sort the mark’s index by the specified channel values, or imputes ordinal scale domains from this mark’s channels.\n\nWhen imputing ordinal scale domains from channel values, the **sort** option is an object whose keys are ordinal scale names such as *x* or *fx*, and whose values are channel names such as *y*, *y1*, or *y2*. For example, to impute the *y* scale’s domain from the associated *x* channel values in ascending order:\n\n```js sort: {y: \"x\"} ```\n\nFor different sort options for different scales, replace the channel name with a *value* object and per-scale options:\n\n```js sort: {y: {value: \"-x\"}} ```\n\nWhen sorting the mark’s index, the **sort** option is instead one of:\n\n- a channel value definition for sorting given values in ascending order\n- a {value, order} object for sorting given values\n- a {channel, order} object for sorting the named channel’s values" + }, + "stroke": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke" + }, + "strokeDasharray": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dasharray][1]; a constant number indicating the length in pixels of alternating dashes and gaps, or a constant string of numbers separated by spaces or commas (_e.g._, *10 2* for dashes of 10 pixels separated by gaps of 2 pixels), or *none* (the default) for no dashing\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dasharray" + }, + "strokeDashoffset": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dashoffset][1]; a constant indicating the offset in pixels of the first dash along the stroke; defaults to zero.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dashoffset" + }, + "strokeLinecap": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linecap][1]; a constant specifying how to cap stroked paths, such as *butt*, *round*, or *square*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linecap" + }, + "strokeLinejoin": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linejoin][1]; a constant specifying how to join stroked paths, such as *bevel*, *miter*, *miter-clip*, or *round*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linejoin" + }, + "strokeMiterlimit": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-miterlimit][1]; a constant number specifying how to limit the length of *miter* joins on stroked paths.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-miterlimit" + }, + "strokeOpacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-opacity" + }, + "strokeWidth": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-width][1]; a constant number in pixels, or a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-width" + }, + "target": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [target][1]; a constant string specifying the target window (_e.g._,\n*_blank*) for clickable links; used in conjunction with the **href** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/target" + }, + "tickSpacing": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The desired approximate spacing between adjacent axis ticks, affecting the default **ticks**; defaults to 80 pixels for *x* and *fx*, and 35 pixels for *y* and *fy*." + }, + "ticks": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/Interval" + }, + { + "items": {}, + "type": "array" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The desired approximate number of axis ticks, or an explicit array of tick values, or an interval such as *day* or *month*." + }, + "tip": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/TipPointer" + }, + { + "properties": { + "anchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The tip anchor specifies how to orient the tip box relative to its anchor position; it refers to the part of the tip box that is attached to the anchor point. For example, the *top-left* anchor places the top-left corner of tip box near the anchor position, hence placing the tip box below and to the right of the anchor position." + }, + "fontFamily": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font-family][1]; a constant; defaults to the plot’s font family, which is typically [*system-ui*][2].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-family [2]: https://drafts.csswg.org/css-fonts-4/#valdef-font-family-system-ui" + }, + "fontSize": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font size][1] in pixels; either a constant or a channel; defaults to the plot’s font size, which is typically 10. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-size" + }, + "fontStyle": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font style][1]; a constant; defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-style" + }, + "fontVariant": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font variant][1]; a constant; if the **text** channel contains numbers or dates, defaults to *tabular-nums* to facilitate comparing numbers; otherwise defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant" + }, + "fontWeight": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font weight][1]; a constant; defaults to the plot’s font weight, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight" + }, + "format": { + "additionalProperties": false, + "description": "How channel values are formatted for display. If a format is a string, it is interpreted as a (UTC) time format for temporal channels, and otherwise a number format.", + "properties": { + "ariaLabel": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fill": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fillOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fontSize": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fx": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fy": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "geometry": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "height": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "href": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "length": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "opacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "path": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "r": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "rotate": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "src": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "stroke": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeWidth": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "symbol": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "text": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "title": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "weight": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "width": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "z": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + } + }, + "type": "object" + }, + "frameAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The frame anchor specifies defaults for **x** and **y** based on the plot’s frame; it may be one of the four sides (*top*, *right*, *bottom*, *left*), one of the four corners (*top-left*, *top-right*, *bottom-right*,\n*bottom-left*), or the *middle* of the frame. For example, for tips distributed horizontally at the top of the frame:\n\n```js Plot.tip(data, {x: \"date\", frameAnchor: \"top\"}) ```" + }, + "lineHeight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line height in ems; defaults to 1. The line height affects the (typically vertical) separation between adjacent baselines of text, as well as the separation between the text and its anchor point." + }, + "lineWidth": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line width in ems (e.g., 10 for about 20 characters); defaults to infinity, disabling wrapping and clipping.\n\nIf **textOverflow** is null, lines will be wrapped at the specified length. If a line is split at a soft hyphen (\\xad), a hyphen (-) will be displayed at the end of the line. If **textOverflow** is not null, lines will be clipped according to the given strategy." + }, + "monospace": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, changes the default **fontFamily** to *monospace*, and uses simplified monospaced text metrics calculations." + }, + "pathFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The image filter for the tip’s box; defaults to a drop shadow." + }, + "pointer": { + "$ref": "#/definitions/TipPointer" + }, + "pointerSize": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The size of the tip’s pointer in pixels; defaults to 12." + }, + "preferredAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If an explicit tip anchor is not specified, an anchor is chosen automatically such that the tip fits within the plot’s frame; if the preferred anchor fits, it is chosen." + }, + "textAnchor": { + "anyOf": [ + { + "const": "start", + "type": "string" + }, + { + "const": "middle", + "type": "string" + }, + { + "const": "end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [text anchor][1] controls how text is aligned (typically horizontally) relative to its anchor point; it is one of *start*, *end*, or *middle*. If the frame anchor is *left*, *top-left*, or *bottom-left*, the default text anchor is *start*; if the frame anchor is *right*, *top-right*, or\n*bottom-right*, the default is *end*; otherwise it is *middle*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/text-anchor" + }, + "textOverflow": { + "anyOf": [ + { + "type": "null" + }, + { + "const": "clip", + "type": "string" + }, + { + "const": "ellipsis", + "type": "string" + }, + { + "const": "clip-start", + "type": "string" + }, + { + "const": "clip-end", + "type": "string" + }, + { + "const": "ellipsis-start", + "type": "string" + }, + { + "const": "ellipsis-middle", + "type": "string" + }, + { + "const": "ellipsis-end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How truncate (or wrap) lines of text longer than the given **lineWidth**; one of:\n\n- null (default) - preserve overflowing characters (and wrap if needed)\n- *clip* or *clip-end* - remove characters from the end\n- *clip-start* - remove characters from the start\n- *ellipsis* or *ellipsis-end* - replace characters from the end with an ellipsis (…)\n- *ellipsis-start* - replace characters from the start with an ellipsis (…)\n- *ellipsis-middle* - replace characters from the middle with an ellipsis (…)\n\nIf no **title** was specified, if text requires truncation, a title containing the non-truncated text will be implicitly added." + }, + "textPadding": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The padding around the text in pixels; defaults to 8." + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + } + }, + "type": "object" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to generate a tooltip for this mark, and any tip options." + }, + "title": { + "$ref": "#/definitions/ChannelValue", + "description": "The title; a channel specifying accessible, short textual descriptions as strings (possibly with newlines). If the tip option is specified, the title will be displayed with an interactive tooltip instead of using the SVG [title element][1].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/title" + }, + "x": { + "$ref": "#/definitions/ChannelValueIntervalSpec", + "description": "Shorthand for specifying both the primary and secondary horizontal position of the tick as the bounds of the containing interval; can only be used in conjunction with the **interval** option." + }, + "x1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The primary (starting, often left) horizontal position of the tick; a channel bound to the *x* scale.\n\nIf *x* represents ordinal values, use a tickY mark instead." + }, + "x2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The secondary (ending, often right) horizontal position of the tick; a channel bound to the *x* scale.\n\nIf *x* represents ordinal values, use a tickY mark instead." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position of the tick; an optional channel bound to the *y* scale. If not specified, the rule will be vertically centered in the plot’s frame." + } + }, + "required": [ + "mark" + ], + "type": "object" + }, + "GridInterpolate": { + "description": "A spatial interpolation method; one of:\n\n- *none* - do not perform interpolation (the default), maps samples to single bins\n- *linear* - apply proportional linear interpolation across adjacent bins\n- *nearest* - assign each pixel to the closest sample’s value (Voronoi diagram)\n- *barycentric* - apply barycentric interpolation over the Delaunay triangulation\n- *random-walk* - apply a random walk from each pixel, stopping when near a sample", + "enum": [ + "none", + "linear", + "nearest", + "barycentric", + "random-walk" + ], + "type": "string" + }, + "GridX": { + "additionalProperties": false, + "description": "The gridX mark.", + "properties": { + "anchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "right", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "const": "left", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The side of the frame on which to place the axis: *top* or *bottom* for horizontal axes (axisX and axisFx) and their associated vertical grids (gridX and gridFx), or *left* or *right* for vertical axes (axisY and axisFY) and their associated horizontal grids (gridY and gridFy).\n\nThe default **anchor** depends on the associated scale:\n\n- *x* - *bottom*\n- *y* - *left*\n- *fx* - *top* if there is a *bottom* *x* axis, and otherwise *bottom*\n- *fy* - *right* if there is a *left* *y* axis, and otherwise *right*\n\nFor grids, the **anchor** also affects the extent of grid lines when the opposite dimension is specified (**x** for gridY and **y** for gridX)." + }, + "ariaDescription": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-description][1]; a constant textual description.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-description" + }, + "ariaHidden": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-hidden][1] state; a constant indicating whether the element is exposed to an accessibility API.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-hidden" + }, + "ariaLabel": { + "$ref": "#/definitions/ChannelValue", + "description": "The [aria-label][1]; a channel specifying short textual labels representing the value in the accessibility tree.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-label" + }, + "clip": { + "anyOf": [ + { + "const": "frame", + "type": "string" + }, + { + "const": "sphere", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to clip the mark; one of:\n\n- *frame* or true - clip to the plot’s frame (inner area)\n- *sphere* - clip to the projected sphere (*e.g.*, front hemisphere)\n- null or false - do not clip\n\nThe *sphere* clip option requires a geographic projection." + }, + "color": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A shorthand for setting both **fill** and **stroke**; affects the stroke of tick vectors and grid rules, and the fill of tick texts and axis label texts; defaults to *currentColor*." + }, + "dx": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The horizontal offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "dy": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The vertical offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "facet": { + "anyOf": [ + { + "const": "auto", + "type": "string" + }, + { + "const": "include", + "type": "string" + }, + { + "const": "exclude", + "type": "string" + }, + { + "const": "super", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to enable or disable faceting; one of:\n\n- *auto* (default) - automatically determine if this mark should be faceted\n- *include* (or true) - draw the subset of the mark’s data in the current facet\n- *exclude* - draw the subset of the mark’s data *not* in the current facet\n- *super* - draw this mark in a single frame that covers all facets\n- null (or false) - repeat this mark’s data across all facets (*i.e.*, no faceting)\n\nWhen a mark uses *super* faceting, it is not allowed to use position scales (*x*, *y*, *fx*, or *fy*); *super* faceting is intended for decorations, such as labels and legends.\n\nWhen top-level faceting is used, the default *auto* setting is equivalent to *include* when the mark data is strictly equal to the top-level facet data; otherwise it is equivalent to null. When the *include* or *exclude* facet mode is chosen, the mark data must be parallel to the top-level facet data: the data must have the same length and order. If the data are not parallel, then the wrong data may be shown in each facet. The default\n*auto* therefore requires strict equality (`===`) for safety, and using the facet data as mark data is recommended when using the *exclude* facet mode. (To construct parallel data safely, consider using [*array*.map][1] on the facet data.)\n\nWhen mark-level faceting is used, the default *auto* setting is equivalent to *include*: the mark will be faceted if either the **fx** or **fy** channel option (or both) is specified. The null or false option will disable faceting, while *exclude* draws the subset of the mark’s data *not* in the current facet.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map" + }, + "facetAnchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "right", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "const": "left", + "type": "string" + }, + { + "const": "top-left", + "type": "string" + }, + { + "const": "top-right", + "type": "string" + }, + { + "const": "bottom-left", + "type": "string" + }, + { + "const": "bottom-right", + "type": "string" + }, + { + "const": "top-empty", + "type": "string" + }, + { + "const": "right-empty", + "type": "string" + }, + { + "const": "bottom-empty", + "type": "string" + }, + { + "const": "left-empty", + "type": "string" + }, + { + "const": "empty", + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to place the mark with respect to facets; one of:\n\n- null (default for most marks) - display the mark in each non-empty facet\n- *top*, *right*, *bottom*, or *left* - display the mark only in facets on the given side\n- *top-empty*, *right-empty*, *bottom-empty*, or *left-empty* (default for axis marks) - display the mark only in facets that have empty space on the given side: either the margin, or an empty facet\n- *empty* - display the mark in empty facets only" + }, + "fill": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill" + }, + "fillOpacity": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill-opacity][1]; a constant number between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill-opacity" + }, + "filter": { + "$ref": "#/definitions/ChannelValue", + "description": "Applies a transform to filter the mark’s index according to the given channel values; only truthy values are retained.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "fx": { + "$ref": "#/definitions/ChannelValue", + "description": "The horizontal facet position channel, for mark-level faceting, bound to the *fx* scale." + }, + "fy": { + "$ref": "#/definitions/ChannelValue", + "description": "The vertical facet position channel, for mark-level faceting, bound to the\n*fy* scale." + }, + "href": { + "$ref": "#/definitions/ChannelValue", + "description": "The [href][1]; a channel specifying URLs for clickable links. May be used in conjunction with the **target** option to open links in another window.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/href" + }, + "imageFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A CSS [filter][1]; a constant string used to adjust the rendering of images, such as *blur(5px)*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/filter" + }, + "inset": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four insets: **insetTop**,\n**insetRight**, **insetBottom**, and **insetLeft**. All insets typically default to zero, though not always (say when using bin transform). A positive inset reduces effective area, while a negative inset increases it." + }, + "insetBottom": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Insets the bottom edge by the specified number of pixels. A positive value insets towards the top edge (reducing effective area), while a negative value insets away from the top edge (increasing it)." + }, + "insetTop": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Insets the top edge by the specified number of pixels. A positive value insets towards the bottom edge (reducing effective area), while a negative value insets away from the bottom edge (increasing it)." + }, + "interval": { + "anyOf": [ + { + "$ref": "#/definitions/Interval" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Enforces uniformity for data at regular intervals, such as integer values or daily samples. The interval may be one of:\n\n- a named time interval such as *day* (for date intervals)\n- a number (for number intervals), defining intervals at integer multiples of *n*\n\nThis option sets the internal transform to the given interval’s\n*interval*.floor function. In addition, the default **domain** will align with interval boundaries." + }, + "margin": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four mark margins: **marginTop**,\n**marginRight**, **marginBottom**, and **marginLeft**; typically defaults to 0, except for axis marks." + }, + "marginBottom": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s bottom margin; the minimum distance in pixels between the bottom edges of the inner and outer plot area." + }, + "marginLeft": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s left margin; the minimum distance in pixels between the left edges of the inner and outer plot area." + }, + "marginRight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s right margin; the minimum distance in pixels between the right edges of the mark’s inner and outer plot area." + }, + "marginTop": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s top margin; the minimum distance in pixels between the top edges of the inner and outer plot area." + }, + "mark": { + "const": "gridX", + "description": "A horizontally-positioned ruleX mark (a vertical line, |) that renders a grid for the *x* scale. The data defaults to tick values sampled from the\n*x* scale’s domain; if desired, use one of the **ticks**, **tickSpacing**, or **interval** options.", + "type": "string" + }, + "marker": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for markerStart, markerMid, and markerEnd; one of:\n\n- a marker name such as *arrow* or *circle*\n- *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*" + }, + "markerEnd": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The marker for the ending point of a line segment; one of:\n\n- a marker name such as *arrow* or *circle*\n* *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*" + }, + "markerMid": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The marker for any middle (interior) points of a line segment. If the line segment only has a start and end point, this option has no effect. One of:\n\n- a marker name such as *arrow* or *circle*\n* *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*\n* a function - a custom marker function; see below" + }, + "markerStart": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The marker for the starting point of a line segment; one of:\n\n- a marker name such as *arrow* or *circle*\n* *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*" + }, + "mixBlendMode": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [mix-blend-mode][1]; a constant string specifying how to blend content such as *multiply*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode" + }, + "opacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "A shorthand for setting both **fillOpacity** and **strokeOpacity**; affects the stroke opacity of tick vectors and grid rules, and the fill opacity of tick texts and axis label texts; defaults to 1 for axes and 0.1 for grids." + }, + "paintOrder": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [paint-order][1]; a constant string specifying the order in which the\n**fill**, **stroke**, and any markers are drawn; defaults to *normal*, which draws the fill, then stroke, then markers; defaults to *stroke* for the text mark to create a “halo” around text to improve legibility.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/paint-order" + }, + "pointerEvents": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [pointer-events][1] property; a constant string such as *none*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/pointer-events" + }, + "reverse": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Applies a transform to reverse the order of the mark’s index, say for reverse input order." + }, + "select": { + "$ref": "#/definitions/SelectFilter", + "description": "Applies a filter transform after data is loaded to highlight selected values only. For example, `first` and `last` select the first or last values of series only (using the *z* channel to separate series). Meanwhile, `nearestX` and `nearestY` select the point nearest to the pointer along the *x* or *y* channel dimension. Unlike Mosaic selections, a mark level *select* is internal to the mark only, and does not populate a param or selection value to be shared across clients.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "shapeRendering": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [shape-rendering][1]; a constant string such as *crispEdges*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/shape-rendering" + }, + "sort": { + "anyOf": [ + { + "$ref": "#/definitions/SortOrder" + }, + { + "$ref": "#/definitions/ChannelDomainSort" + } + ], + "description": "Either applies a transform to sort the mark’s index by the specified channel values, or imputes ordinal scale domains from this mark’s channels.\n\nWhen imputing ordinal scale domains from channel values, the **sort** option is an object whose keys are ordinal scale names such as *x* or *fx*, and whose values are channel names such as *y*, *y1*, or *y2*. For example, to impute the *y* scale’s domain from the associated *x* channel values in ascending order:\n\n```js sort: {y: \"x\"} ```\n\nFor different sort options for different scales, replace the channel name with a *value* object and per-scale options:\n\n```js sort: {y: {value: \"-x\"}} ```\n\nWhen sorting the mark’s index, the **sort** option is instead one of:\n\n- a channel value definition for sorting given values in ascending order\n- a {value, order} object for sorting given values\n- a {channel, order} object for sorting the named channel’s values" + }, + "stroke": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke" + }, + "strokeDasharray": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dasharray][1]; a constant number indicating the length in pixels of alternating dashes and gaps, or a constant string of numbers separated by spaces or commas (_e.g._, *10 2* for dashes of 10 pixels separated by gaps of 2 pixels), or *none* (the default) for no dashing\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dasharray" + }, + "strokeDashoffset": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dashoffset][1]; a constant indicating the offset in pixels of the first dash along the stroke; defaults to zero.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dashoffset" + }, + "strokeLinecap": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linecap][1]; a constant specifying how to cap stroked paths, such as *butt*, *round*, or *square*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linecap" + }, + "strokeLinejoin": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linejoin][1]; a constant specifying how to join stroked paths, such as *bevel*, *miter*, *miter-clip*, or *round*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linejoin" + }, + "strokeMiterlimit": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-miterlimit][1]; a constant number specifying how to limit the length of *miter* joins on stroked paths.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-miterlimit" + }, + "strokeOpacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-opacity" + }, + "strokeWidth": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-width][1]; a constant number in pixels, or a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-width" + }, + "target": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [target][1]; a constant string specifying the target window (_e.g._,\n*_blank*) for clickable links; used in conjunction with the **href** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/target" + }, + "tickSpacing": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The desired approximate spacing between adjacent axis ticks, affecting the default **ticks**; defaults to 80 pixels for *x* and *fx*, and 35 pixels for *y* and *fy*." + }, + "ticks": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/Interval" + }, + { + "items": {}, + "type": "array" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The desired approximate number of axis ticks, or an explicit array of tick values, or an interval such as *day* or *month*." + }, + "tip": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/TipPointer" + }, + { + "properties": { + "anchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The tip anchor specifies how to orient the tip box relative to its anchor position; it refers to the part of the tip box that is attached to the anchor point. For example, the *top-left* anchor places the top-left corner of tip box near the anchor position, hence placing the tip box below and to the right of the anchor position." + }, + "fontFamily": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font-family][1]; a constant; defaults to the plot’s font family, which is typically [*system-ui*][2].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-family [2]: https://drafts.csswg.org/css-fonts-4/#valdef-font-family-system-ui" + }, + "fontSize": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font size][1] in pixels; either a constant or a channel; defaults to the plot’s font size, which is typically 10. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-size" + }, + "fontStyle": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font style][1]; a constant; defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-style" + }, + "fontVariant": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font variant][1]; a constant; if the **text** channel contains numbers or dates, defaults to *tabular-nums* to facilitate comparing numbers; otherwise defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant" + }, + "fontWeight": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font weight][1]; a constant; defaults to the plot’s font weight, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight" + }, + "format": { + "additionalProperties": false, + "description": "How channel values are formatted for display. If a format is a string, it is interpreted as a (UTC) time format for temporal channels, and otherwise a number format.", + "properties": { + "ariaLabel": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fill": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fillOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fontSize": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fx": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fy": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "geometry": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "height": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "href": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "length": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "opacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "path": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "r": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "rotate": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "src": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "stroke": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeWidth": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "symbol": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "text": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "title": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "weight": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "width": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "z": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + } + }, + "type": "object" + }, + "frameAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The frame anchor specifies defaults for **x** and **y** based on the plot’s frame; it may be one of the four sides (*top*, *right*, *bottom*, *left*), one of the four corners (*top-left*, *top-right*, *bottom-right*,\n*bottom-left*), or the *middle* of the frame. For example, for tips distributed horizontally at the top of the frame:\n\n```js Plot.tip(data, {x: \"date\", frameAnchor: \"top\"}) ```" + }, + "lineHeight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line height in ems; defaults to 1. The line height affects the (typically vertical) separation between adjacent baselines of text, as well as the separation between the text and its anchor point." + }, + "lineWidth": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line width in ems (e.g., 10 for about 20 characters); defaults to infinity, disabling wrapping and clipping.\n\nIf **textOverflow** is null, lines will be wrapped at the specified length. If a line is split at a soft hyphen (\\xad), a hyphen (-) will be displayed at the end of the line. If **textOverflow** is not null, lines will be clipped according to the given strategy." + }, + "monospace": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, changes the default **fontFamily** to *monospace*, and uses simplified monospaced text metrics calculations." + }, + "pathFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The image filter for the tip’s box; defaults to a drop shadow." + }, + "pointer": { + "$ref": "#/definitions/TipPointer" + }, + "pointerSize": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The size of the tip’s pointer in pixels; defaults to 12." + }, + "preferredAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If an explicit tip anchor is not specified, an anchor is chosen automatically such that the tip fits within the plot’s frame; if the preferred anchor fits, it is chosen." + }, + "textAnchor": { + "anyOf": [ + { + "const": "start", + "type": "string" + }, + { + "const": "middle", + "type": "string" + }, + { + "const": "end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [text anchor][1] controls how text is aligned (typically horizontally) relative to its anchor point; it is one of *start*, *end*, or *middle*. If the frame anchor is *left*, *top-left*, or *bottom-left*, the default text anchor is *start*; if the frame anchor is *right*, *top-right*, or\n*bottom-right*, the default is *end*; otherwise it is *middle*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/text-anchor" + }, + "textOverflow": { + "anyOf": [ + { + "type": "null" + }, + { + "const": "clip", + "type": "string" + }, + { + "const": "ellipsis", + "type": "string" + }, + { + "const": "clip-start", + "type": "string" + }, + { + "const": "clip-end", + "type": "string" + }, + { + "const": "ellipsis-start", + "type": "string" + }, + { + "const": "ellipsis-middle", + "type": "string" + }, + { + "const": "ellipsis-end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How truncate (or wrap) lines of text longer than the given **lineWidth**; one of:\n\n- null (default) - preserve overflowing characters (and wrap if needed)\n- *clip* or *clip-end* - remove characters from the end\n- *clip-start* - remove characters from the start\n- *ellipsis* or *ellipsis-end* - replace characters from the end with an ellipsis (…)\n- *ellipsis-start* - replace characters from the start with an ellipsis (…)\n- *ellipsis-middle* - replace characters from the middle with an ellipsis (…)\n\nIf no **title** was specified, if text requires truncation, a title containing the non-truncated text will be implicitly added." + }, + "textPadding": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The padding around the text in pixels; defaults to 8." + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + } + }, + "type": "object" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to generate a tooltip for this mark, and any tip options." + }, + "title": { + "$ref": "#/definitions/ChannelValue", + "description": "The title; a channel specifying accessible, short textual descriptions as strings (possibly with newlines). If the tip option is specified, the title will be displayed with an interactive tooltip instead of using the SVG [title element][1].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/title" + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position of the tick; an optional channel bound to the *x* scale. If not specified, the rule will be horizontally centered in the plot’s frame." + }, + "y": { + "$ref": "#/definitions/ChannelValueIntervalSpec", + "description": "Shorthand for specifying both the primary and secondary vertical position of the tick as the bounds of the containing interval; can only be used in conjunction with the **interval** option." + }, + "y1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The primary (starting, often bottom) vertical position of the tick; a channel bound to the *y* scale.\n\nIf *y* represents ordinal values, use a tickX mark instead." + }, + "y2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The secondary (ending, often top) vertical position of the tick; a channel bound to the *y* scale.\n\nIf *y* represents ordinal values, use a tickX mark instead." + } + }, + "required": [ + "mark" + ], + "type": "object" + }, + "GridY": { + "additionalProperties": false, + "description": "The gridY mark.", + "properties": { + "anchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "right", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "const": "left", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The side of the frame on which to place the axis: *top* or *bottom* for horizontal axes (axisX and axisFx) and their associated vertical grids (gridX and gridFx), or *left* or *right* for vertical axes (axisY and axisFY) and their associated horizontal grids (gridY and gridFy).\n\nThe default **anchor** depends on the associated scale:\n\n- *x* - *bottom*\n- *y* - *left*\n- *fx* - *top* if there is a *bottom* *x* axis, and otherwise *bottom*\n- *fy* - *right* if there is a *left* *y* axis, and otherwise *right*\n\nFor grids, the **anchor** also affects the extent of grid lines when the opposite dimension is specified (**x** for gridY and **y** for gridX)." + }, + "ariaDescription": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-description][1]; a constant textual description.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-description" + }, + "ariaHidden": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-hidden][1] state; a constant indicating whether the element is exposed to an accessibility API.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-hidden" + }, + "ariaLabel": { + "$ref": "#/definitions/ChannelValue", + "description": "The [aria-label][1]; a channel specifying short textual labels representing the value in the accessibility tree.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-label" + }, + "clip": { + "anyOf": [ + { + "const": "frame", + "type": "string" + }, + { + "const": "sphere", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to clip the mark; one of:\n\n- *frame* or true - clip to the plot’s frame (inner area)\n- *sphere* - clip to the projected sphere (*e.g.*, front hemisphere)\n- null or false - do not clip\n\nThe *sphere* clip option requires a geographic projection." + }, + "color": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A shorthand for setting both **fill** and **stroke**; affects the stroke of tick vectors and grid rules, and the fill of tick texts and axis label texts; defaults to *currentColor*." + }, + "dx": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The horizontal offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "dy": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The vertical offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "facet": { + "anyOf": [ + { + "const": "auto", + "type": "string" + }, + { + "const": "include", + "type": "string" + }, + { + "const": "exclude", + "type": "string" + }, + { + "const": "super", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to enable or disable faceting; one of:\n\n- *auto* (default) - automatically determine if this mark should be faceted\n- *include* (or true) - draw the subset of the mark’s data in the current facet\n- *exclude* - draw the subset of the mark’s data *not* in the current facet\n- *super* - draw this mark in a single frame that covers all facets\n- null (or false) - repeat this mark’s data across all facets (*i.e.*, no faceting)\n\nWhen a mark uses *super* faceting, it is not allowed to use position scales (*x*, *y*, *fx*, or *fy*); *super* faceting is intended for decorations, such as labels and legends.\n\nWhen top-level faceting is used, the default *auto* setting is equivalent to *include* when the mark data is strictly equal to the top-level facet data; otherwise it is equivalent to null. When the *include* or *exclude* facet mode is chosen, the mark data must be parallel to the top-level facet data: the data must have the same length and order. If the data are not parallel, then the wrong data may be shown in each facet. The default\n*auto* therefore requires strict equality (`===`) for safety, and using the facet data as mark data is recommended when using the *exclude* facet mode. (To construct parallel data safely, consider using [*array*.map][1] on the facet data.)\n\nWhen mark-level faceting is used, the default *auto* setting is equivalent to *include*: the mark will be faceted if either the **fx** or **fy** channel option (or both) is specified. The null or false option will disable faceting, while *exclude* draws the subset of the mark’s data *not* in the current facet.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map" + }, + "facetAnchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "right", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "const": "left", + "type": "string" + }, + { + "const": "top-left", + "type": "string" + }, + { + "const": "top-right", + "type": "string" + }, + { + "const": "bottom-left", + "type": "string" + }, + { + "const": "bottom-right", + "type": "string" + }, + { + "const": "top-empty", + "type": "string" + }, + { + "const": "right-empty", + "type": "string" + }, + { + "const": "bottom-empty", + "type": "string" + }, + { + "const": "left-empty", + "type": "string" + }, + { + "const": "empty", + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to place the mark with respect to facets; one of:\n\n- null (default for most marks) - display the mark in each non-empty facet\n- *top*, *right*, *bottom*, or *left* - display the mark only in facets on the given side\n- *top-empty*, *right-empty*, *bottom-empty*, or *left-empty* (default for axis marks) - display the mark only in facets that have empty space on the given side: either the margin, or an empty facet\n- *empty* - display the mark in empty facets only" + }, + "fill": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill" + }, + "fillOpacity": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill-opacity][1]; a constant number between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill-opacity" + }, + "filter": { + "$ref": "#/definitions/ChannelValue", + "description": "Applies a transform to filter the mark’s index according to the given channel values; only truthy values are retained.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "fx": { + "$ref": "#/definitions/ChannelValue", + "description": "The horizontal facet position channel, for mark-level faceting, bound to the *fx* scale." + }, + "fy": { + "$ref": "#/definitions/ChannelValue", + "description": "The vertical facet position channel, for mark-level faceting, bound to the\n*fy* scale." + }, + "href": { + "$ref": "#/definitions/ChannelValue", + "description": "The [href][1]; a channel specifying URLs for clickable links. May be used in conjunction with the **target** option to open links in another window.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/href" + }, + "imageFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A CSS [filter][1]; a constant string used to adjust the rendering of images, such as *blur(5px)*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/filter" + }, + "inset": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four insets: **insetTop**,\n**insetRight**, **insetBottom**, and **insetLeft**. All insets typically default to zero, though not always (say when using bin transform). A positive inset reduces effective area, while a negative inset increases it." + }, + "insetLeft": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Insets the left edge by the specified number of pixels. A positive value insets towards the right edge (reducing effective area), while a negative value insets away from the right edge (increasing it)." + }, + "insetRight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Insets the right edge by the specified number of pixels. A positive value insets towards the left edge (reducing effective area), while a negative value insets away from the left edge (increasing it)." + }, + "interval": { + "anyOf": [ + { + "$ref": "#/definitions/Interval" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Enforces uniformity for data at regular intervals, such as integer values or daily samples. The interval may be one of:\n\n- a named time interval such as *day* (for date intervals)\n- a number (for number intervals), defining intervals at integer multiples of *n*\n\nThis option sets the internal transform to the given interval’s\n*interval*.floor function. In addition, the default **domain** will align with interval boundaries." + }, + "margin": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four mark margins: **marginTop**,\n**marginRight**, **marginBottom**, and **marginLeft**; typically defaults to 0, except for axis marks." + }, + "marginBottom": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s bottom margin; the minimum distance in pixels between the bottom edges of the inner and outer plot area." + }, + "marginLeft": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s left margin; the minimum distance in pixels between the left edges of the inner and outer plot area." + }, + "marginRight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s right margin; the minimum distance in pixels between the right edges of the mark’s inner and outer plot area." + }, + "marginTop": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s top margin; the minimum distance in pixels between the top edges of the inner and outer plot area." + }, + "mark": { + "const": "gridY", + "description": "A vertically-positioned ruleY mark (a horizontal line, —) that renders a grid for the *y* scale. The data defaults to tick values sampled from the\n*y* scale’s domain; if desired, use one of the **ticks**, **tickSpacing**, or **interval** options.", + "type": "string" + }, + "marker": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for markerStart, markerMid, and markerEnd; one of:\n\n- a marker name such as *arrow* or *circle*\n- *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*" + }, + "markerEnd": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The marker for the ending point of a line segment; one of:\n\n- a marker name such as *arrow* or *circle*\n* *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*" + }, + "markerMid": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The marker for any middle (interior) points of a line segment. If the line segment only has a start and end point, this option has no effect. One of:\n\n- a marker name such as *arrow* or *circle*\n* *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*\n* a function - a custom marker function; see below" + }, + "markerStart": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The marker for the starting point of a line segment; one of:\n\n- a marker name such as *arrow* or *circle*\n* *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*" + }, + "mixBlendMode": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [mix-blend-mode][1]; a constant string specifying how to blend content such as *multiply*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode" + }, + "opacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "A shorthand for setting both **fillOpacity** and **strokeOpacity**; affects the stroke opacity of tick vectors and grid rules, and the fill opacity of tick texts and axis label texts; defaults to 1 for axes and 0.1 for grids." + }, + "paintOrder": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [paint-order][1]; a constant string specifying the order in which the\n**fill**, **stroke**, and any markers are drawn; defaults to *normal*, which draws the fill, then stroke, then markers; defaults to *stroke* for the text mark to create a “halo” around text to improve legibility.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/paint-order" + }, + "pointerEvents": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [pointer-events][1] property; a constant string such as *none*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/pointer-events" + }, + "reverse": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Applies a transform to reverse the order of the mark’s index, say for reverse input order." + }, + "select": { + "$ref": "#/definitions/SelectFilter", + "description": "Applies a filter transform after data is loaded to highlight selected values only. For example, `first` and `last` select the first or last values of series only (using the *z* channel to separate series). Meanwhile, `nearestX` and `nearestY` select the point nearest to the pointer along the *x* or *y* channel dimension. Unlike Mosaic selections, a mark level *select* is internal to the mark only, and does not populate a param or selection value to be shared across clients.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "shapeRendering": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [shape-rendering][1]; a constant string such as *crispEdges*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/shape-rendering" + }, + "sort": { + "anyOf": [ + { + "$ref": "#/definitions/SortOrder" + }, + { + "$ref": "#/definitions/ChannelDomainSort" + } + ], + "description": "Either applies a transform to sort the mark’s index by the specified channel values, or imputes ordinal scale domains from this mark’s channels.\n\nWhen imputing ordinal scale domains from channel values, the **sort** option is an object whose keys are ordinal scale names such as *x* or *fx*, and whose values are channel names such as *y*, *y1*, or *y2*. For example, to impute the *y* scale’s domain from the associated *x* channel values in ascending order:\n\n```js sort: {y: \"x\"} ```\n\nFor different sort options for different scales, replace the channel name with a *value* object and per-scale options:\n\n```js sort: {y: {value: \"-x\"}} ```\n\nWhen sorting the mark’s index, the **sort** option is instead one of:\n\n- a channel value definition for sorting given values in ascending order\n- a {value, order} object for sorting given values\n- a {channel, order} object for sorting the named channel’s values" + }, + "stroke": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke" + }, + "strokeDasharray": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dasharray][1]; a constant number indicating the length in pixels of alternating dashes and gaps, or a constant string of numbers separated by spaces or commas (_e.g._, *10 2* for dashes of 10 pixels separated by gaps of 2 pixels), or *none* (the default) for no dashing\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dasharray" + }, + "strokeDashoffset": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dashoffset][1]; a constant indicating the offset in pixels of the first dash along the stroke; defaults to zero.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dashoffset" + }, + "strokeLinecap": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linecap][1]; a constant specifying how to cap stroked paths, such as *butt*, *round*, or *square*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linecap" + }, + "strokeLinejoin": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linejoin][1]; a constant specifying how to join stroked paths, such as *bevel*, *miter*, *miter-clip*, or *round*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linejoin" + }, + "strokeMiterlimit": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-miterlimit][1]; a constant number specifying how to limit the length of *miter* joins on stroked paths.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-miterlimit" + }, + "strokeOpacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-opacity" + }, + "strokeWidth": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-width][1]; a constant number in pixels, or a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-width" + }, + "target": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [target][1]; a constant string specifying the target window (_e.g._,\n*_blank*) for clickable links; used in conjunction with the **href** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/target" + }, + "tickSpacing": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The desired approximate spacing between adjacent axis ticks, affecting the default **ticks**; defaults to 80 pixels for *x* and *fx*, and 35 pixels for *y* and *fy*." + }, + "ticks": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/Interval" + }, + { + "items": {}, + "type": "array" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The desired approximate number of axis ticks, or an explicit array of tick values, or an interval such as *day* or *month*." + }, + "tip": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/TipPointer" + }, + { + "properties": { + "anchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The tip anchor specifies how to orient the tip box relative to its anchor position; it refers to the part of the tip box that is attached to the anchor point. For example, the *top-left* anchor places the top-left corner of tip box near the anchor position, hence placing the tip box below and to the right of the anchor position." + }, + "fontFamily": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font-family][1]; a constant; defaults to the plot’s font family, which is typically [*system-ui*][2].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-family [2]: https://drafts.csswg.org/css-fonts-4/#valdef-font-family-system-ui" + }, + "fontSize": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font size][1] in pixels; either a constant or a channel; defaults to the plot’s font size, which is typically 10. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-size" + }, + "fontStyle": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font style][1]; a constant; defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-style" + }, + "fontVariant": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font variant][1]; a constant; if the **text** channel contains numbers or dates, defaults to *tabular-nums* to facilitate comparing numbers; otherwise defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant" + }, + "fontWeight": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font weight][1]; a constant; defaults to the plot’s font weight, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight" + }, + "format": { + "additionalProperties": false, + "description": "How channel values are formatted for display. If a format is a string, it is interpreted as a (UTC) time format for temporal channels, and otherwise a number format.", + "properties": { + "ariaLabel": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fill": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fillOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fontSize": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fx": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fy": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "geometry": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "height": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "href": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "length": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "opacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "path": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "r": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "rotate": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "src": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "stroke": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeWidth": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "symbol": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "text": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "title": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "weight": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "width": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "z": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + } + }, + "type": "object" + }, + "frameAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The frame anchor specifies defaults for **x** and **y** based on the plot’s frame; it may be one of the four sides (*top*, *right*, *bottom*, *left*), one of the four corners (*top-left*, *top-right*, *bottom-right*,\n*bottom-left*), or the *middle* of the frame. For example, for tips distributed horizontally at the top of the frame:\n\n```js Plot.tip(data, {x: \"date\", frameAnchor: \"top\"}) ```" + }, + "lineHeight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line height in ems; defaults to 1. The line height affects the (typically vertical) separation between adjacent baselines of text, as well as the separation between the text and its anchor point." + }, + "lineWidth": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line width in ems (e.g., 10 for about 20 characters); defaults to infinity, disabling wrapping and clipping.\n\nIf **textOverflow** is null, lines will be wrapped at the specified length. If a line is split at a soft hyphen (\\xad), a hyphen (-) will be displayed at the end of the line. If **textOverflow** is not null, lines will be clipped according to the given strategy." + }, + "monospace": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, changes the default **fontFamily** to *monospace*, and uses simplified monospaced text metrics calculations." + }, + "pathFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The image filter for the tip’s box; defaults to a drop shadow." + }, + "pointer": { + "$ref": "#/definitions/TipPointer" + }, + "pointerSize": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The size of the tip’s pointer in pixels; defaults to 12." + }, + "preferredAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If an explicit tip anchor is not specified, an anchor is chosen automatically such that the tip fits within the plot’s frame; if the preferred anchor fits, it is chosen." + }, + "textAnchor": { + "anyOf": [ + { + "const": "start", + "type": "string" + }, + { + "const": "middle", + "type": "string" + }, + { + "const": "end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [text anchor][1] controls how text is aligned (typically horizontally) relative to its anchor point; it is one of *start*, *end*, or *middle*. If the frame anchor is *left*, *top-left*, or *bottom-left*, the default text anchor is *start*; if the frame anchor is *right*, *top-right*, or\n*bottom-right*, the default is *end*; otherwise it is *middle*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/text-anchor" + }, + "textOverflow": { + "anyOf": [ + { + "type": "null" + }, + { + "const": "clip", + "type": "string" + }, + { + "const": "ellipsis", + "type": "string" + }, + { + "const": "clip-start", + "type": "string" + }, + { + "const": "clip-end", + "type": "string" + }, + { + "const": "ellipsis-start", + "type": "string" + }, + { + "const": "ellipsis-middle", + "type": "string" + }, + { + "const": "ellipsis-end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How truncate (or wrap) lines of text longer than the given **lineWidth**; one of:\n\n- null (default) - preserve overflowing characters (and wrap if needed)\n- *clip* or *clip-end* - remove characters from the end\n- *clip-start* - remove characters from the start\n- *ellipsis* or *ellipsis-end* - replace characters from the end with an ellipsis (…)\n- *ellipsis-start* - replace characters from the start with an ellipsis (…)\n- *ellipsis-middle* - replace characters from the middle with an ellipsis (…)\n\nIf no **title** was specified, if text requires truncation, a title containing the non-truncated text will be implicitly added." + }, + "textPadding": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The padding around the text in pixels; defaults to 8." + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + } + }, + "type": "object" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to generate a tooltip for this mark, and any tip options." + }, + "title": { + "$ref": "#/definitions/ChannelValue", + "description": "The title; a channel specifying accessible, short textual descriptions as strings (possibly with newlines). If the tip option is specified, the title will be displayed with an interactive tooltip instead of using the SVG [title element][1].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/title" + }, + "x": { + "$ref": "#/definitions/ChannelValueIntervalSpec", + "description": "Shorthand for specifying both the primary and secondary horizontal position of the tick as the bounds of the containing interval; can only be used in conjunction with the **interval** option." + }, + "x1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The primary (starting, often left) horizontal position of the tick; a channel bound to the *x* scale.\n\nIf *x* represents ordinal values, use a tickY mark instead." + }, + "x2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The secondary (ending, often right) horizontal position of the tick; a channel bound to the *x* scale.\n\nIf *x* represents ordinal values, use a tickY mark instead." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position of the tick; an optional channel bound to the *y* scale. If not specified, the rule will be vertically centered in the plot’s frame." + } + }, + "required": [ + "mark" + ], + "type": "object" + }, + "HConcat": { + "additionalProperties": false, + "description": "An hconcat component.", + "properties": { + "hconcat": { + "description": "Horizontally concatenate components in a row layout.", + "items": { + "$ref": "#/definitions/Component" + }, + "type": "array" + } + }, + "required": [ + "hconcat" + ], + "type": "object" + }, + "HSpace": { + "additionalProperties": false, + "description": "An hspace component.", + "properties": { + "hspace": { + "description": "Horizontal space to place between components. Number values indicate screen pixels. String values may use CSS units (em, pt, px, etc).", + "type": [ + "number", + "string" + ] + } + }, + "required": [ + "hspace" + ], + "type": "object" + }, + "Heatmap": { + "additionalProperties": false, + "description": "The heatmap mark.", + "properties": { + "ariaDescription": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-description][1]; a constant textual description.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-description" + }, + "ariaHidden": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-hidden][1] state; a constant indicating whether the element is exposed to an accessibility API.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-hidden" + }, + "ariaLabel": { + "$ref": "#/definitions/ChannelValue", + "description": "The [aria-label][1]; a channel specifying short textual labels representing the value in the accessibility tree.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-label" + }, + "bandwidth": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The kernel density bandwidth for smoothing, in pixels." + }, + "clip": { + "anyOf": [ + { + "const": "frame", + "type": "string" + }, + { + "const": "sphere", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to clip the mark; one of:\n\n- *frame* or true - clip to the plot’s frame (inner area)\n- *sphere* - clip to the projected sphere (*e.g.*, front hemisphere)\n- null or false - do not clip\n\nThe *sphere* clip option requires a geographic projection." + }, + "data": { + "$ref": "#/definitions/PlotMarkData", + "description": "The data source for the mark." + }, + "dx": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The horizontal offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "dy": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The vertical offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "facet": { + "anyOf": [ + { + "const": "auto", + "type": "string" + }, + { + "const": "include", + "type": "string" + }, + { + "const": "exclude", + "type": "string" + }, + { + "const": "super", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to enable or disable faceting; one of:\n\n- *auto* (default) - automatically determine if this mark should be faceted\n- *include* (or true) - draw the subset of the mark’s data in the current facet\n- *exclude* - draw the subset of the mark’s data *not* in the current facet\n- *super* - draw this mark in a single frame that covers all facets\n- null (or false) - repeat this mark’s data across all facets (*i.e.*, no faceting)\n\nWhen a mark uses *super* faceting, it is not allowed to use position scales (*x*, *y*, *fx*, or *fy*); *super* faceting is intended for decorations, such as labels and legends.\n\nWhen top-level faceting is used, the default *auto* setting is equivalent to *include* when the mark data is strictly equal to the top-level facet data; otherwise it is equivalent to null. When the *include* or *exclude* facet mode is chosen, the mark data must be parallel to the top-level facet data: the data must have the same length and order. If the data are not parallel, then the wrong data may be shown in each facet. The default\n*auto* therefore requires strict equality (`===`) for safety, and using the facet data as mark data is recommended when using the *exclude* facet mode. (To construct parallel data safely, consider using [*array*.map][1] on the facet data.)\n\nWhen mark-level faceting is used, the default *auto* setting is equivalent to *include*: the mark will be faceted if either the **fx** or **fy** channel option (or both) is specified. The null or false option will disable faceting, while *exclude* draws the subset of the mark’s data *not* in the current facet.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map" + }, + "facetAnchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "right", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "const": "left", + "type": "string" + }, + { + "const": "top-left", + "type": "string" + }, + { + "const": "top-right", + "type": "string" + }, + { + "const": "bottom-left", + "type": "string" + }, + { + "const": "bottom-right", + "type": "string" + }, + { + "const": "top-empty", + "type": "string" + }, + { + "const": "right-empty", + "type": "string" + }, + { + "const": "bottom-empty", + "type": "string" + }, + { + "const": "left-empty", + "type": "string" + }, + { + "const": "empty", + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to place the mark with respect to facets; one of:\n\n- null (default for most marks) - display the mark in each non-empty facet\n- *top*, *right*, *bottom*, or *left* - display the mark only in facets on the given side\n- *top-empty*, *right-empty*, *bottom-empty*, or *left-empty* (default for axis marks) - display the mark only in facets that have empty space on the given side: either the margin, or an empty facet\n- *empty* - display the mark in empty facets only" + }, + "fill": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The fill, typically bound to the *color* scale. Can be specified as a constant or a channel based on the input data. Use the special value `\"density\"` to map computed density values to pixel colors. Use an aggregate expression to instead visualize an aggregate value per raster bin. If fill is set to a constant color or to a non-aggregate field, opacity will be used to convey densities. If a non-aggregate (group by) field is provided, multiple rasters are created with a unique categorical color per layer." + }, + "fillOpacity": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The opacity, typically bound to the *opacity* scale. Can be specified as a constant or a channel based on the input data. Use the special value `\"density\"` to map computed density values to opacity. Use an aggregate expression to instead visualize an aggregate value per raster bin." + }, + "filter": { + "$ref": "#/definitions/ChannelValue", + "description": "Applies a transform to filter the mark’s index according to the given channel values; only truthy values are retained.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "fx": { + "$ref": "#/definitions/ChannelValue", + "description": "The horizontal facet position channel, for mark-level faceting, bound to the *fx* scale." + }, + "fy": { + "$ref": "#/definitions/ChannelValue", + "description": "The vertical facet position channel, for mark-level faceting, bound to the\n*fy* scale." + }, + "height": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The height (number of rows) of the grid, in actual pixels." + }, + "href": { + "$ref": "#/definitions/ChannelValue", + "description": "The [href][1]; a channel specifying URLs for clickable links. May be used in conjunction with the **target** option to open links in another window.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/href" + }, + "imageFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A CSS [filter][1]; a constant string used to adjust the rendering of images, such as *blur(5px)*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/filter" + }, + "imageRendering": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [image-rendering attribute][1]; defaults to *auto* (bilinear). The option may be set to *pixelated* to disable bilinear interpolation for a sharper image; however, note that this is not supported in WebKit.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/image-rendering" + }, + "interpolate": { + "anyOf": [ + { + "$ref": "#/definitions/GridInterpolate" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The spatial interpolation method; one of:\n\n- *none* - do not perform interpolation (the default), maps samples to single bins\n- *linear* - apply proportional linear interpolation across adjacent bins\n- *nearest* - assign each pixel to the closest sample’s value (Voronoi diagram)\n- *barycentric* - apply barycentric interpolation over the Delaunay triangulation\n- *random-walk* - apply a random walk from each pixel, stopping when near a sample" + }, + "margin": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four mark margins: **marginTop**,\n**marginRight**, **marginBottom**, and **marginLeft**; typically defaults to 0, except for axis marks." + }, + "marginBottom": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s bottom margin; the minimum distance in pixels between the bottom edges of the inner and outer plot area." + }, + "marginLeft": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s left margin; the minimum distance in pixels between the left edges of the inner and outer plot area." + }, + "marginRight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s right margin; the minimum distance in pixels between the right edges of the mark’s inner and outer plot area." + }, + "marginTop": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s top margin; the minimum distance in pixels between the top edges of the inner and outer plot area." + }, + "mark": { + "const": "heatmap", + "description": "Like raster, but with default options for accurate density estimation via smoothing. The *bandwidth* (20), *interpolate* (\"linear\"), and\n*pixelSize* (2) options are set to produce smoothed density heatmaps.", + "type": "string" + }, + "mixBlendMode": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [mix-blend-mode][1]; a constant string specifying how to blend content such as *multiply*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode" + }, + "opacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally. For faster rendering, prefer the **strokeOpacity** or **fillOpacity** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/opacity" + }, + "pad": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The bin padding, one of 1 (default) to include extra padding for the final bin, or 0 to make the bins flush with the maximum domain value." + }, + "paintOrder": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [paint-order][1]; a constant string specifying the order in which the\n**fill**, **stroke**, and any markers are drawn; defaults to *normal*, which draws the fill, then stroke, then markers; defaults to *stroke* for the text mark to create a “halo” around text to improve legibility.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/paint-order" + }, + "pixelSize": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The effective screen size of a raster pixel, used to determine the height and width of the raster from the frame’s dimensions; defaults to 1." + }, + "pointerEvents": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [pointer-events][1] property; a constant string such as *none*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/pointer-events" + }, + "reverse": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Applies a transform to reverse the order of the mark’s index, say for reverse input order." + }, + "select": { + "$ref": "#/definitions/SelectFilter", + "description": "Applies a filter transform after data is loaded to highlight selected values only. For example, `first` and `last` select the first or last values of series only (using the *z* channel to separate series). Meanwhile, `nearestX` and `nearestY` select the point nearest to the pointer along the *x* or *y* channel dimension. Unlike Mosaic selections, a mark level *select* is internal to the mark only, and does not populate a param or selection value to be shared across clients.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "shapeRendering": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [shape-rendering][1]; a constant string such as *crispEdges*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/shape-rendering" + }, + "sort": { + "anyOf": [ + { + "$ref": "#/definitions/SortOrder" + }, + { + "$ref": "#/definitions/ChannelDomainSort" + } + ], + "description": "Either applies a transform to sort the mark’s index by the specified channel values, or imputes ordinal scale domains from this mark’s channels.\n\nWhen imputing ordinal scale domains from channel values, the **sort** option is an object whose keys are ordinal scale names such as *x* or *fx*, and whose values are channel names such as *y*, *y1*, or *y2*. For example, to impute the *y* scale’s domain from the associated *x* channel values in ascending order:\n\n```js sort: {y: \"x\"} ```\n\nFor different sort options for different scales, replace the channel name with a *value* object and per-scale options:\n\n```js sort: {y: {value: \"-x\"}} ```\n\nWhen sorting the mark’s index, the **sort** option is instead one of:\n\n- a channel value definition for sorting given values in ascending order\n- a {value, order} object for sorting given values\n- a {channel, order} object for sorting the named channel’s values" + }, + "stroke": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke" + }, + "strokeDasharray": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dasharray][1]; a constant number indicating the length in pixels of alternating dashes and gaps, or a constant string of numbers separated by spaces or commas (_e.g._, *10 2* for dashes of 10 pixels separated by gaps of 2 pixels), or *none* (the default) for no dashing\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dasharray" + }, + "strokeDashoffset": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dashoffset][1]; a constant indicating the offset in pixels of the first dash along the stroke; defaults to zero.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dashoffset" + }, + "strokeLinecap": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linecap][1]; a constant specifying how to cap stroked paths, such as *butt*, *round*, or *square*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linecap" + }, + "strokeLinejoin": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linejoin][1]; a constant specifying how to join stroked paths, such as *bevel*, *miter*, *miter-clip*, or *round*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linejoin" + }, + "strokeMiterlimit": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-miterlimit][1]; a constant number specifying how to limit the length of *miter* joins on stroked paths.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-miterlimit" + }, + "strokeOpacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-opacity" + }, + "strokeWidth": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-width][1]; a constant number in pixels, or a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-width" + }, + "target": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [target][1]; a constant string specifying the target window (_e.g._,\n*_blank*) for clickable links; used in conjunction with the **href** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/target" + }, + "tip": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/TipPointer" + }, + { + "properties": { + "anchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The tip anchor specifies how to orient the tip box relative to its anchor position; it refers to the part of the tip box that is attached to the anchor point. For example, the *top-left* anchor places the top-left corner of tip box near the anchor position, hence placing the tip box below and to the right of the anchor position." + }, + "fontFamily": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font-family][1]; a constant; defaults to the plot’s font family, which is typically [*system-ui*][2].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-family [2]: https://drafts.csswg.org/css-fonts-4/#valdef-font-family-system-ui" + }, + "fontSize": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font size][1] in pixels; either a constant or a channel; defaults to the plot’s font size, which is typically 10. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-size" + }, + "fontStyle": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font style][1]; a constant; defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-style" + }, + "fontVariant": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font variant][1]; a constant; if the **text** channel contains numbers or dates, defaults to *tabular-nums* to facilitate comparing numbers; otherwise defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant" + }, + "fontWeight": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font weight][1]; a constant; defaults to the plot’s font weight, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight" + }, + "format": { + "additionalProperties": false, + "description": "How channel values are formatted for display. If a format is a string, it is interpreted as a (UTC) time format for temporal channels, and otherwise a number format.", + "properties": { + "ariaLabel": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fill": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fillOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fontSize": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fx": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fy": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "geometry": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "height": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "href": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "length": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "opacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "path": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "r": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "rotate": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "src": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "stroke": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeWidth": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "symbol": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "text": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "title": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "weight": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "width": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "z": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + } + }, + "type": "object" + }, + "frameAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The frame anchor specifies defaults for **x** and **y** based on the plot’s frame; it may be one of the four sides (*top*, *right*, *bottom*, *left*), one of the four corners (*top-left*, *top-right*, *bottom-right*,\n*bottom-left*), or the *middle* of the frame. For example, for tips distributed horizontally at the top of the frame:\n\n```js Plot.tip(data, {x: \"date\", frameAnchor: \"top\"}) ```" + }, + "lineHeight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line height in ems; defaults to 1. The line height affects the (typically vertical) separation between adjacent baselines of text, as well as the separation between the text and its anchor point." + }, + "lineWidth": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line width in ems (e.g., 10 for about 20 characters); defaults to infinity, disabling wrapping and clipping.\n\nIf **textOverflow** is null, lines will be wrapped at the specified length. If a line is split at a soft hyphen (\\xad), a hyphen (-) will be displayed at the end of the line. If **textOverflow** is not null, lines will be clipped according to the given strategy." + }, + "monospace": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, changes the default **fontFamily** to *monospace*, and uses simplified monospaced text metrics calculations." + }, + "pathFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The image filter for the tip’s box; defaults to a drop shadow." + }, + "pointer": { + "$ref": "#/definitions/TipPointer" + }, + "pointerSize": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The size of the tip’s pointer in pixels; defaults to 12." + }, + "preferredAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If an explicit tip anchor is not specified, an anchor is chosen automatically such that the tip fits within the plot’s frame; if the preferred anchor fits, it is chosen." + }, + "textAnchor": { + "anyOf": [ + { + "const": "start", + "type": "string" + }, + { + "const": "middle", + "type": "string" + }, + { + "const": "end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [text anchor][1] controls how text is aligned (typically horizontally) relative to its anchor point; it is one of *start*, *end*, or *middle*. If the frame anchor is *left*, *top-left*, or *bottom-left*, the default text anchor is *start*; if the frame anchor is *right*, *top-right*, or\n*bottom-right*, the default is *end*; otherwise it is *middle*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/text-anchor" + }, + "textOverflow": { + "anyOf": [ + { + "type": "null" + }, + { + "const": "clip", + "type": "string" + }, + { + "const": "ellipsis", + "type": "string" + }, + { + "const": "clip-start", + "type": "string" + }, + { + "const": "clip-end", + "type": "string" + }, + { + "const": "ellipsis-start", + "type": "string" + }, + { + "const": "ellipsis-middle", + "type": "string" + }, + { + "const": "ellipsis-end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How truncate (or wrap) lines of text longer than the given **lineWidth**; one of:\n\n- null (default) - preserve overflowing characters (and wrap if needed)\n- *clip* or *clip-end* - remove characters from the end\n- *clip-start* - remove characters from the start\n- *ellipsis* or *ellipsis-end* - replace characters from the end with an ellipsis (…)\n- *ellipsis-start* - replace characters from the start with an ellipsis (…)\n- *ellipsis-middle* - replace characters from the middle with an ellipsis (…)\n\nIf no **title** was specified, if text requires truncation, a title containing the non-truncated text will be implicitly added." + }, + "textPadding": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The padding around the text in pixels; defaults to 8." + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + } + }, + "type": "object" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to generate a tooltip for this mark, and any tip options." + }, + "title": { + "$ref": "#/definitions/ChannelValue", + "description": "The title; a channel specifying accessible, short textual descriptions as strings (possibly with newlines). If the tip option is specified, the title will be displayed with an interactive tooltip instead of using the SVG [title element][1].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/title" + }, + "width": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The width (number of columns) of the grid, in actual pixels." + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel, typically bound to the *x* scale. Domain values are binned into a grid with *width* horizontal bins." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel, typically bound to the *y* scale. Domain values are binned into a grid with *height* vertical bins." + } + }, + "required": [ + "data", + "mark" + ], + "type": "object" + }, + "Hexagon": { + "additionalProperties": false, + "description": "The hexagon mark.", + "properties": { + "ariaDescription": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-description][1]; a constant textual description.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-description" + }, + "ariaHidden": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-hidden][1] state; a constant indicating whether the element is exposed to an accessibility API.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-hidden" + }, + "ariaLabel": { + "$ref": "#/definitions/ChannelValue", + "description": "The [aria-label][1]; a channel specifying short textual labels representing the value in the accessibility tree.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-label" + }, + "clip": { + "anyOf": [ + { + "const": "frame", + "type": "string" + }, + { + "const": "sphere", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to clip the mark; one of:\n\n- *frame* or true - clip to the plot’s frame (inner area)\n- *sphere* - clip to the projected sphere (*e.g.*, front hemisphere)\n- null or false - do not clip\n\nThe *sphere* clip option requires a geographic projection." + }, + "data": { + "$ref": "#/definitions/PlotMarkData", + "description": "The data source for the mark." + }, + "dx": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The horizontal offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "dy": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The vertical offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "facet": { + "anyOf": [ + { + "const": "auto", + "type": "string" + }, + { + "const": "include", + "type": "string" + }, + { + "const": "exclude", + "type": "string" + }, + { + "const": "super", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to enable or disable faceting; one of:\n\n- *auto* (default) - automatically determine if this mark should be faceted\n- *include* (or true) - draw the subset of the mark’s data in the current facet\n- *exclude* - draw the subset of the mark’s data *not* in the current facet\n- *super* - draw this mark in a single frame that covers all facets\n- null (or false) - repeat this mark’s data across all facets (*i.e.*, no faceting)\n\nWhen a mark uses *super* faceting, it is not allowed to use position scales (*x*, *y*, *fx*, or *fy*); *super* faceting is intended for decorations, such as labels and legends.\n\nWhen top-level faceting is used, the default *auto* setting is equivalent to *include* when the mark data is strictly equal to the top-level facet data; otherwise it is equivalent to null. When the *include* or *exclude* facet mode is chosen, the mark data must be parallel to the top-level facet data: the data must have the same length and order. If the data are not parallel, then the wrong data may be shown in each facet. The default\n*auto* therefore requires strict equality (`===`) for safety, and using the facet data as mark data is recommended when using the *exclude* facet mode. (To construct parallel data safely, consider using [*array*.map][1] on the facet data.)\n\nWhen mark-level faceting is used, the default *auto* setting is equivalent to *include*: the mark will be faceted if either the **fx** or **fy** channel option (or both) is specified. The null or false option will disable faceting, while *exclude* draws the subset of the mark’s data *not* in the current facet.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map" + }, + "facetAnchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "right", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "const": "left", + "type": "string" + }, + { + "const": "top-left", + "type": "string" + }, + { + "const": "top-right", + "type": "string" + }, + { + "const": "bottom-left", + "type": "string" + }, + { + "const": "bottom-right", + "type": "string" + }, + { + "const": "top-empty", + "type": "string" + }, + { + "const": "right-empty", + "type": "string" + }, + { + "const": "bottom-empty", + "type": "string" + }, + { + "const": "left-empty", + "type": "string" + }, + { + "const": "empty", + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to place the mark with respect to facets; one of:\n\n- null (default for most marks) - display the mark in each non-empty facet\n- *top*, *right*, *bottom*, or *left* - display the mark only in facets on the given side\n- *top-empty*, *right-empty*, *bottom-empty*, or *left-empty* (default for axis marks) - display the mark only in facets that have empty space on the given side: either the margin, or an empty facet\n- *empty* - display the mark in empty facets only" + }, + "fill": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill" + }, + "fillOpacity": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill-opacity][1]; a constant number between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill-opacity" + }, + "filter": { + "$ref": "#/definitions/ChannelValue", + "description": "Applies a transform to filter the mark’s index according to the given channel values; only truthy values are retained.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "frameAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The frame anchor specifies defaults for **x** and **y** based on the plot’s frame; it may be one of the four sides (*top*, *right*, *bottom*, *left*), one of the four corners (*top-left*, *top-right*, *bottom-right*,\n*bottom-left*), or the *middle* of the frame. For example, for dots distributed horizontally at the top of the frame:\n\n```js Plot.dot(data, {x: \"date\", frameAnchor: \"top\"}) ```" + }, + "fx": { + "$ref": "#/definitions/ChannelValue", + "description": "The horizontal facet position channel, for mark-level faceting, bound to the *fx* scale." + }, + "fy": { + "$ref": "#/definitions/ChannelValue", + "description": "The vertical facet position channel, for mark-level faceting, bound to the\n*fy* scale." + }, + "href": { + "$ref": "#/definitions/ChannelValue", + "description": "The [href][1]; a channel specifying URLs for clickable links. May be used in conjunction with the **target** option to open links in another window.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/href" + }, + "imageFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A CSS [filter][1]; a constant string used to adjust the rendering of images, such as *blur(5px)*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/filter" + }, + "margin": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four mark margins: **marginTop**,\n**marginRight**, **marginBottom**, and **marginLeft**; typically defaults to 0, except for axis marks." + }, + "marginBottom": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s bottom margin; the minimum distance in pixels between the bottom edges of the inner and outer plot area." + }, + "marginLeft": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s left margin; the minimum distance in pixels between the left edges of the inner and outer plot area." + }, + "marginRight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s right margin; the minimum distance in pixels between the right edges of the mark’s inner and outer plot area." + }, + "marginTop": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s top margin; the minimum distance in pixels between the top edges of the inner and outer plot area." + }, + "mark": { + "const": "hexagon", + "description": "Like dot, except that the **symbol** option is set to *hexagon*.", + "type": "string" + }, + "mixBlendMode": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [mix-blend-mode][1]; a constant string specifying how to blend content such as *multiply*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode" + }, + "opacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally. For faster rendering, prefer the **strokeOpacity** or **fillOpacity** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/opacity" + }, + "paintOrder": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [paint-order][1]; a constant string specifying the order in which the\n**fill**, **stroke**, and any markers are drawn; defaults to *normal*, which draws the fill, then stroke, then markers; defaults to *stroke* for the text mark to create a “halo” around text to improve legibility.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/paint-order" + }, + "pointerEvents": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [pointer-events][1] property; a constant string such as *none*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/pointer-events" + }, + "r": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The radius of dots; either a channel or constant. When a number, it is interpreted as a constant radius in pixels. Otherwise it is interpreted as a channel, typically bound to the *r* channel, which defaults to the *sqrt* type for proportional symbols. The radius defaults to 4.5 pixels when using the **symbol** channel, and otherwise 3 pixels. Dots with a nonpositive radius are not drawn." + }, + "reverse": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Applies a transform to reverse the order of the mark’s index, say for reverse input order." + }, + "rotate": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The rotation angle of dots in degrees clockwise; either a channel or a constant. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel. Defaults to 0°, pointing up." + }, + "select": { + "$ref": "#/definitions/SelectFilter", + "description": "Applies a filter transform after data is loaded to highlight selected values only. For example, `first` and `last` select the first or last values of series only (using the *z* channel to separate series). Meanwhile, `nearestX` and `nearestY` select the point nearest to the pointer along the *x* or *y* channel dimension. Unlike Mosaic selections, a mark level *select* is internal to the mark only, and does not populate a param or selection value to be shared across clients.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "shapeRendering": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [shape-rendering][1]; a constant string such as *crispEdges*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/shape-rendering" + }, + "sort": { + "anyOf": [ + { + "$ref": "#/definitions/SortOrder" + }, + { + "$ref": "#/definitions/ChannelDomainSort" + } + ], + "description": "Either applies a transform to sort the mark’s index by the specified channel values, or imputes ordinal scale domains from this mark’s channels.\n\nWhen imputing ordinal scale domains from channel values, the **sort** option is an object whose keys are ordinal scale names such as *x* or *fx*, and whose values are channel names such as *y*, *y1*, or *y2*. For example, to impute the *y* scale’s domain from the associated *x* channel values in ascending order:\n\n```js sort: {y: \"x\"} ```\n\nFor different sort options for different scales, replace the channel name with a *value* object and per-scale options:\n\n```js sort: {y: {value: \"-x\"}} ```\n\nWhen sorting the mark’s index, the **sort** option is instead one of:\n\n- a channel value definition for sorting given values in ascending order\n- a {value, order} object for sorting given values\n- a {channel, order} object for sorting the named channel’s values" + }, + "stroke": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke" + }, + "strokeDasharray": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dasharray][1]; a constant number indicating the length in pixels of alternating dashes and gaps, or a constant string of numbers separated by spaces or commas (_e.g._, *10 2* for dashes of 10 pixels separated by gaps of 2 pixels), or *none* (the default) for no dashing\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dasharray" + }, + "strokeDashoffset": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dashoffset][1]; a constant indicating the offset in pixels of the first dash along the stroke; defaults to zero.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dashoffset" + }, + "strokeLinecap": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linecap][1]; a constant specifying how to cap stroked paths, such as *butt*, *round*, or *square*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linecap" + }, + "strokeLinejoin": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linejoin][1]; a constant specifying how to join stroked paths, such as *bevel*, *miter*, *miter-clip*, or *round*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linejoin" + }, + "strokeMiterlimit": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-miterlimit][1]; a constant number specifying how to limit the length of *miter* joins on stroked paths.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-miterlimit" + }, + "strokeOpacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-opacity" + }, + "strokeWidth": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-width][1]; a constant number in pixels, or a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-width" + }, + "symbol": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/SymbolType" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The categorical symbol; either a channel or a constant. A constant symbol can be specified by a valid symbol name such as *star*, or a symbol object (implementing the draw method); otherwise it is interpreted as a channel. Defaults to *circle* for the **dot** mark, and *hexagon* for the\n**hexagon** mark.\n\nIf the **symbol** channel’s values are all symbols, symbol names, or nullish, the channel is unscaled (values are interpreted literally); otherwise, the channel is bound to the *symbol* scale." + }, + "target": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [target][1]; a constant string specifying the target window (_e.g._,\n*_blank*) for clickable links; used in conjunction with the **href** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/target" + }, + "tip": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/TipPointer" + }, + { + "properties": { + "anchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The tip anchor specifies how to orient the tip box relative to its anchor position; it refers to the part of the tip box that is attached to the anchor point. For example, the *top-left* anchor places the top-left corner of tip box near the anchor position, hence placing the tip box below and to the right of the anchor position." + }, + "fontFamily": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font-family][1]; a constant; defaults to the plot’s font family, which is typically [*system-ui*][2].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-family [2]: https://drafts.csswg.org/css-fonts-4/#valdef-font-family-system-ui" + }, + "fontSize": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font size][1] in pixels; either a constant or a channel; defaults to the plot’s font size, which is typically 10. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-size" + }, + "fontStyle": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font style][1]; a constant; defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-style" + }, + "fontVariant": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font variant][1]; a constant; if the **text** channel contains numbers or dates, defaults to *tabular-nums* to facilitate comparing numbers; otherwise defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant" + }, + "fontWeight": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font weight][1]; a constant; defaults to the plot’s font weight, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight" + }, + "format": { + "additionalProperties": false, + "description": "How channel values are formatted for display. If a format is a string, it is interpreted as a (UTC) time format for temporal channels, and otherwise a number format.", + "properties": { + "ariaLabel": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fill": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fillOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fontSize": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fx": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fy": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "geometry": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "height": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "href": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "length": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "opacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "path": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "r": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "rotate": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "src": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "stroke": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeWidth": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "symbol": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "text": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "title": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "weight": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "width": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "z": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + } + }, + "type": "object" + }, + "frameAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The frame anchor specifies defaults for **x** and **y** based on the plot’s frame; it may be one of the four sides (*top*, *right*, *bottom*, *left*), one of the four corners (*top-left*, *top-right*, *bottom-right*,\n*bottom-left*), or the *middle* of the frame. For example, for tips distributed horizontally at the top of the frame:\n\n```js Plot.tip(data, {x: \"date\", frameAnchor: \"top\"}) ```" + }, + "lineHeight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line height in ems; defaults to 1. The line height affects the (typically vertical) separation between adjacent baselines of text, as well as the separation between the text and its anchor point." + }, + "lineWidth": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line width in ems (e.g., 10 for about 20 characters); defaults to infinity, disabling wrapping and clipping.\n\nIf **textOverflow** is null, lines will be wrapped at the specified length. If a line is split at a soft hyphen (\\xad), a hyphen (-) will be displayed at the end of the line. If **textOverflow** is not null, lines will be clipped according to the given strategy." + }, + "monospace": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, changes the default **fontFamily** to *monospace*, and uses simplified monospaced text metrics calculations." + }, + "pathFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The image filter for the tip’s box; defaults to a drop shadow." + }, + "pointer": { + "$ref": "#/definitions/TipPointer" + }, + "pointerSize": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The size of the tip’s pointer in pixels; defaults to 12." + }, + "preferredAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If an explicit tip anchor is not specified, an anchor is chosen automatically such that the tip fits within the plot’s frame; if the preferred anchor fits, it is chosen." + }, + "textAnchor": { + "anyOf": [ + { + "const": "start", + "type": "string" + }, + { + "const": "middle", + "type": "string" + }, + { + "const": "end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [text anchor][1] controls how text is aligned (typically horizontally) relative to its anchor point; it is one of *start*, *end*, or *middle*. If the frame anchor is *left*, *top-left*, or *bottom-left*, the default text anchor is *start*; if the frame anchor is *right*, *top-right*, or\n*bottom-right*, the default is *end*; otherwise it is *middle*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/text-anchor" + }, + "textOverflow": { + "anyOf": [ + { + "type": "null" + }, + { + "const": "clip", + "type": "string" + }, + { + "const": "ellipsis", + "type": "string" + }, + { + "const": "clip-start", + "type": "string" + }, + { + "const": "clip-end", + "type": "string" + }, + { + "const": "ellipsis-start", + "type": "string" + }, + { + "const": "ellipsis-middle", + "type": "string" + }, + { + "const": "ellipsis-end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How truncate (or wrap) lines of text longer than the given **lineWidth**; one of:\n\n- null (default) - preserve overflowing characters (and wrap if needed)\n- *clip* or *clip-end* - remove characters from the end\n- *clip-start* - remove characters from the start\n- *ellipsis* or *ellipsis-end* - replace characters from the end with an ellipsis (…)\n- *ellipsis-start* - replace characters from the start with an ellipsis (…)\n- *ellipsis-middle* - replace characters from the middle with an ellipsis (…)\n\nIf no **title** was specified, if text requires truncation, a title containing the non-truncated text will be implicitly added." + }, + "textPadding": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The padding around the text in pixels; defaults to 8." + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + } + }, + "type": "object" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to generate a tooltip for this mark, and any tip options." + }, + "title": { + "$ref": "#/definitions/ChannelValue", + "description": "The title; a channel specifying accessible, short textual descriptions as strings (possibly with newlines). If the tip option is specified, the title will be displayed with an interactive tooltip instead of using the SVG [title element][1].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/title" + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel specifying the dot’s center, typically bound to the *x* scale." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel specifying the dot’s center, typically bound to the *y* scale." + }, + "z": { + "$ref": "#/definitions/ChannelValue", + "description": "An optional ordinal channel for grouping data into series." + } + }, + "required": [ + "data", + "mark" + ], + "type": "object" + }, + "Hexbin": { + "additionalProperties": false, + "description": "The hexbin mark.", + "properties": { + "ariaDescription": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-description][1]; a constant textual description.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-description" + }, + "ariaHidden": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-hidden][1] state; a constant indicating whether the element is exposed to an accessibility API.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-hidden" + }, + "ariaLabel": { + "$ref": "#/definitions/ChannelValue", + "description": "The [aria-label][1]; a channel specifying short textual labels representing the value in the accessibility tree.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-label" + }, + "binWidth": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The distance between centers of neighboring hexagons, in pixels; defaults to 20. If also using a hexgrid mark, use matching **binWidth** values." + }, + "clip": { + "anyOf": [ + { + "const": "frame", + "type": "string" + }, + { + "const": "sphere", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to clip the mark; one of:\n\n- *frame* or true - clip to the plot’s frame (inner area)\n- *sphere* - clip to the projected sphere (*e.g.*, front hemisphere)\n- null or false - do not clip\n\nThe *sphere* clip option requires a geographic projection." + }, + "data": { + "$ref": "#/definitions/PlotMarkData", + "description": "The data source for the mark." + }, + "dx": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The horizontal offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "dy": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The vertical offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "facet": { + "anyOf": [ + { + "const": "auto", + "type": "string" + }, + { + "const": "include", + "type": "string" + }, + { + "const": "exclude", + "type": "string" + }, + { + "const": "super", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to enable or disable faceting; one of:\n\n- *auto* (default) - automatically determine if this mark should be faceted\n- *include* (or true) - draw the subset of the mark’s data in the current facet\n- *exclude* - draw the subset of the mark’s data *not* in the current facet\n- *super* - draw this mark in a single frame that covers all facets\n- null (or false) - repeat this mark’s data across all facets (*i.e.*, no faceting)\n\nWhen a mark uses *super* faceting, it is not allowed to use position scales (*x*, *y*, *fx*, or *fy*); *super* faceting is intended for decorations, such as labels and legends.\n\nWhen top-level faceting is used, the default *auto* setting is equivalent to *include* when the mark data is strictly equal to the top-level facet data; otherwise it is equivalent to null. When the *include* or *exclude* facet mode is chosen, the mark data must be parallel to the top-level facet data: the data must have the same length and order. If the data are not parallel, then the wrong data may be shown in each facet. The default\n*auto* therefore requires strict equality (`===`) for safety, and using the facet data as mark data is recommended when using the *exclude* facet mode. (To construct parallel data safely, consider using [*array*.map][1] on the facet data.)\n\nWhen mark-level faceting is used, the default *auto* setting is equivalent to *include*: the mark will be faceted if either the **fx** or **fy** channel option (or both) is specified. The null or false option will disable faceting, while *exclude* draws the subset of the mark’s data *not* in the current facet.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map" + }, + "facetAnchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "right", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "const": "left", + "type": "string" + }, + { + "const": "top-left", + "type": "string" + }, + { + "const": "top-right", + "type": "string" + }, + { + "const": "bottom-left", + "type": "string" + }, + { + "const": "bottom-right", + "type": "string" + }, + { + "const": "top-empty", + "type": "string" + }, + { + "const": "right-empty", + "type": "string" + }, + { + "const": "bottom-empty", + "type": "string" + }, + { + "const": "left-empty", + "type": "string" + }, + { + "const": "empty", + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to place the mark with respect to facets; one of:\n\n- null (default for most marks) - display the mark in each non-empty facet\n- *top*, *right*, *bottom*, or *left* - display the mark only in facets on the given side\n- *top-empty*, *right-empty*, *bottom-empty*, or *left-empty* (default for axis marks) - display the mark only in facets that have empty space on the given side: either the margin, or an empty facet\n- *empty* - display the mark in empty facets only" + }, + "fill": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill" + }, + "fillOpacity": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill-opacity][1]; a constant number between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill-opacity" + }, + "filter": { + "$ref": "#/definitions/ChannelValue", + "description": "Applies a transform to filter the mark’s index according to the given channel values; only truthy values are retained.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "fontFamily": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font-family][1]; a constant; defaults to the plot’s font family, which is typically [*system-ui*][2].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-family [2]: https://drafts.csswg.org/css-fonts-4/#valdef-font-family-system-ui" + }, + "fontSize": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font size][1] in pixels; either a constant or a channel; defaults to the plot’s font size, which is typically 10. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-size" + }, + "fontStyle": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font style][1]; a constant; defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-style" + }, + "fontVariant": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font variant][1]; a constant; if the **text** channel contains numbers or dates, defaults to *tabular-nums* to facilitate comparing numbers; otherwise defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant" + }, + "fontWeight": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font weight][1]; a constant; defaults to the plot’s font weight, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight" + }, + "frameAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The frame anchor specifies defaults for **x** and **y** based on the plot’s frame; it may be one of the four sides (*top*, *right*, *bottom*, *left*), one of the four corners (*top-left*, *top-right*, *bottom-right*,\n*bottom-left*), or the *middle* of the frame. For example, for dots distributed horizontally at the top of the frame:\n\n```js Plot.dot(data, {x: \"date\", frameAnchor: \"top\"}) ```" + }, + "fx": { + "$ref": "#/definitions/ChannelValue", + "description": "The horizontal facet position channel, for mark-level faceting, bound to the *fx* scale." + }, + "fy": { + "$ref": "#/definitions/ChannelValue", + "description": "The vertical facet position channel, for mark-level faceting, bound to the\n*fy* scale." + }, + "href": { + "$ref": "#/definitions/ChannelValue", + "description": "The [href][1]; a channel specifying URLs for clickable links. May be used in conjunction with the **target** option to open links in another window.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/href" + }, + "imageFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A CSS [filter][1]; a constant string used to adjust the rendering of images, such as *blur(5px)*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/filter" + }, + "lineHeight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line height in ems; defaults to 1. The line height affects the (typically vertical) separation between adjacent baselines of text, as well as the separation between the text and its anchor point." + }, + "lineWidth": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line width in ems (e.g., 10 for about 20 characters); defaults to infinity, disabling wrapping and clipping.\n\nIf **textOverflow** is null, lines will be wrapped at the specified length. If a line is split at a soft hyphen (\\xad), a hyphen (-) will be displayed at the end of the line. If **textOverflow** is not null, lines will be clipped according to the given strategy." + }, + "margin": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four mark margins: **marginTop**,\n**marginRight**, **marginBottom**, and **marginLeft**; typically defaults to 0, except for axis marks." + }, + "marginBottom": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s bottom margin; the minimum distance in pixels between the bottom edges of the inner and outer plot area." + }, + "marginLeft": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s left margin; the minimum distance in pixels between the left edges of the inner and outer plot area." + }, + "marginRight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s right margin; the minimum distance in pixels between the right edges of the mark’s inner and outer plot area." + }, + "marginTop": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s top margin; the minimum distance in pixels between the top edges of the inner and outer plot area." + }, + "mark": { + "const": "hexbin", + "description": "A hexbin mark that bins **x** and **y** data into a hexagonal grid and visualizes aggregate functions per bin (e.g., count for binned density). Aggregate functions can be used for fill, stroke, or r (radius) options.", + "type": "string" + }, + "mixBlendMode": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [mix-blend-mode][1]; a constant string specifying how to blend content such as *multiply*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode" + }, + "monospace": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, changes the default **fontFamily** to *monospace*, and uses simplified monospaced text metrics calculations." + }, + "opacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally. For faster rendering, prefer the **strokeOpacity** or **fillOpacity** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/opacity" + }, + "paintOrder": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [paint-order][1]; a constant string specifying the order in which the\n**fill**, **stroke**, and any markers are drawn; defaults to *normal*, which draws the fill, then stroke, then markers; defaults to *stroke* for the text mark to create a “halo” around text to improve legibility.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/paint-order" + }, + "pointerEvents": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [pointer-events][1] property; a constant string such as *none*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/pointer-events" + }, + "r": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The radius of dots; either a channel or constant. When a number, it is interpreted as a constant radius in pixels. Otherwise it is interpreted as a channel, typically bound to the *r* channel, which defaults to the *sqrt* type for proportional symbols. The radius defaults to 4.5 pixels when using the **symbol** channel, and otherwise 3 pixels. Dots with a nonpositive radius are not drawn." + }, + "reverse": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Applies a transform to reverse the order of the mark’s index, say for reverse input order." + }, + "rotate": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The rotation angle of dots in degrees clockwise; either a channel or a constant. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel. Defaults to 0°, pointing up." + }, + "select": { + "$ref": "#/definitions/SelectFilter", + "description": "Applies a filter transform after data is loaded to highlight selected values only. For example, `first` and `last` select the first or last values of series only (using the *z* channel to separate series). Meanwhile, `nearestX` and `nearestY` select the point nearest to the pointer along the *x* or *y* channel dimension. Unlike Mosaic selections, a mark level *select* is internal to the mark only, and does not populate a param or selection value to be shared across clients.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "shapeRendering": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [shape-rendering][1]; a constant string such as *crispEdges*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/shape-rendering" + }, + "sort": { + "anyOf": [ + { + "$ref": "#/definitions/SortOrder" + }, + { + "$ref": "#/definitions/ChannelDomainSort" + } + ], + "description": "Either applies a transform to sort the mark’s index by the specified channel values, or imputes ordinal scale domains from this mark’s channels.\n\nWhen imputing ordinal scale domains from channel values, the **sort** option is an object whose keys are ordinal scale names such as *x* or *fx*, and whose values are channel names such as *y*, *y1*, or *y2*. For example, to impute the *y* scale’s domain from the associated *x* channel values in ascending order:\n\n```js sort: {y: \"x\"} ```\n\nFor different sort options for different scales, replace the channel name with a *value* object and per-scale options:\n\n```js sort: {y: {value: \"-x\"}} ```\n\nWhen sorting the mark’s index, the **sort** option is instead one of:\n\n- a channel value definition for sorting given values in ascending order\n- a {value, order} object for sorting given values\n- a {channel, order} object for sorting the named channel’s values" + }, + "stroke": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke" + }, + "strokeDasharray": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dasharray][1]; a constant number indicating the length in pixels of alternating dashes and gaps, or a constant string of numbers separated by spaces or commas (_e.g._, *10 2* for dashes of 10 pixels separated by gaps of 2 pixels), or *none* (the default) for no dashing\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dasharray" + }, + "strokeDashoffset": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dashoffset][1]; a constant indicating the offset in pixels of the first dash along the stroke; defaults to zero.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dashoffset" + }, + "strokeLinecap": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linecap][1]; a constant specifying how to cap stroked paths, such as *butt*, *round*, or *square*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linecap" + }, + "strokeLinejoin": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linejoin][1]; a constant specifying how to join stroked paths, such as *bevel*, *miter*, *miter-clip*, or *round*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linejoin" + }, + "strokeMiterlimit": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-miterlimit][1]; a constant number specifying how to limit the length of *miter* joins on stroked paths.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-miterlimit" + }, + "strokeOpacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-opacity" + }, + "strokeWidth": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-width][1]; a constant number in pixels, or a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-width" + }, + "symbol": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/SymbolType" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The categorical symbol; either a channel or a constant. A constant symbol can be specified by a valid symbol name such as *star*, or a symbol object (implementing the draw method); otherwise it is interpreted as a channel. Defaults to *circle* for the **dot** mark, and *hexagon* for the\n**hexagon** mark.\n\nIf the **symbol** channel’s values are all symbols, symbol names, or nullish, the channel is unscaled (values are interpreted literally); otherwise, the channel is bound to the *symbol* scale." + }, + "target": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [target][1]; a constant string specifying the target window (_e.g._,\n*_blank*) for clickable links; used in conjunction with the **href** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/target" + }, + "textAnchor": { + "anyOf": [ + { + "const": "start", + "type": "string" + }, + { + "const": "middle", + "type": "string" + }, + { + "const": "end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [text anchor][1] controls how text is aligned (typically horizontally) relative to its anchor point; it is one of *start*, *end*, or *middle*. If the frame anchor is *left*, *top-left*, or *bottom-left*, the default text anchor is *start*; if the frame anchor is *right*, *top-right*, or\n*bottom-right*, the default is *end*; otherwise it is *middle*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/text-anchor" + }, + "textOverflow": { + "anyOf": [ + { + "type": "null" + }, + { + "const": "clip", + "type": "string" + }, + { + "const": "ellipsis", + "type": "string" + }, + { + "const": "clip-start", + "type": "string" + }, + { + "const": "clip-end", + "type": "string" + }, + { + "const": "ellipsis-start", + "type": "string" + }, + { + "const": "ellipsis-middle", + "type": "string" + }, + { + "const": "ellipsis-end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How truncate (or wrap) lines of text longer than the given **lineWidth**; one of:\n\n- null (default) - preserve overflowing characters (and wrap if needed)\n- *clip* or *clip-end* - remove characters from the end\n- *clip-start* - remove characters from the start\n- *ellipsis* or *ellipsis-end* - replace characters from the end with an ellipsis (…)\n- *ellipsis-start* - replace characters from the start with an ellipsis (…)\n- *ellipsis-middle* - replace characters from the middle with an ellipsis (…)\n\nIf no **title** was specified, if text requires truncation, a title containing the non-truncated text will be implicitly added." + }, + "tip": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/TipPointer" + }, + { + "properties": { + "anchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The tip anchor specifies how to orient the tip box relative to its anchor position; it refers to the part of the tip box that is attached to the anchor point. For example, the *top-left* anchor places the top-left corner of tip box near the anchor position, hence placing the tip box below and to the right of the anchor position." + }, + "fontFamily": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font-family][1]; a constant; defaults to the plot’s font family, which is typically [*system-ui*][2].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-family [2]: https://drafts.csswg.org/css-fonts-4/#valdef-font-family-system-ui" + }, + "fontSize": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font size][1] in pixels; either a constant or a channel; defaults to the plot’s font size, which is typically 10. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-size" + }, + "fontStyle": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font style][1]; a constant; defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-style" + }, + "fontVariant": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font variant][1]; a constant; if the **text** channel contains numbers or dates, defaults to *tabular-nums* to facilitate comparing numbers; otherwise defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant" + }, + "fontWeight": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font weight][1]; a constant; defaults to the plot’s font weight, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight" + }, + "format": { + "additionalProperties": false, + "description": "How channel values are formatted for display. If a format is a string, it is interpreted as a (UTC) time format for temporal channels, and otherwise a number format.", + "properties": { + "ariaLabel": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fill": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fillOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fontSize": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fx": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fy": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "geometry": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "height": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "href": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "length": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "opacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "path": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "r": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "rotate": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "src": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "stroke": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeWidth": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "symbol": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "text": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "title": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "weight": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "width": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "z": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + } + }, + "type": "object" + }, + "frameAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The frame anchor specifies defaults for **x** and **y** based on the plot’s frame; it may be one of the four sides (*top*, *right*, *bottom*, *left*), one of the four corners (*top-left*, *top-right*, *bottom-right*,\n*bottom-left*), or the *middle* of the frame. For example, for tips distributed horizontally at the top of the frame:\n\n```js Plot.tip(data, {x: \"date\", frameAnchor: \"top\"}) ```" + }, + "lineHeight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line height in ems; defaults to 1. The line height affects the (typically vertical) separation between adjacent baselines of text, as well as the separation between the text and its anchor point." + }, + "lineWidth": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line width in ems (e.g., 10 for about 20 characters); defaults to infinity, disabling wrapping and clipping.\n\nIf **textOverflow** is null, lines will be wrapped at the specified length. If a line is split at a soft hyphen (\\xad), a hyphen (-) will be displayed at the end of the line. If **textOverflow** is not null, lines will be clipped according to the given strategy." + }, + "monospace": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, changes the default **fontFamily** to *monospace*, and uses simplified monospaced text metrics calculations." + }, + "pathFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The image filter for the tip’s box; defaults to a drop shadow." + }, + "pointer": { + "$ref": "#/definitions/TipPointer" + }, + "pointerSize": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The size of the tip’s pointer in pixels; defaults to 12." + }, + "preferredAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If an explicit tip anchor is not specified, an anchor is chosen automatically such that the tip fits within the plot’s frame; if the preferred anchor fits, it is chosen." + }, + "textAnchor": { + "anyOf": [ + { + "const": "start", + "type": "string" + }, + { + "const": "middle", + "type": "string" + }, + { + "const": "end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [text anchor][1] controls how text is aligned (typically horizontally) relative to its anchor point; it is one of *start*, *end*, or *middle*. If the frame anchor is *left*, *top-left*, or *bottom-left*, the default text anchor is *start*; if the frame anchor is *right*, *top-right*, or\n*bottom-right*, the default is *end*; otherwise it is *middle*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/text-anchor" + }, + "textOverflow": { + "anyOf": [ + { + "type": "null" + }, + { + "const": "clip", + "type": "string" + }, + { + "const": "ellipsis", + "type": "string" + }, + { + "const": "clip-start", + "type": "string" + }, + { + "const": "clip-end", + "type": "string" + }, + { + "const": "ellipsis-start", + "type": "string" + }, + { + "const": "ellipsis-middle", + "type": "string" + }, + { + "const": "ellipsis-end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How truncate (or wrap) lines of text longer than the given **lineWidth**; one of:\n\n- null (default) - preserve overflowing characters (and wrap if needed)\n- *clip* or *clip-end* - remove characters from the end\n- *clip-start* - remove characters from the start\n- *ellipsis* or *ellipsis-end* - replace characters from the end with an ellipsis (…)\n- *ellipsis-start* - replace characters from the start with an ellipsis (…)\n- *ellipsis-middle* - replace characters from the middle with an ellipsis (…)\n\nIf no **title** was specified, if text requires truncation, a title containing the non-truncated text will be implicitly added." + }, + "textPadding": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The padding around the text in pixels; defaults to 8." + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + } + }, + "type": "object" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to generate a tooltip for this mark, and any tip options." + }, + "title": { + "$ref": "#/definitions/ChannelValue", + "description": "The title; a channel specifying accessible, short textual descriptions as strings (possibly with newlines). If the tip option is specified, the title will be displayed with an interactive tooltip instead of using the SVG [title element][1].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/title" + }, + "type": { + "anyOf": [ + { + "const": "dot", + "type": "string" + }, + { + "const": "circle", + "type": "string" + }, + { + "const": "hexagon", + "type": "string" + }, + { + "const": "text", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The basic mark type to use for hex-binned values. Defaults to a hexagon mark; dot and text marks are also supported." + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel specifying the dot’s center, typically bound to the *x* scale." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel specifying the dot’s center, typically bound to the *y* scale." + }, + "z": { + "$ref": "#/definitions/ChannelValue", + "description": "How to subdivide bins. If not specified, defaults to the *fill* channel, if any, or the *stroke* channel, if any. If null, bins will not be subdivided." + } + }, + "required": [ + "data", + "mark" + ], + "type": "object" + }, + "Hexgrid": { + "additionalProperties": false, + "description": "The hexgrid mark.", + "properties": { + "ariaDescription": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-description][1]; a constant textual description.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-description" + }, + "ariaHidden": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-hidden][1] state; a constant indicating whether the element is exposed to an accessibility API.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-hidden" + }, + "ariaLabel": { + "$ref": "#/definitions/ChannelValue", + "description": "The [aria-label][1]; a channel specifying short textual labels representing the value in the accessibility tree.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-label" + }, + "binWidth": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The distance between centers of neighboring hexagons, in pixels; defaults to 20. Should match the **binWidth** of the hexbin mark." + }, + "clip": { + "anyOf": [ + { + "const": "frame", + "type": "string" + }, + { + "const": "sphere", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to clip the mark; one of:\n\n- *frame* or true - clip to the plot’s frame (inner area)\n- *sphere* - clip to the projected sphere (*e.g.*, front hemisphere)\n- null or false - do not clip\n\nThe *sphere* clip option requires a geographic projection." + }, + "dx": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The horizontal offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "dy": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The vertical offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "facet": { + "anyOf": [ + { + "const": "auto", + "type": "string" + }, + { + "const": "include", + "type": "string" + }, + { + "const": "exclude", + "type": "string" + }, + { + "const": "super", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to enable or disable faceting; one of:\n\n- *auto* (default) - automatically determine if this mark should be faceted\n- *include* (or true) - draw the subset of the mark’s data in the current facet\n- *exclude* - draw the subset of the mark’s data *not* in the current facet\n- *super* - draw this mark in a single frame that covers all facets\n- null (or false) - repeat this mark’s data across all facets (*i.e.*, no faceting)\n\nWhen a mark uses *super* faceting, it is not allowed to use position scales (*x*, *y*, *fx*, or *fy*); *super* faceting is intended for decorations, such as labels and legends.\n\nWhen top-level faceting is used, the default *auto* setting is equivalent to *include* when the mark data is strictly equal to the top-level facet data; otherwise it is equivalent to null. When the *include* or *exclude* facet mode is chosen, the mark data must be parallel to the top-level facet data: the data must have the same length and order. If the data are not parallel, then the wrong data may be shown in each facet. The default\n*auto* therefore requires strict equality (`===`) for safety, and using the facet data as mark data is recommended when using the *exclude* facet mode. (To construct parallel data safely, consider using [*array*.map][1] on the facet data.)\n\nWhen mark-level faceting is used, the default *auto* setting is equivalent to *include*: the mark will be faceted if either the **fx** or **fy** channel option (or both) is specified. The null or false option will disable faceting, while *exclude* draws the subset of the mark’s data *not* in the current facet.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map" + }, + "facetAnchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "right", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "const": "left", + "type": "string" + }, + { + "const": "top-left", + "type": "string" + }, + { + "const": "top-right", + "type": "string" + }, + { + "const": "bottom-left", + "type": "string" + }, + { + "const": "bottom-right", + "type": "string" + }, + { + "const": "top-empty", + "type": "string" + }, + { + "const": "right-empty", + "type": "string" + }, + { + "const": "bottom-empty", + "type": "string" + }, + { + "const": "left-empty", + "type": "string" + }, + { + "const": "empty", + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to place the mark with respect to facets; one of:\n\n- null (default for most marks) - display the mark in each non-empty facet\n- *top*, *right*, *bottom*, or *left* - display the mark only in facets on the given side\n- *top-empty*, *right-empty*, *bottom-empty*, or *left-empty* (default for axis marks) - display the mark only in facets that have empty space on the given side: either the margin, or an empty facet\n- *empty* - display the mark in empty facets only" + }, + "fill": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill" + }, + "fillOpacity": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill-opacity][1]; a constant number between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill-opacity" + }, + "filter": { + "$ref": "#/definitions/ChannelValue", + "description": "Applies a transform to filter the mark’s index according to the given channel values; only truthy values are retained.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "fx": { + "$ref": "#/definitions/ChannelValue", + "description": "The horizontal facet position channel, for mark-level faceting, bound to the *fx* scale." + }, + "fy": { + "$ref": "#/definitions/ChannelValue", + "description": "The vertical facet position channel, for mark-level faceting, bound to the\n*fy* scale." + }, + "href": { + "$ref": "#/definitions/ChannelValue", + "description": "The [href][1]; a channel specifying URLs for clickable links. May be used in conjunction with the **target** option to open links in another window.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/href" + }, + "imageFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A CSS [filter][1]; a constant string used to adjust the rendering of images, such as *blur(5px)*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/filter" + }, + "margin": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four mark margins: **marginTop**,\n**marginRight**, **marginBottom**, and **marginLeft**; typically defaults to 0, except for axis marks." + }, + "marginBottom": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s bottom margin; the minimum distance in pixels between the bottom edges of the inner and outer plot area." + }, + "marginLeft": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s left margin; the minimum distance in pixels between the left edges of the inner and outer plot area." + }, + "marginRight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s right margin; the minimum distance in pixels between the right edges of the mark’s inner and outer plot area." + }, + "marginTop": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s top margin; the minimum distance in pixels between the top edges of the inner and outer plot area." + }, + "mark": { + "const": "hexgrid", + "description": "The hexgrid decoration mark complements the hexbin mark, showing the outlines of all hexagons spanning the frame with a default **stroke** of\n*currentColor* and a default **strokeOpacity** of 0.1, similar to the default axis grids.\n\nNote that the **binWidth** option of the hexgrid mark should match that of the hexbin transform. The grid is clipped by the frame. This is a stroke-only mark, and **fill** is not supported; to fill the frame, use the frame mark.", + "type": "string" + }, + "mixBlendMode": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [mix-blend-mode][1]; a constant string specifying how to blend content such as *multiply*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode" + }, + "opacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally. For faster rendering, prefer the **strokeOpacity** or **fillOpacity** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/opacity" + }, + "paintOrder": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [paint-order][1]; a constant string specifying the order in which the\n**fill**, **stroke**, and any markers are drawn; defaults to *normal*, which draws the fill, then stroke, then markers; defaults to *stroke* for the text mark to create a “halo” around text to improve legibility.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/paint-order" + }, + "pointerEvents": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [pointer-events][1] property; a constant string such as *none*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/pointer-events" + }, + "reverse": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Applies a transform to reverse the order of the mark’s index, say for reverse input order." + }, + "select": { + "$ref": "#/definitions/SelectFilter", + "description": "Applies a filter transform after data is loaded to highlight selected values only. For example, `first` and `last` select the first or last values of series only (using the *z* channel to separate series). Meanwhile, `nearestX` and `nearestY` select the point nearest to the pointer along the *x* or *y* channel dimension. Unlike Mosaic selections, a mark level *select* is internal to the mark only, and does not populate a param or selection value to be shared across clients.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "shapeRendering": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [shape-rendering][1]; a constant string such as *crispEdges*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/shape-rendering" + }, + "sort": { + "anyOf": [ + { + "$ref": "#/definitions/SortOrder" + }, + { + "$ref": "#/definitions/ChannelDomainSort" + } + ], + "description": "Either applies a transform to sort the mark’s index by the specified channel values, or imputes ordinal scale domains from this mark’s channels.\n\nWhen imputing ordinal scale domains from channel values, the **sort** option is an object whose keys are ordinal scale names such as *x* or *fx*, and whose values are channel names such as *y*, *y1*, or *y2*. For example, to impute the *y* scale’s domain from the associated *x* channel values in ascending order:\n\n```js sort: {y: \"x\"} ```\n\nFor different sort options for different scales, replace the channel name with a *value* object and per-scale options:\n\n```js sort: {y: {value: \"-x\"}} ```\n\nWhen sorting the mark’s index, the **sort** option is instead one of:\n\n- a channel value definition for sorting given values in ascending order\n- a {value, order} object for sorting given values\n- a {channel, order} object for sorting the named channel’s values" + }, + "stroke": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke" + }, + "strokeDasharray": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dasharray][1]; a constant number indicating the length in pixels of alternating dashes and gaps, or a constant string of numbers separated by spaces or commas (_e.g._, *10 2* for dashes of 10 pixels separated by gaps of 2 pixels), or *none* (the default) for no dashing\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dasharray" + }, + "strokeDashoffset": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dashoffset][1]; a constant indicating the offset in pixels of the first dash along the stroke; defaults to zero.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dashoffset" + }, + "strokeLinecap": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linecap][1]; a constant specifying how to cap stroked paths, such as *butt*, *round*, or *square*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linecap" + }, + "strokeLinejoin": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linejoin][1]; a constant specifying how to join stroked paths, such as *bevel*, *miter*, *miter-clip*, or *round*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linejoin" + }, + "strokeMiterlimit": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-miterlimit][1]; a constant number specifying how to limit the length of *miter* joins on stroked paths.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-miterlimit" + }, + "strokeOpacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-opacity" + }, + "strokeWidth": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-width][1]; a constant number in pixels, or a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-width" + }, + "target": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [target][1]; a constant string specifying the target window (_e.g._,\n*_blank*) for clickable links; used in conjunction with the **href** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/target" + }, + "tip": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/TipPointer" + }, + { + "properties": { + "anchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The tip anchor specifies how to orient the tip box relative to its anchor position; it refers to the part of the tip box that is attached to the anchor point. For example, the *top-left* anchor places the top-left corner of tip box near the anchor position, hence placing the tip box below and to the right of the anchor position." + }, + "fontFamily": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font-family][1]; a constant; defaults to the plot’s font family, which is typically [*system-ui*][2].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-family [2]: https://drafts.csswg.org/css-fonts-4/#valdef-font-family-system-ui" + }, + "fontSize": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font size][1] in pixels; either a constant or a channel; defaults to the plot’s font size, which is typically 10. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-size" + }, + "fontStyle": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font style][1]; a constant; defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-style" + }, + "fontVariant": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font variant][1]; a constant; if the **text** channel contains numbers or dates, defaults to *tabular-nums* to facilitate comparing numbers; otherwise defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant" + }, + "fontWeight": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font weight][1]; a constant; defaults to the plot’s font weight, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight" + }, + "format": { + "additionalProperties": false, + "description": "How channel values are formatted for display. If a format is a string, it is interpreted as a (UTC) time format for temporal channels, and otherwise a number format.", + "properties": { + "ariaLabel": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fill": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fillOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fontSize": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fx": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fy": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "geometry": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "height": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "href": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "length": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "opacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "path": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "r": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "rotate": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "src": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "stroke": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeWidth": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "symbol": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "text": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "title": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "weight": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "width": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "z": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + } + }, + "type": "object" + }, + "frameAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The frame anchor specifies defaults for **x** and **y** based on the plot’s frame; it may be one of the four sides (*top*, *right*, *bottom*, *left*), one of the four corners (*top-left*, *top-right*, *bottom-right*,\n*bottom-left*), or the *middle* of the frame. For example, for tips distributed horizontally at the top of the frame:\n\n```js Plot.tip(data, {x: \"date\", frameAnchor: \"top\"}) ```" + }, + "lineHeight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line height in ems; defaults to 1. The line height affects the (typically vertical) separation between adjacent baselines of text, as well as the separation between the text and its anchor point." + }, + "lineWidth": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line width in ems (e.g., 10 for about 20 characters); defaults to infinity, disabling wrapping and clipping.\n\nIf **textOverflow** is null, lines will be wrapped at the specified length. If a line is split at a soft hyphen (\\xad), a hyphen (-) will be displayed at the end of the line. If **textOverflow** is not null, lines will be clipped according to the given strategy." + }, + "monospace": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, changes the default **fontFamily** to *monospace*, and uses simplified monospaced text metrics calculations." + }, + "pathFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The image filter for the tip’s box; defaults to a drop shadow." + }, + "pointer": { + "$ref": "#/definitions/TipPointer" + }, + "pointerSize": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The size of the tip’s pointer in pixels; defaults to 12." + }, + "preferredAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If an explicit tip anchor is not specified, an anchor is chosen automatically such that the tip fits within the plot’s frame; if the preferred anchor fits, it is chosen." + }, + "textAnchor": { + "anyOf": [ + { + "const": "start", + "type": "string" + }, + { + "const": "middle", + "type": "string" + }, + { + "const": "end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [text anchor][1] controls how text is aligned (typically horizontally) relative to its anchor point; it is one of *start*, *end*, or *middle*. If the frame anchor is *left*, *top-left*, or *bottom-left*, the default text anchor is *start*; if the frame anchor is *right*, *top-right*, or\n*bottom-right*, the default is *end*; otherwise it is *middle*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/text-anchor" + }, + "textOverflow": { + "anyOf": [ + { + "type": "null" + }, + { + "const": "clip", + "type": "string" + }, + { + "const": "ellipsis", + "type": "string" + }, + { + "const": "clip-start", + "type": "string" + }, + { + "const": "clip-end", + "type": "string" + }, + { + "const": "ellipsis-start", + "type": "string" + }, + { + "const": "ellipsis-middle", + "type": "string" + }, + { + "const": "ellipsis-end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How truncate (or wrap) lines of text longer than the given **lineWidth**; one of:\n\n- null (default) - preserve overflowing characters (and wrap if needed)\n- *clip* or *clip-end* - remove characters from the end\n- *clip-start* - remove characters from the start\n- *ellipsis* or *ellipsis-end* - replace characters from the end with an ellipsis (…)\n- *ellipsis-start* - replace characters from the start with an ellipsis (…)\n- *ellipsis-middle* - replace characters from the middle with an ellipsis (…)\n\nIf no **title** was specified, if text requires truncation, a title containing the non-truncated text will be implicitly added." + }, + "textPadding": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The padding around the text in pixels; defaults to 8." + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + } + }, + "type": "object" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to generate a tooltip for this mark, and any tip options." + }, + "title": { + "$ref": "#/definitions/ChannelValue", + "description": "The title; a channel specifying accessible, short textual descriptions as strings (possibly with newlines). If the tip option is specified, the title will be displayed with an interactive tooltip instead of using the SVG [title element][1].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/title" + } + }, + "required": [ + "mark" + ], + "type": "object" + }, + "Highlight": { + "additionalProperties": false, + "description": "A highlight interactor.", + "properties": { + "by": { + "$ref": "#/definitions/ParamRef", + "description": "The input selection. Unselected marks are deemphasized." + }, + "fill": { + "description": "The fill color of deemphasized marks. By default the fill is unchanged.", + "type": "string" + }, + "fillOpacity": { + "description": "The fill opacity of deemphasized marks. By default the fill opacity is unchanged.", + "type": "number" + }, + "opacity": { + "description": "The overall opacity of deemphasized marks. By default the opacity is set to 0.2.", + "type": "number" + }, + "select": { + "const": "highlight", + "description": "Highlight selected marks by deemphasizing the others.", + "type": "string" + }, + "stroke": { + "description": "The stroke color of deemphasized marks. By default the stroke is unchanged.", + "type": "string" + }, + "strokeOpacity": { + "description": "The stroke opacity of deemphasized marks. By default the stroke opacity is unchanged.", + "type": "number" + } + }, + "required": [ + "select", + "by" + ], + "type": "object" + }, + "Hull": { + "additionalProperties": false, + "description": "The hull mark.", + "properties": { + "ariaDescription": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-description][1]; a constant textual description.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-description" + }, + "ariaHidden": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-hidden][1] state; a constant indicating whether the element is exposed to an accessibility API.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-hidden" + }, + "ariaLabel": { + "$ref": "#/definitions/ChannelValue", + "description": "The [aria-label][1]; a channel specifying short textual labels representing the value in the accessibility tree.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-label" + }, + "clip": { + "anyOf": [ + { + "const": "frame", + "type": "string" + }, + { + "const": "sphere", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to clip the mark; one of:\n\n- *frame* or true - clip to the plot’s frame (inner area)\n- *sphere* - clip to the projected sphere (*e.g.*, front hemisphere)\n- null or false - do not clip\n\nThe *sphere* clip option requires a geographic projection." + }, + "curve": { + "anyOf": [ + { + "$ref": "#/definitions/Curve" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The curve (interpolation) method for connecting adjacent points. One of:\n\n- *basis* - a cubic basis spline (repeating the end points)\n- *basis-open* - an open cubic basis spline\n- *basis-closed* - a closed cubic basis spline\n- *bump-x* - a Bézier curve with horizontal tangents\n- *bump-y* - a Bézier curve with vertical tangents\n- *bundle* - a straightened cubic basis spline (suitable for lines only, not areas)\n- *cardinal* - a cubic cardinal spline (with one-sided differences at the ends)\n- *cardinal-open* - an open cubic cardinal spline\n- *cardinal-closed* - an closed cubic cardinal spline\n- *catmull-rom* - a cubic Catmull–Rom spline (with one-sided differences at the ends)\n- *catmull-rom-open* - an open cubic Catmull–Rom spline\n- *catmull-rom-closed* - a closed cubic Catmull–Rom spline\n- *linear* - a piecewise linear curve (*i.e.*, straight line segments)\n- *linear-closed* - a closed piecewise linear curve (*i.e.*, straight line segments)\n- *monotone-x* - a cubic spline that preserves monotonicity in *x*\n- *monotone-y* - a cubic spline that preserves monotonicity in *y*\n- *natural* - a natural cubic spline\n- *step* - a piecewise constant function where *y* changes at the midpoint of *x*\n- *step-after* - a piecewise constant function where *y* changes after *x*\n- *step-before* - a piecewise constant function where *x* changes after *y*" + }, + "data": { + "$ref": "#/definitions/PlotMarkData", + "description": "The data source for the mark." + }, + "dx": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The horizontal offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "dy": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The vertical offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "facet": { + "anyOf": [ + { + "const": "auto", + "type": "string" + }, + { + "const": "include", + "type": "string" + }, + { + "const": "exclude", + "type": "string" + }, + { + "const": "super", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to enable or disable faceting; one of:\n\n- *auto* (default) - automatically determine if this mark should be faceted\n- *include* (or true) - draw the subset of the mark’s data in the current facet\n- *exclude* - draw the subset of the mark’s data *not* in the current facet\n- *super* - draw this mark in a single frame that covers all facets\n- null (or false) - repeat this mark’s data across all facets (*i.e.*, no faceting)\n\nWhen a mark uses *super* faceting, it is not allowed to use position scales (*x*, *y*, *fx*, or *fy*); *super* faceting is intended for decorations, such as labels and legends.\n\nWhen top-level faceting is used, the default *auto* setting is equivalent to *include* when the mark data is strictly equal to the top-level facet data; otherwise it is equivalent to null. When the *include* or *exclude* facet mode is chosen, the mark data must be parallel to the top-level facet data: the data must have the same length and order. If the data are not parallel, then the wrong data may be shown in each facet. The default\n*auto* therefore requires strict equality (`===`) for safety, and using the facet data as mark data is recommended when using the *exclude* facet mode. (To construct parallel data safely, consider using [*array*.map][1] on the facet data.)\n\nWhen mark-level faceting is used, the default *auto* setting is equivalent to *include*: the mark will be faceted if either the **fx** or **fy** channel option (or both) is specified. The null or false option will disable faceting, while *exclude* draws the subset of the mark’s data *not* in the current facet.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map" + }, + "facetAnchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "right", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "const": "left", + "type": "string" + }, + { + "const": "top-left", + "type": "string" + }, + { + "const": "top-right", + "type": "string" + }, + { + "const": "bottom-left", + "type": "string" + }, + { + "const": "bottom-right", + "type": "string" + }, + { + "const": "top-empty", + "type": "string" + }, + { + "const": "right-empty", + "type": "string" + }, + { + "const": "bottom-empty", + "type": "string" + }, + { + "const": "left-empty", + "type": "string" + }, + { + "const": "empty", + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to place the mark with respect to facets; one of:\n\n- null (default for most marks) - display the mark in each non-empty facet\n- *top*, *right*, *bottom*, or *left* - display the mark only in facets on the given side\n- *top-empty*, *right-empty*, *bottom-empty*, or *left-empty* (default for axis marks) - display the mark only in facets that have empty space on the given side: either the margin, or an empty facet\n- *empty* - display the mark in empty facets only" + }, + "fill": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill" + }, + "fillOpacity": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill-opacity][1]; a constant number between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill-opacity" + }, + "filter": { + "$ref": "#/definitions/ChannelValue", + "description": "Applies a transform to filter the mark’s index according to the given channel values; only truthy values are retained.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "fx": { + "$ref": "#/definitions/ChannelValue", + "description": "The horizontal facet position channel, for mark-level faceting, bound to the *fx* scale." + }, + "fy": { + "$ref": "#/definitions/ChannelValue", + "description": "The vertical facet position channel, for mark-level faceting, bound to the\n*fy* scale." + }, + "href": { + "$ref": "#/definitions/ChannelValue", + "description": "The [href][1]; a channel specifying URLs for clickable links. May be used in conjunction with the **target** option to open links in another window.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/href" + }, + "imageFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A CSS [filter][1]; a constant string used to adjust the rendering of images, such as *blur(5px)*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/filter" + }, + "margin": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four mark margins: **marginTop**,\n**marginRight**, **marginBottom**, and **marginLeft**; typically defaults to 0, except for axis marks." + }, + "marginBottom": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s bottom margin; the minimum distance in pixels between the bottom edges of the inner and outer plot area." + }, + "marginLeft": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s left margin; the minimum distance in pixels between the left edges of the inner and outer plot area." + }, + "marginRight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s right margin; the minimum distance in pixels between the right edges of the mark’s inner and outer plot area." + }, + "marginTop": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s top margin; the minimum distance in pixels between the top edges of the inner and outer plot area." + }, + "mark": { + "const": "hull", + "description": "A mark that draws a convex hull around the points given by the **x** and\n**y** channels. The **stroke** option defaults to _currentColor_ and the\n**fill** option defaults to _none_. When an aesthetic channel is specified (such as **stroke** or **strokeWidth**), the hull inherits the corresponding channel value from one of its constituent points arbitrarily.\n\nIf **z** is specified, the input points are grouped by *z*, producing a separate hull for each group. If **z** is not specified, it defaults to the **fill** channel, if any, or the **stroke** channel, if any.", + "type": "string" + }, + "marker": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for markerStart, markerMid, and markerEnd; one of:\n\n- a marker name such as *arrow* or *circle*\n- *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*" + }, + "markerEnd": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The marker for the ending point of a line segment; one of:\n\n- a marker name such as *arrow* or *circle*\n* *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*" + }, + "markerMid": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The marker for any middle (interior) points of a line segment. If the line segment only has a start and end point, this option has no effect. One of:\n\n- a marker name such as *arrow* or *circle*\n* *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*\n* a function - a custom marker function; see below" + }, + "markerStart": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The marker for the starting point of a line segment; one of:\n\n- a marker name such as *arrow* or *circle*\n* *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*" + }, + "mixBlendMode": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [mix-blend-mode][1]; a constant string specifying how to blend content such as *multiply*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode" + }, + "opacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally. For faster rendering, prefer the **strokeOpacity** or **fillOpacity** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/opacity" + }, + "paintOrder": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [paint-order][1]; a constant string specifying the order in which the\n**fill**, **stroke**, and any markers are drawn; defaults to *normal*, which draws the fill, then stroke, then markers; defaults to *stroke* for the text mark to create a “halo” around text to improve legibility.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/paint-order" + }, + "pointerEvents": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [pointer-events][1] property; a constant string such as *none*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/pointer-events" + }, + "reverse": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Applies a transform to reverse the order of the mark’s index, say for reverse input order." + }, + "select": { + "$ref": "#/definitions/SelectFilter", + "description": "Applies a filter transform after data is loaded to highlight selected values only. For example, `first` and `last` select the first or last values of series only (using the *z* channel to separate series). Meanwhile, `nearestX` and `nearestY` select the point nearest to the pointer along the *x* or *y* channel dimension. Unlike Mosaic selections, a mark level *select* is internal to the mark only, and does not populate a param or selection value to be shared across clients.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "shapeRendering": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [shape-rendering][1]; a constant string such as *crispEdges*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/shape-rendering" + }, + "sort": { + "anyOf": [ + { + "$ref": "#/definitions/SortOrder" + }, + { + "$ref": "#/definitions/ChannelDomainSort" + } + ], + "description": "Either applies a transform to sort the mark’s index by the specified channel values, or imputes ordinal scale domains from this mark’s channels.\n\nWhen imputing ordinal scale domains from channel values, the **sort** option is an object whose keys are ordinal scale names such as *x* or *fx*, and whose values are channel names such as *y*, *y1*, or *y2*. For example, to impute the *y* scale’s domain from the associated *x* channel values in ascending order:\n\n```js sort: {y: \"x\"} ```\n\nFor different sort options for different scales, replace the channel name with a *value* object and per-scale options:\n\n```js sort: {y: {value: \"-x\"}} ```\n\nWhen sorting the mark’s index, the **sort** option is instead one of:\n\n- a channel value definition for sorting given values in ascending order\n- a {value, order} object for sorting given values\n- a {channel, order} object for sorting the named channel’s values" + }, + "stroke": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke" + }, + "strokeDasharray": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dasharray][1]; a constant number indicating the length in pixels of alternating dashes and gaps, or a constant string of numbers separated by spaces or commas (_e.g._, *10 2* for dashes of 10 pixels separated by gaps of 2 pixels), or *none* (the default) for no dashing\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dasharray" + }, + "strokeDashoffset": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dashoffset][1]; a constant indicating the offset in pixels of the first dash along the stroke; defaults to zero.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dashoffset" + }, + "strokeLinecap": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linecap][1]; a constant specifying how to cap stroked paths, such as *butt*, *round*, or *square*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linecap" + }, + "strokeLinejoin": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linejoin][1]; a constant specifying how to join stroked paths, such as *bevel*, *miter*, *miter-clip*, or *round*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linejoin" + }, + "strokeMiterlimit": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-miterlimit][1]; a constant number specifying how to limit the length of *miter* joins on stroked paths.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-miterlimit" + }, + "strokeOpacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-opacity" + }, + "strokeWidth": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-width][1]; a constant number in pixels, or a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-width" + }, + "target": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [target][1]; a constant string specifying the target window (_e.g._,\n*_blank*) for clickable links; used in conjunction with the **href** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/target" + }, + "tension": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The tension option only has an effect on bundle, cardinal and Catmull–Rom splines (*bundle*, *cardinal*, *cardinal-open*, *cardinal-closed*,\n*catmull-rom*, *catmull-rom-open*, and *catmull-rom-closed*). For bundle splines, it corresponds to [beta][1]; for cardinal splines, [tension][2]; for Catmull–Rom splines, [alpha][3].\n\n[1]: https://d3js.org/d3-shape/curve#curveBundle_beta [2]: https://d3js.org/d3-shape/curve#curveCardinal_tension [3]: https://d3js.org/d3-shape/curve#curveCatmullRom_alpha" + }, + "tip": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/TipPointer" + }, + { + "properties": { + "anchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The tip anchor specifies how to orient the tip box relative to its anchor position; it refers to the part of the tip box that is attached to the anchor point. For example, the *top-left* anchor places the top-left corner of tip box near the anchor position, hence placing the tip box below and to the right of the anchor position." + }, + "fontFamily": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font-family][1]; a constant; defaults to the plot’s font family, which is typically [*system-ui*][2].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-family [2]: https://drafts.csswg.org/css-fonts-4/#valdef-font-family-system-ui" + }, + "fontSize": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font size][1] in pixels; either a constant or a channel; defaults to the plot’s font size, which is typically 10. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-size" + }, + "fontStyle": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font style][1]; a constant; defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-style" + }, + "fontVariant": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font variant][1]; a constant; if the **text** channel contains numbers or dates, defaults to *tabular-nums* to facilitate comparing numbers; otherwise defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant" + }, + "fontWeight": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font weight][1]; a constant; defaults to the plot’s font weight, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight" + }, + "format": { + "additionalProperties": false, + "description": "How channel values are formatted for display. If a format is a string, it is interpreted as a (UTC) time format for temporal channels, and otherwise a number format.", + "properties": { + "ariaLabel": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fill": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fillOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fontSize": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fx": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fy": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "geometry": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "height": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "href": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "length": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "opacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "path": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "r": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "rotate": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "src": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "stroke": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeWidth": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "symbol": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "text": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "title": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "weight": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "width": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "z": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + } + }, + "type": "object" + }, + "frameAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The frame anchor specifies defaults for **x** and **y** based on the plot’s frame; it may be one of the four sides (*top*, *right*, *bottom*, *left*), one of the four corners (*top-left*, *top-right*, *bottom-right*,\n*bottom-left*), or the *middle* of the frame. For example, for tips distributed horizontally at the top of the frame:\n\n```js Plot.tip(data, {x: \"date\", frameAnchor: \"top\"}) ```" + }, + "lineHeight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line height in ems; defaults to 1. The line height affects the (typically vertical) separation between adjacent baselines of text, as well as the separation between the text and its anchor point." + }, + "lineWidth": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line width in ems (e.g., 10 for about 20 characters); defaults to infinity, disabling wrapping and clipping.\n\nIf **textOverflow** is null, lines will be wrapped at the specified length. If a line is split at a soft hyphen (\\xad), a hyphen (-) will be displayed at the end of the line. If **textOverflow** is not null, lines will be clipped according to the given strategy." + }, + "monospace": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, changes the default **fontFamily** to *monospace*, and uses simplified monospaced text metrics calculations." + }, + "pathFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The image filter for the tip’s box; defaults to a drop shadow." + }, + "pointer": { + "$ref": "#/definitions/TipPointer" + }, + "pointerSize": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The size of the tip’s pointer in pixels; defaults to 12." + }, + "preferredAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If an explicit tip anchor is not specified, an anchor is chosen automatically such that the tip fits within the plot’s frame; if the preferred anchor fits, it is chosen." + }, + "textAnchor": { + "anyOf": [ + { + "const": "start", + "type": "string" + }, + { + "const": "middle", + "type": "string" + }, + { + "const": "end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [text anchor][1] controls how text is aligned (typically horizontally) relative to its anchor point; it is one of *start*, *end*, or *middle*. If the frame anchor is *left*, *top-left*, or *bottom-left*, the default text anchor is *start*; if the frame anchor is *right*, *top-right*, or\n*bottom-right*, the default is *end*; otherwise it is *middle*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/text-anchor" + }, + "textOverflow": { + "anyOf": [ + { + "type": "null" + }, + { + "const": "clip", + "type": "string" + }, + { + "const": "ellipsis", + "type": "string" + }, + { + "const": "clip-start", + "type": "string" + }, + { + "const": "clip-end", + "type": "string" + }, + { + "const": "ellipsis-start", + "type": "string" + }, + { + "const": "ellipsis-middle", + "type": "string" + }, + { + "const": "ellipsis-end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How truncate (or wrap) lines of text longer than the given **lineWidth**; one of:\n\n- null (default) - preserve overflowing characters (and wrap if needed)\n- *clip* or *clip-end* - remove characters from the end\n- *clip-start* - remove characters from the start\n- *ellipsis* or *ellipsis-end* - replace characters from the end with an ellipsis (…)\n- *ellipsis-start* - replace characters from the start with an ellipsis (…)\n- *ellipsis-middle* - replace characters from the middle with an ellipsis (…)\n\nIf no **title** was specified, if text requires truncation, a title containing the non-truncated text will be implicitly added." + }, + "textPadding": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The padding around the text in pixels; defaults to 8." + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + } + }, + "type": "object" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to generate a tooltip for this mark, and any tip options." + }, + "title": { + "$ref": "#/definitions/ChannelValue", + "description": "The title; a channel specifying accessible, short textual descriptions as strings (possibly with newlines). If the tip option is specified, the title will be displayed with an interactive tooltip instead of using the SVG [title element][1].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/title" + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel, typically bound to the *x* scale." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel, typically bound to the *y* scale." + }, + "z": { + "$ref": "#/definitions/ChannelValue", + "description": "An optional ordinal channel for grouping to produce multiple (possibly overlapping) triangulations." + } + }, + "required": [ + "data", + "mark" + ], + "type": "object" + }, + "Image": { + "additionalProperties": false, + "properties": { + "ariaDescription": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-description][1]; a constant textual description.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-description" + }, + "ariaHidden": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-hidden][1] state; a constant indicating whether the element is exposed to an accessibility API.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-hidden" + }, + "ariaLabel": { + "$ref": "#/definitions/ChannelValue", + "description": "The [aria-label][1]; a channel specifying short textual labels representing the value in the accessibility tree.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-label" + }, + "clip": { + "anyOf": [ + { + "const": "frame", + "type": "string" + }, + { + "const": "sphere", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to clip the mark; one of:\n\n- *frame* or true - clip to the plot’s frame (inner area)\n- *sphere* - clip to the projected sphere (*e.g.*, front hemisphere)\n- null or false - do not clip\n\nThe *sphere* clip option requires a geographic projection." + }, + "crossOrigin": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [cross-origin][1] behavior. See the [Plot.image notebook][2] for details.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/crossorigin [2]: https://observablehq.com/@observablehq/plot-image" + }, + "data": { + "$ref": "#/definitions/PlotMarkData", + "description": "The data source for the mark." + }, + "dx": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The horizontal offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "dy": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The vertical offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "facet": { + "anyOf": [ + { + "const": "auto", + "type": "string" + }, + { + "const": "include", + "type": "string" + }, + { + "const": "exclude", + "type": "string" + }, + { + "const": "super", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to enable or disable faceting; one of:\n\n- *auto* (default) - automatically determine if this mark should be faceted\n- *include* (or true) - draw the subset of the mark’s data in the current facet\n- *exclude* - draw the subset of the mark’s data *not* in the current facet\n- *super* - draw this mark in a single frame that covers all facets\n- null (or false) - repeat this mark’s data across all facets (*i.e.*, no faceting)\n\nWhen a mark uses *super* faceting, it is not allowed to use position scales (*x*, *y*, *fx*, or *fy*); *super* faceting is intended for decorations, such as labels and legends.\n\nWhen top-level faceting is used, the default *auto* setting is equivalent to *include* when the mark data is strictly equal to the top-level facet data; otherwise it is equivalent to null. When the *include* or *exclude* facet mode is chosen, the mark data must be parallel to the top-level facet data: the data must have the same length and order. If the data are not parallel, then the wrong data may be shown in each facet. The default\n*auto* therefore requires strict equality (`===`) for safety, and using the facet data as mark data is recommended when using the *exclude* facet mode. (To construct parallel data safely, consider using [*array*.map][1] on the facet data.)\n\nWhen mark-level faceting is used, the default *auto* setting is equivalent to *include*: the mark will be faceted if either the **fx** or **fy** channel option (or both) is specified. The null or false option will disable faceting, while *exclude* draws the subset of the mark’s data *not* in the current facet.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map" + }, + "facetAnchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "right", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "const": "left", + "type": "string" + }, + { + "const": "top-left", + "type": "string" + }, + { + "const": "top-right", + "type": "string" + }, + { + "const": "bottom-left", + "type": "string" + }, + { + "const": "bottom-right", + "type": "string" + }, + { + "const": "top-empty", + "type": "string" + }, + { + "const": "right-empty", + "type": "string" + }, + { + "const": "bottom-empty", + "type": "string" + }, + { + "const": "left-empty", + "type": "string" + }, + { + "const": "empty", + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to place the mark with respect to facets; one of:\n\n- null (default for most marks) - display the mark in each non-empty facet\n- *top*, *right*, *bottom*, or *left* - display the mark only in facets on the given side\n- *top-empty*, *right-empty*, *bottom-empty*, or *left-empty* (default for axis marks) - display the mark only in facets that have empty space on the given side: either the margin, or an empty facet\n- *empty* - display the mark in empty facets only" + }, + "fill": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill" + }, + "fillOpacity": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill-opacity][1]; a constant number between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill-opacity" + }, + "filter": { + "$ref": "#/definitions/ChannelValue", + "description": "Applies a transform to filter the mark’s index according to the given channel values; only truthy values are retained.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "frameAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The frame anchor specifies defaults for **x** and **y** based on the plot’s frame; it may be one of the four sides (*top*, *right*, *bottom*, *left*), one of the four corners (*top-left*, *top-right*, *bottom-right*,\n*bottom-left*), or the *middle* of the frame." + }, + "fx": { + "$ref": "#/definitions/ChannelValue", + "description": "The horizontal facet position channel, for mark-level faceting, bound to the *fx* scale." + }, + "fy": { + "$ref": "#/definitions/ChannelValue", + "description": "The vertical facet position channel, for mark-level faceting, bound to the\n*fy* scale." + }, + "height": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The image height in pixels. When a number, it is interpreted as a constant radius in pixels; otherwise it is interpreted as a channel. Also sets the default **height**; if neither are set, defaults to 16. Images with a nonpositive height are not drawn." + }, + "href": { + "$ref": "#/definitions/ChannelValue", + "description": "The [href][1]; a channel specifying URLs for clickable links. May be used in conjunction with the **target** option to open links in another window.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/href" + }, + "imageFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A CSS [filter][1]; a constant string used to adjust the rendering of images, such as *blur(5px)*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/filter" + }, + "imageRendering": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [image-rendering attribute][1]; defaults to *auto* (bilinear). The option may be set to *pixelated* to disable bilinear interpolation for a sharper image; however, note that this is not supported in WebKit.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/image-rendering" + }, + "margin": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four mark margins: **marginTop**,\n**marginRight**, **marginBottom**, and **marginLeft**; typically defaults to 0, except for axis marks." + }, + "marginBottom": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s bottom margin; the minimum distance in pixels between the bottom edges of the inner and outer plot area." + }, + "marginLeft": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s left margin; the minimum distance in pixels between the left edges of the inner and outer plot area." + }, + "marginRight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s right margin; the minimum distance in pixels between the right edges of the mark’s inner and outer plot area." + }, + "marginTop": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s top margin; the minimum distance in pixels between the top edges of the inner and outer plot area." + }, + "mark": { + "const": "image", + "description": "An image mark that draws images as in a scatterplot.\n\nIf either **x** or **y** is not specified, the default is determined by the **frameAnchor** option. If none of **x**, **y**, and **frameAnchor** are specified, *data* is assumed to be an array of pairs [[*x₀*, *y₀*], [*x₁*, *y₁*], [*x₂*, *y₂*], …] such that **x** = [*x₀*, *x₁*, *x₂*, …] and **y** = [*y₀*, *y₁*, *y₂*, …].", + "type": "string" + }, + "mixBlendMode": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [mix-blend-mode][1]; a constant string specifying how to blend content such as *multiply*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode" + }, + "opacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally. For faster rendering, prefer the **strokeOpacity** or **fillOpacity** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/opacity" + }, + "paintOrder": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [paint-order][1]; a constant string specifying the order in which the\n**fill**, **stroke**, and any markers are drawn; defaults to *normal*, which draws the fill, then stroke, then markers; defaults to *stroke* for the text mark to create a “halo” around text to improve legibility.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/paint-order" + }, + "pointerEvents": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [pointer-events][1] property; a constant string such as *none*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/pointer-events" + }, + "preserveAspectRatio": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The image [aspect ratio][1]; defaults to *xMidYMid meet*. To crop the image instead of scaling it to fit, use *xMidYMid slice*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/preserveAspectRatio" + }, + "r": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The image clip radius, for circular images. If null (default), images are not clipped; when a number, it is interpreted as a constant in pixels; otherwise it is interpreted as a channel, typically bound to the *r* scale. Also defaults **height** and **width** to twice its value." + }, + "reverse": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Applies a transform to reverse the order of the mark’s index, say for reverse input order." + }, + "rotate": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The rotation angle, in degrees clockwise. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel." + }, + "select": { + "$ref": "#/definitions/SelectFilter", + "description": "Applies a filter transform after data is loaded to highlight selected values only. For example, `first` and `last` select the first or last values of series only (using the *z* channel to separate series). Meanwhile, `nearestX` and `nearestY` select the point nearest to the pointer along the *x* or *y* channel dimension. Unlike Mosaic selections, a mark level *select* is internal to the mark only, and does not populate a param or selection value to be shared across clients.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "shapeRendering": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [shape-rendering][1]; a constant string such as *crispEdges*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/shape-rendering" + }, + "sort": { + "anyOf": [ + { + "$ref": "#/definitions/SortOrder" + }, + { + "$ref": "#/definitions/ChannelDomainSort" + } + ], + "description": "Either applies a transform to sort the mark’s index by the specified channel values, or imputes ordinal scale domains from this mark’s channels.\n\nWhen imputing ordinal scale domains from channel values, the **sort** option is an object whose keys are ordinal scale names such as *x* or *fx*, and whose values are channel names such as *y*, *y1*, or *y2*. For example, to impute the *y* scale’s domain from the associated *x* channel values in ascending order:\n\n```js sort: {y: \"x\"} ```\n\nFor different sort options for different scales, replace the channel name with a *value* object and per-scale options:\n\n```js sort: {y: {value: \"-x\"}} ```\n\nWhen sorting the mark’s index, the **sort** option is instead one of:\n\n- a channel value definition for sorting given values in ascending order\n- a {value, order} object for sorting given values\n- a {channel, order} object for sorting the named channel’s values" + }, + "src": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The required image URL (or relative path). If a string that starts with a dot, slash, or URL protocol (*e.g.*, “https:”) it is assumed to be a constant; otherwise it is interpreted as a channel." + }, + "stroke": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke" + }, + "strokeDasharray": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dasharray][1]; a constant number indicating the length in pixels of alternating dashes and gaps, or a constant string of numbers separated by spaces or commas (_e.g._, *10 2* for dashes of 10 pixels separated by gaps of 2 pixels), or *none* (the default) for no dashing\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dasharray" + }, + "strokeDashoffset": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dashoffset][1]; a constant indicating the offset in pixels of the first dash along the stroke; defaults to zero.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dashoffset" + }, + "strokeLinecap": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linecap][1]; a constant specifying how to cap stroked paths, such as *butt*, *round*, or *square*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linecap" + }, + "strokeLinejoin": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linejoin][1]; a constant specifying how to join stroked paths, such as *bevel*, *miter*, *miter-clip*, or *round*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linejoin" + }, + "strokeMiterlimit": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-miterlimit][1]; a constant number specifying how to limit the length of *miter* joins on stroked paths.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-miterlimit" + }, + "strokeOpacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-opacity" + }, + "strokeWidth": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-width][1]; a constant number in pixels, or a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-width" + }, + "target": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [target][1]; a constant string specifying the target window (_e.g._,\n*_blank*) for clickable links; used in conjunction with the **href** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/target" + }, + "tip": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/TipPointer" + }, + { + "properties": { + "anchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The tip anchor specifies how to orient the tip box relative to its anchor position; it refers to the part of the tip box that is attached to the anchor point. For example, the *top-left* anchor places the top-left corner of tip box near the anchor position, hence placing the tip box below and to the right of the anchor position." + }, + "fontFamily": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font-family][1]; a constant; defaults to the plot’s font family, which is typically [*system-ui*][2].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-family [2]: https://drafts.csswg.org/css-fonts-4/#valdef-font-family-system-ui" + }, + "fontSize": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font size][1] in pixels; either a constant or a channel; defaults to the plot’s font size, which is typically 10. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-size" + }, + "fontStyle": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font style][1]; a constant; defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-style" + }, + "fontVariant": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font variant][1]; a constant; if the **text** channel contains numbers or dates, defaults to *tabular-nums* to facilitate comparing numbers; otherwise defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant" + }, + "fontWeight": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font weight][1]; a constant; defaults to the plot’s font weight, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight" + }, + "format": { + "additionalProperties": false, + "description": "How channel values are formatted for display. If a format is a string, it is interpreted as a (UTC) time format for temporal channels, and otherwise a number format.", + "properties": { + "ariaLabel": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fill": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fillOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fontSize": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fx": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fy": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "geometry": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "height": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "href": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "length": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "opacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "path": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "r": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "rotate": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "src": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "stroke": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeWidth": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "symbol": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "text": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "title": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "weight": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "width": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "z": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + } + }, + "type": "object" + }, + "frameAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The frame anchor specifies defaults for **x** and **y** based on the plot’s frame; it may be one of the four sides (*top*, *right*, *bottom*, *left*), one of the four corners (*top-left*, *top-right*, *bottom-right*,\n*bottom-left*), or the *middle* of the frame. For example, for tips distributed horizontally at the top of the frame:\n\n```js Plot.tip(data, {x: \"date\", frameAnchor: \"top\"}) ```" + }, + "lineHeight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line height in ems; defaults to 1. The line height affects the (typically vertical) separation between adjacent baselines of text, as well as the separation between the text and its anchor point." + }, + "lineWidth": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line width in ems (e.g., 10 for about 20 characters); defaults to infinity, disabling wrapping and clipping.\n\nIf **textOverflow** is null, lines will be wrapped at the specified length. If a line is split at a soft hyphen (\\xad), a hyphen (-) will be displayed at the end of the line. If **textOverflow** is not null, lines will be clipped according to the given strategy." + }, + "monospace": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, changes the default **fontFamily** to *monospace*, and uses simplified monospaced text metrics calculations." + }, + "pathFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The image filter for the tip’s box; defaults to a drop shadow." + }, + "pointer": { + "$ref": "#/definitions/TipPointer" + }, + "pointerSize": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The size of the tip’s pointer in pixels; defaults to 12." + }, + "preferredAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If an explicit tip anchor is not specified, an anchor is chosen automatically such that the tip fits within the plot’s frame; if the preferred anchor fits, it is chosen." + }, + "textAnchor": { + "anyOf": [ + { + "const": "start", + "type": "string" + }, + { + "const": "middle", + "type": "string" + }, + { + "const": "end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [text anchor][1] controls how text is aligned (typically horizontally) relative to its anchor point; it is one of *start*, *end*, or *middle*. If the frame anchor is *left*, *top-left*, or *bottom-left*, the default text anchor is *start*; if the frame anchor is *right*, *top-right*, or\n*bottom-right*, the default is *end*; otherwise it is *middle*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/text-anchor" + }, + "textOverflow": { + "anyOf": [ + { + "type": "null" + }, + { + "const": "clip", + "type": "string" + }, + { + "const": "ellipsis", + "type": "string" + }, + { + "const": "clip-start", + "type": "string" + }, + { + "const": "clip-end", + "type": "string" + }, + { + "const": "ellipsis-start", + "type": "string" + }, + { + "const": "ellipsis-middle", + "type": "string" + }, + { + "const": "ellipsis-end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How truncate (or wrap) lines of text longer than the given **lineWidth**; one of:\n\n- null (default) - preserve overflowing characters (and wrap if needed)\n- *clip* or *clip-end* - remove characters from the end\n- *clip-start* - remove characters from the start\n- *ellipsis* or *ellipsis-end* - replace characters from the end with an ellipsis (…)\n- *ellipsis-start* - replace characters from the start with an ellipsis (…)\n- *ellipsis-middle* - replace characters from the middle with an ellipsis (…)\n\nIf no **title** was specified, if text requires truncation, a title containing the non-truncated text will be implicitly added." + }, + "textPadding": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The padding around the text in pixels; defaults to 8." + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + } + }, + "type": "object" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to generate a tooltip for this mark, and any tip options." + }, + "title": { + "$ref": "#/definitions/ChannelValue", + "description": "The title; a channel specifying accessible, short textual descriptions as strings (possibly with newlines). If the tip option is specified, the title will be displayed with an interactive tooltip instead of using the SVG [title element][1].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/title" + }, + "width": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The image width in pixels. When a number, it is interpreted as a constant radius in pixels; otherwise it is interpreted as a channel. Also sets the default **height**; if neither are set, defaults to 16. Images with a nonpositive width are not drawn." + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel specifying the image’s center; typically bound to the *x* scale." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel specifying the image’s center; typically bound to the *y* scale." + } + }, + "required": [ + "data", + "mark" + ], + "type": "object" + }, + "Interpolate": { + "description": "How to interpolate range (output) values for continuous scales; one of:\n\n- *number* - linear numeric interpolation\n- *rgb* - red, green, blue (sRGB)\n- *hsl* - hue, saturation, lightness (HSL; cylindrical sRGB)\n- *hcl* - hue, chroma, perceptual lightness (CIELCh_ab; cylindrical CIELAB)\n- *lab* - perceptual lightness and opponent colors (L\\*a\\*b\\*, CIELAB)", + "enum": [ + "number", + "rgb", + "hsl", + "hcl", + "lab" + ], + "type": "string" + }, + "Interval": { + "$ref": "#/definitions/LiteralTimeInterval", + "description": "How to partition a continuous range into discrete intervals; one of:\n\n- a named time interval such as *day* (for date intervals)\n- a number (for number intervals), defining intervals at integer multiples of *n*" + }, + "IntervalX": { + "additionalProperties": false, + "description": "An intervalX interactor.", + "properties": { + "as": { + "$ref": "#/definitions/ParamRef", + "description": "The output selection. A clause of the form `field BETWEEN lo AND hi` is added for the currently selected interval [lo, hi]." + }, + "brush": { + "$ref": "#/definitions/BrushStyles", + "description": "CSS styles for the brush (SVG `rect`) element." + }, + "field": { + "description": "The name of the field (database column) over which the interval selection should be defined. If unspecified, the channel field of the first valid prior mark definition is used.", + "type": "string" + }, + "peers": { + "description": "A flag indicating if peer (sibling) marks are when cross-filtering (default `true`). If set, peer marks will not be filtered by this interactor's selection in cross-filtering setups.", + "type": "boolean" + }, + "pixelSize": { + "description": "The size of an interative pixel (default `1`). Larger pixel sizes reduce the brush resolution, which can reduce the size of data cube indexes.", + "type": "number" + }, + "select": { + "const": "intervalX", + "description": "Select a continuous 1D interval selection over the `x` scale domain.", + "type": "string" + } + }, + "required": [ + "as", + "select" + ], + "type": "object" + }, + "IntervalXY": { + "additionalProperties": false, + "description": "An intervalXY interactor.", + "properties": { + "as": { + "$ref": "#/definitions/ParamRef", + "description": "The output selection. A clause of the form `(xfield BETWEEN x1 AND x2) AND (yfield BETWEEN y1 AND y2)` is added for the currently selected intervals." + }, + "brush": { + "$ref": "#/definitions/BrushStyles", + "description": "CSS styles for the brush (SVG `rect`) element." + }, + "peers": { + "description": "A flag indicating if peer (sibling) marks are when cross-filtering (default `true`). If set, peer marks will not be filtered by this interactor's selection in cross-filtering setups.", + "type": "boolean" + }, + "pixelSize": { + "description": "The size of an interative pixel (default `1`). Larger pixel sizes reduce the brush resolution, which can reduce the size of data cube indexes.", + "type": "number" + }, + "select": { + "const": "intervalXY", + "description": "Select a continuous 2D interval selection over the `x` and `y` scale domains.", + "type": "string" + }, + "xfield": { + "description": "The name of the field (database column) over which the `x`-component of the interval selection should be defined. If unspecified, the `x` channel field of the first valid prior mark definition is used.", + "type": "string" + }, + "yfield": { + "description": "The name of the field (database column) over which the `y`-component of the interval selection should be defined. If unspecified, the `y` channel field of the first valid prior mark definition is used.", + "type": "string" + } + }, + "required": [ + "as", + "select" + ], + "type": "object" + }, + "IntervalY": { + "additionalProperties": false, + "description": "An intervalY interactor.", + "properties": { + "as": { + "$ref": "#/definitions/ParamRef", + "description": "The output selection. A clause of the form `field BETWEEN lo AND hi` is added for the currently selected interval [lo, hi]." + }, + "brush": { + "$ref": "#/definitions/BrushStyles", + "description": "CSS styles for the brush (SVG `rect`) element." + }, + "field": { + "description": "The name of the field (database column) over which the interval selection should be defined. If unspecified, the channel field of the first valid prior mark definition is used.", + "type": "string" + }, + "peers": { + "description": "A flag indicating if peer (sibling) marks are when cross-filtering (default `true`). If set, peer marks will not be filtered by this interactor's selection in cross-filtering setups.", + "type": "boolean" + }, + "pixelSize": { + "description": "The size of an interative pixel (default `1`). Larger pixel sizes reduce the brush resolution, which can reduce the size of data cube indexes.", + "type": "number" + }, + "select": { + "const": "intervalY", + "description": "Select a continuous 1D interval selection over the `y` scale domain.", + "type": "string" + } + }, + "required": [ + "as", + "select" + ], + "type": "object" + }, + "LabelArrow": { + "enum": [ + "auto", + "up", + "right", + "down", + "left", + "none", + true, + false, + null + ], + "type": [ + "string", + "boolean", + "null" + ] + }, + "Lag": { + "additionalProperties": false, + "properties": { + "lag": { + "anyOf": [ + { + "description": "A transform argument.", + "type": [ + "string", + "number", + "boolean" + ] + }, + { + "items": { + "description": "A transform argument.", + "type": [ + "string", + "number", + "boolean" + ] + }, + "maxItems": 3, + "minItems": 1, + "type": "array" + } + ], + "description": "Compute lagging values in a column. Returns the value at the row that is `offset` (second argument, default `1`) rows before the current row within the window frame. If there is no such row, instead return `default` (third argument, default `null`). Both offset and default are evaluated with respect to the current row." + }, + "orderby": { + "anyOf": [ + { + "$ref": "#/definitions/TransformField" + }, + { + "items": { + "$ref": "#/definitions/TransformField" + }, + "type": "array" + } + ] + }, + "partitionby": { + "anyOf": [ + { + "$ref": "#/definitions/TransformField" + }, + { + "items": { + "$ref": "#/definitions/TransformField" + }, + "type": "array" + } + ] + }, + "range": { + "anyOf": [ + { + "items": { + "type": [ + "number", + "null" + ] + }, + "type": "array" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "rows": { + "anyOf": [ + { + "items": { + "type": [ + "number", + "null" + ] + }, + "type": "array" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + } + }, + "required": [ + "lag" + ], + "type": "object" + }, + "Last": { + "additionalProperties": false, + "properties": { + "distinct": { + "type": "boolean" + }, + "last": { + "anyOf": [ + { + "description": "A transform argument.", + "type": [ + "string", + "number", + "boolean" + ] + }, + { + "items": { + "description": "A transform argument.", + "type": [ + "string", + "number", + "boolean" + ] + }, + "maxItems": 1, + "minItems": 1, + "type": "array" + } + ], + "description": "Return the last column value found in an aggregation group." + }, + "orderby": { + "anyOf": [ + { + "$ref": "#/definitions/TransformField" + }, + { + "items": { + "$ref": "#/definitions/TransformField" + }, + "type": "array" + } + ] + }, + "partitionby": { + "anyOf": [ + { + "$ref": "#/definitions/TransformField" + }, + { + "items": { + "$ref": "#/definitions/TransformField" + }, + "type": "array" + } + ] + }, + "range": { + "anyOf": [ + { + "items": { + "type": [ + "number", + "null" + ] + }, + "type": "array" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "rows": { + "anyOf": [ + { + "items": { + "type": [ + "number", + "null" + ] + }, + "type": "array" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + } + }, + "required": [ + "last" + ], + "type": "object" + }, + "LastValue": { + "additionalProperties": false, + "properties": { + "last_value": { + "anyOf": [ + { + "description": "A transform argument.", + "type": [ + "string", + "number", + "boolean" + ] + }, + { + "items": { + "description": "A transform argument.", + "type": [ + "string", + "number", + "boolean" + ] + }, + "maxItems": 1, + "minItems": 1, + "type": "array" + } + ], + "description": "Get the last value of the given column in the current window frame." + }, + "orderby": { + "anyOf": [ + { + "$ref": "#/definitions/TransformField" + }, + { + "items": { + "$ref": "#/definitions/TransformField" + }, + "type": "array" + } + ] + }, + "partitionby": { + "anyOf": [ + { + "$ref": "#/definitions/TransformField" + }, + { + "items": { + "$ref": "#/definitions/TransformField" + }, + "type": "array" + } + ] + }, + "range": { + "anyOf": [ + { + "items": { + "type": [ + "number", + "null" + ] + }, + "type": "array" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "rows": { + "anyOf": [ + { + "items": { + "type": [ + "number", + "null" + ] + }, + "type": "array" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + } + }, + "required": [ + "last_value" + ], + "type": "object" + }, + "Lead": { + "additionalProperties": false, + "properties": { + "lag": { + "anyOf": [ + { + "description": "A transform argument.", + "type": [ + "string", + "number", + "boolean" + ] + }, + { + "items": { + "description": "A transform argument.", + "type": [ + "string", + "number", + "boolean" + ] + }, + "maxItems": 3, + "minItems": 1, + "type": "array" + } + ], + "description": "Compute leading values in a column. Returns the value at the row that is `offset` (second argument, default `1`) rows after the current row within the window frame. If there is no such row, instead return `default` (third argument, default `null`). Both offset and default are evaluated with respect to the current row." + }, + "orderby": { + "anyOf": [ + { + "$ref": "#/definitions/TransformField" + }, + { + "items": { + "$ref": "#/definitions/TransformField" + }, + "type": "array" + } + ] + }, + "partitionby": { + "anyOf": [ + { + "$ref": "#/definitions/TransformField" + }, + { + "items": { + "$ref": "#/definitions/TransformField" + }, + "type": "array" + } + ] + }, + "range": { + "anyOf": [ + { + "items": { + "type": [ + "number", + "null" + ] + }, + "type": "array" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "rows": { + "anyOf": [ + { + "items": { + "type": [ + "number", + "null" + ] + }, + "type": "array" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + } + }, + "required": [ + "lag" + ], + "type": "object" + }, + "Legend": { + "additionalProperties": false, + "description": "A legend defined as a top-level spec component.", + "properties": { + "as": { + "$ref": "#/definitions/ParamRef", + "description": "The output selection. If specified, the legend is interactive, using a `toggle` interaction for discrete legends or an `intervalX` interaction for continuous legends." + }, + "columns": { + "description": "The number of columns to use to layout a discrete legend.", + "type": "number" + }, + "field": { + "description": "The data field over which to generate output selection clauses. If unspecified, a matching field is retrieved from existing plot marks.", + "type": "string" + }, + "for": { + "description": "The name of the plot this legend applies to. A plot must include a `name` attribute to be referenced.", + "type": "string" + }, + "height": { + "description": "The height of a continuous legend, in pixels.", + "type": "number" + }, + "label": { + "description": "The legend label.", + "type": "string" + }, + "legend": { + "description": "A legend of the given type. The valid types are `\"color\"`, `\"opacity\"`, and `\"symbol\"`.", + "enum": [ + "color", + "opacity", + "symbol" + ], + "type": "string" + }, + "marginBottom": { + "description": "The bottom margin of the legend component, in pixels.", + "type": "number" + }, + "marginLeft": { + "description": "The left margin of the legend component, in pixels.", + "type": "number" + }, + "marginRight": { + "description": "The right margin of the legend component, in pixels.", + "type": "number" + }, + "marginTop": { + "description": "The top margin of the legend component, in pixels.", + "type": "number" + }, + "tickSize": { + "description": "The size of legend ticks in a continuous legend, in pixels.", + "type": "number" + }, + "width": { + "description": "The width of a continuous legend, in pixels.", + "type": "number" + } + }, + "required": [ + "for", + "legend" + ], + "type": "object" + }, + "Line": { + "additionalProperties": false, + "description": "The line mark.", + "properties": { + "ariaDescription": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-description][1]; a constant textual description.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-description" + }, + "ariaHidden": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-hidden][1] state; a constant indicating whether the element is exposed to an accessibility API.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-hidden" + }, + "ariaLabel": { + "$ref": "#/definitions/ChannelValue", + "description": "The [aria-label][1]; a channel specifying short textual labels representing the value in the accessibility tree.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-label" + }, + "clip": { + "anyOf": [ + { + "const": "frame", + "type": "string" + }, + { + "const": "sphere", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to clip the mark; one of:\n\n- *frame* or true - clip to the plot’s frame (inner area)\n- *sphere* - clip to the projected sphere (*e.g.*, front hemisphere)\n- null or false - do not clip\n\nThe *sphere* clip option requires a geographic projection." + }, + "curve": { + "anyOf": [ + { + "$ref": "#/definitions/Curve" + }, + { + "const": "auto", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The curve (interpolation) method for connecting adjacent points. One of:\n\n- *basis* - a cubic basis spline (repeating the end points)\n- *basis-open* - an open cubic basis spline\n- *basis-closed* - a closed cubic basis spline\n- *bump-x* - a Bézier curve with horizontal tangents\n- *bump-y* - a Bézier curve with vertical tangents\n- *bundle* - a straightened cubic basis spline (suitable for lines only, not areas)\n- *cardinal* - a cubic cardinal spline (with one-sided differences at the ends)\n- *cardinal-open* - an open cubic cardinal spline\n- *cardinal-closed* - an closed cubic cardinal spline\n- *catmull-rom* - a cubic Catmull–Rom spline (with one-sided differences at the ends)\n- *catmull-rom-open* - an open cubic Catmull–Rom spline\n- *catmull-rom-closed* - a closed cubic Catmull–Rom spline\n- *linear* - a piecewise linear curve (*i.e.*, straight line segments)\n- *linear-closed* - a closed piecewise linear curve (*i.e.*, straight line segments)\n- *monotone-x* - a cubic spline that preserves monotonicity in *x*\n- *monotone-y* - a cubic spline that preserves monotonicity in *y*\n- *natural* - a natural cubic spline\n- *step* - a piecewise constant function where *y* changes at the midpoint of *x*\n- *step-after* - a piecewise constant function where *y* changes after *x*\n- *step-before* - a piecewise constant function where *x* changes after *y*\n- *auto* (default) - like *linear*, but use the (possibly spherical) projection, if any\n\nThe *auto* curve is typically used in conjunction with a spherical projection to interpolate along geodesics." + }, + "data": { + "$ref": "#/definitions/PlotMarkData", + "description": "The data source for the mark." + }, + "dx": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The horizontal offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "dy": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The vertical offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "facet": { + "anyOf": [ + { + "const": "auto", + "type": "string" + }, + { + "const": "include", + "type": "string" + }, + { + "const": "exclude", + "type": "string" + }, + { + "const": "super", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to enable or disable faceting; one of:\n\n- *auto* (default) - automatically determine if this mark should be faceted\n- *include* (or true) - draw the subset of the mark’s data in the current facet\n- *exclude* - draw the subset of the mark’s data *not* in the current facet\n- *super* - draw this mark in a single frame that covers all facets\n- null (or false) - repeat this mark’s data across all facets (*i.e.*, no faceting)\n\nWhen a mark uses *super* faceting, it is not allowed to use position scales (*x*, *y*, *fx*, or *fy*); *super* faceting is intended for decorations, such as labels and legends.\n\nWhen top-level faceting is used, the default *auto* setting is equivalent to *include* when the mark data is strictly equal to the top-level facet data; otherwise it is equivalent to null. When the *include* or *exclude* facet mode is chosen, the mark data must be parallel to the top-level facet data: the data must have the same length and order. If the data are not parallel, then the wrong data may be shown in each facet. The default\n*auto* therefore requires strict equality (`===`) for safety, and using the facet data as mark data is recommended when using the *exclude* facet mode. (To construct parallel data safely, consider using [*array*.map][1] on the facet data.)\n\nWhen mark-level faceting is used, the default *auto* setting is equivalent to *include*: the mark will be faceted if either the **fx** or **fy** channel option (or both) is specified. The null or false option will disable faceting, while *exclude* draws the subset of the mark’s data *not* in the current facet.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map" + }, + "facetAnchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "right", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "const": "left", + "type": "string" + }, + { + "const": "top-left", + "type": "string" + }, + { + "const": "top-right", + "type": "string" + }, + { + "const": "bottom-left", + "type": "string" + }, + { + "const": "bottom-right", + "type": "string" + }, + { + "const": "top-empty", + "type": "string" + }, + { + "const": "right-empty", + "type": "string" + }, + { + "const": "bottom-empty", + "type": "string" + }, + { + "const": "left-empty", + "type": "string" + }, + { + "const": "empty", + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to place the mark with respect to facets; one of:\n\n- null (default for most marks) - display the mark in each non-empty facet\n- *top*, *right*, *bottom*, or *left* - display the mark only in facets on the given side\n- *top-empty*, *right-empty*, *bottom-empty*, or *left-empty* (default for axis marks) - display the mark only in facets that have empty space on the given side: either the margin, or an empty facet\n- *empty* - display the mark in empty facets only" + }, + "fill": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill" + }, + "fillOpacity": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill-opacity][1]; a constant number between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill-opacity" + }, + "filter": { + "$ref": "#/definitions/ChannelValue", + "description": "Applies a transform to filter the mark’s index according to the given channel values; only truthy values are retained.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "fx": { + "$ref": "#/definitions/ChannelValue", + "description": "The horizontal facet position channel, for mark-level faceting, bound to the *fx* scale." + }, + "fy": { + "$ref": "#/definitions/ChannelValue", + "description": "The vertical facet position channel, for mark-level faceting, bound to the\n*fy* scale." + }, + "href": { + "$ref": "#/definitions/ChannelValue", + "description": "The [href][1]; a channel specifying URLs for clickable links. May be used in conjunction with the **target** option to open links in another window.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/href" + }, + "imageFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A CSS [filter][1]; a constant string used to adjust the rendering of images, such as *blur(5px)*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/filter" + }, + "margin": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four mark margins: **marginTop**,\n**marginRight**, **marginBottom**, and **marginLeft**; typically defaults to 0, except for axis marks." + }, + "marginBottom": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s bottom margin; the minimum distance in pixels between the bottom edges of the inner and outer plot area." + }, + "marginLeft": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s left margin; the minimum distance in pixels between the left edges of the inner and outer plot area." + }, + "marginRight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s right margin; the minimum distance in pixels between the right edges of the mark’s inner and outer plot area." + }, + "marginTop": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s top margin; the minimum distance in pixels between the top edges of the inner and outer plot area." + }, + "mark": { + "const": "line", + "description": "A line mark that connects control points.\n\nPoints along the line are connected in input order. If there are multiple series via the **z**, **fill**, or **stroke** channel, series are drawn in input order such that the last series is drawn on top. Typically *data* is already in sorted order, such as chronological for time series; if needed, consider a **sort** transform.\n\nIf any **x** or **y** values are invalid (undefined, null, or NaN), the line will be interrupted, resulting in a break that divides the line shape into multiple segments. If a line segment consists of only a single point, it may appear invisible unless rendered with rounded or square line caps. In addition, some curves such as *cardinal-open* only render a visible segment if it contains multiple points.\n\nVariable aesthetic channels are supported: if the **stroke** is defined as a channel, the line will be broken into contiguous overlapping segments when the stroke color changes; the stroke color will apply to the interval spanning the current data point and the following data point. This behavior also applies to the **fill**, **fillOpacity**, **strokeOpacity**,\n**strokeWidth**, **opacity**, **href**, **title**, and **ariaLabel** channels. When any of these channels are used, setting an explicit **z** channel (possibly to null) is strongly recommended.", + "type": "string" + }, + "marker": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for markerStart, markerMid, and markerEnd; one of:\n\n- a marker name such as *arrow* or *circle*\n- *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*" + }, + "markerEnd": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The marker for the ending point of a line segment; one of:\n\n- a marker name such as *arrow* or *circle*\n* *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*" + }, + "markerMid": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The marker for any middle (interior) points of a line segment. If the line segment only has a start and end point, this option has no effect. One of:\n\n- a marker name such as *arrow* or *circle*\n* *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*\n* a function - a custom marker function; see below" + }, + "markerStart": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The marker for the starting point of a line segment; one of:\n\n- a marker name such as *arrow* or *circle*\n* *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*" + }, + "mixBlendMode": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [mix-blend-mode][1]; a constant string specifying how to blend content such as *multiply*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode" + }, + "opacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally. For faster rendering, prefer the **strokeOpacity** or **fillOpacity** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/opacity" + }, + "paintOrder": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [paint-order][1]; a constant string specifying the order in which the\n**fill**, **stroke**, and any markers are drawn; defaults to *normal*, which draws the fill, then stroke, then markers; defaults to *stroke* for the text mark to create a “halo” around text to improve legibility.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/paint-order" + }, + "pointerEvents": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [pointer-events][1] property; a constant string such as *none*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/pointer-events" + }, + "reverse": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Applies a transform to reverse the order of the mark’s index, say for reverse input order." + }, + "select": { + "$ref": "#/definitions/SelectFilter", + "description": "Applies a filter transform after data is loaded to highlight selected values only. For example, `first` and `last` select the first or last values of series only (using the *z* channel to separate series). Meanwhile, `nearestX` and `nearestY` select the point nearest to the pointer along the *x* or *y* channel dimension. Unlike Mosaic selections, a mark level *select* is internal to the mark only, and does not populate a param or selection value to be shared across clients.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "shapeRendering": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [shape-rendering][1]; a constant string such as *crispEdges*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/shape-rendering" + }, + "sort": { + "anyOf": [ + { + "$ref": "#/definitions/SortOrder" + }, + { + "$ref": "#/definitions/ChannelDomainSort" + } + ], + "description": "Either applies a transform to sort the mark’s index by the specified channel values, or imputes ordinal scale domains from this mark’s channels.\n\nWhen imputing ordinal scale domains from channel values, the **sort** option is an object whose keys are ordinal scale names such as *x* or *fx*, and whose values are channel names such as *y*, *y1*, or *y2*. For example, to impute the *y* scale’s domain from the associated *x* channel values in ascending order:\n\n```js sort: {y: \"x\"} ```\n\nFor different sort options for different scales, replace the channel name with a *value* object and per-scale options:\n\n```js sort: {y: {value: \"-x\"}} ```\n\nWhen sorting the mark’s index, the **sort** option is instead one of:\n\n- a channel value definition for sorting given values in ascending order\n- a {value, order} object for sorting given values\n- a {channel, order} object for sorting the named channel’s values" + }, + "stroke": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke" + }, + "strokeDasharray": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dasharray][1]; a constant number indicating the length in pixels of alternating dashes and gaps, or a constant string of numbers separated by spaces or commas (_e.g._, *10 2* for dashes of 10 pixels separated by gaps of 2 pixels), or *none* (the default) for no dashing\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dasharray" + }, + "strokeDashoffset": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dashoffset][1]; a constant indicating the offset in pixels of the first dash along the stroke; defaults to zero.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dashoffset" + }, + "strokeLinecap": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linecap][1]; a constant specifying how to cap stroked paths, such as *butt*, *round*, or *square*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linecap" + }, + "strokeLinejoin": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linejoin][1]; a constant specifying how to join stroked paths, such as *bevel*, *miter*, *miter-clip*, or *round*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linejoin" + }, + "strokeMiterlimit": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-miterlimit][1]; a constant number specifying how to limit the length of *miter* joins on stroked paths.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-miterlimit" + }, + "strokeOpacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-opacity" + }, + "strokeWidth": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-width][1]; a constant number in pixels, or a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-width" + }, + "target": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [target][1]; a constant string specifying the target window (_e.g._,\n*_blank*) for clickable links; used in conjunction with the **href** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/target" + }, + "tension": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The tension option only has an effect on bundle, cardinal and Catmull–Rom splines (*bundle*, *cardinal*, *cardinal-open*, *cardinal-closed*,\n*catmull-rom*, *catmull-rom-open*, and *catmull-rom-closed*). For bundle splines, it corresponds to [beta][1]; for cardinal splines, [tension][2]; for Catmull–Rom splines, [alpha][3].\n\n[1]: https://d3js.org/d3-shape/curve#curveBundle_beta [2]: https://d3js.org/d3-shape/curve#curveCardinal_tension [3]: https://d3js.org/d3-shape/curve#curveCatmullRom_alpha" + }, + "tip": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/TipPointer" + }, + { + "properties": { + "anchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The tip anchor specifies how to orient the tip box relative to its anchor position; it refers to the part of the tip box that is attached to the anchor point. For example, the *top-left* anchor places the top-left corner of tip box near the anchor position, hence placing the tip box below and to the right of the anchor position." + }, + "fontFamily": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font-family][1]; a constant; defaults to the plot’s font family, which is typically [*system-ui*][2].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-family [2]: https://drafts.csswg.org/css-fonts-4/#valdef-font-family-system-ui" + }, + "fontSize": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font size][1] in pixels; either a constant or a channel; defaults to the plot’s font size, which is typically 10. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-size" + }, + "fontStyle": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font style][1]; a constant; defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-style" + }, + "fontVariant": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font variant][1]; a constant; if the **text** channel contains numbers or dates, defaults to *tabular-nums* to facilitate comparing numbers; otherwise defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant" + }, + "fontWeight": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font weight][1]; a constant; defaults to the plot’s font weight, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight" + }, + "format": { + "additionalProperties": false, + "description": "How channel values are formatted for display. If a format is a string, it is interpreted as a (UTC) time format for temporal channels, and otherwise a number format.", + "properties": { + "ariaLabel": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fill": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fillOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fontSize": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fx": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fy": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "geometry": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "height": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "href": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "length": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "opacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "path": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "r": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "rotate": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "src": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "stroke": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeWidth": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "symbol": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "text": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "title": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "weight": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "width": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "z": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + } + }, + "type": "object" + }, + "frameAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The frame anchor specifies defaults for **x** and **y** based on the plot’s frame; it may be one of the four sides (*top*, *right*, *bottom*, *left*), one of the four corners (*top-left*, *top-right*, *bottom-right*,\n*bottom-left*), or the *middle* of the frame. For example, for tips distributed horizontally at the top of the frame:\n\n```js Plot.tip(data, {x: \"date\", frameAnchor: \"top\"}) ```" + }, + "lineHeight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line height in ems; defaults to 1. The line height affects the (typically vertical) separation between adjacent baselines of text, as well as the separation between the text and its anchor point." + }, + "lineWidth": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line width in ems (e.g., 10 for about 20 characters); defaults to infinity, disabling wrapping and clipping.\n\nIf **textOverflow** is null, lines will be wrapped at the specified length. If a line is split at a soft hyphen (\\xad), a hyphen (-) will be displayed at the end of the line. If **textOverflow** is not null, lines will be clipped according to the given strategy." + }, + "monospace": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, changes the default **fontFamily** to *monospace*, and uses simplified monospaced text metrics calculations." + }, + "pathFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The image filter for the tip’s box; defaults to a drop shadow." + }, + "pointer": { + "$ref": "#/definitions/TipPointer" + }, + "pointerSize": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The size of the tip’s pointer in pixels; defaults to 12." + }, + "preferredAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If an explicit tip anchor is not specified, an anchor is chosen automatically such that the tip fits within the plot’s frame; if the preferred anchor fits, it is chosen." + }, + "textAnchor": { + "anyOf": [ + { + "const": "start", + "type": "string" + }, + { + "const": "middle", + "type": "string" + }, + { + "const": "end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [text anchor][1] controls how text is aligned (typically horizontally) relative to its anchor point; it is one of *start*, *end*, or *middle*. If the frame anchor is *left*, *top-left*, or *bottom-left*, the default text anchor is *start*; if the frame anchor is *right*, *top-right*, or\n*bottom-right*, the default is *end*; otherwise it is *middle*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/text-anchor" + }, + "textOverflow": { + "anyOf": [ + { + "type": "null" + }, + { + "const": "clip", + "type": "string" + }, + { + "const": "ellipsis", + "type": "string" + }, + { + "const": "clip-start", + "type": "string" + }, + { + "const": "clip-end", + "type": "string" + }, + { + "const": "ellipsis-start", + "type": "string" + }, + { + "const": "ellipsis-middle", + "type": "string" + }, + { + "const": "ellipsis-end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How truncate (or wrap) lines of text longer than the given **lineWidth**; one of:\n\n- null (default) - preserve overflowing characters (and wrap if needed)\n- *clip* or *clip-end* - remove characters from the end\n- *clip-start* - remove characters from the start\n- *ellipsis* or *ellipsis-end* - replace characters from the end with an ellipsis (…)\n- *ellipsis-start* - replace characters from the start with an ellipsis (…)\n- *ellipsis-middle* - replace characters from the middle with an ellipsis (…)\n\nIf no **title** was specified, if text requires truncation, a title containing the non-truncated text will be implicitly added." + }, + "textPadding": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The padding around the text in pixels; defaults to 8." + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + } + }, + "type": "object" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to generate a tooltip for this mark, and any tip options." + }, + "title": { + "$ref": "#/definitions/ChannelValue", + "description": "The title; a channel specifying accessible, short textual descriptions as strings (possibly with newlines). If the tip option is specified, the title will be displayed with an interactive tooltip instead of using the SVG [title element][1].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/title" + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The required horizontal position channel, typically bound to the *x* scale." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The required vertical position channel, typically bound to the *y* scale." + }, + "z": { + "$ref": "#/definitions/ChannelValue", + "description": "An optional ordinal channel for grouping data into (possibly stacked) series to be drawn as separate lines. If not specified, it defaults to\n**fill** if a channel, or **stroke** if a channel." + } + }, + "required": [ + "data", + "mark" + ], + "type": "object" + }, + "LineX": { + "additionalProperties": false, + "description": "The lineX mark.", + "properties": { + "ariaDescription": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-description][1]; a constant textual description.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-description" + }, + "ariaHidden": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-hidden][1] state; a constant indicating whether the element is exposed to an accessibility API.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-hidden" + }, + "ariaLabel": { + "$ref": "#/definitions/ChannelValue", + "description": "The [aria-label][1]; a channel specifying short textual labels representing the value in the accessibility tree.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-label" + }, + "clip": { + "anyOf": [ + { + "const": "frame", + "type": "string" + }, + { + "const": "sphere", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to clip the mark; one of:\n\n- *frame* or true - clip to the plot’s frame (inner area)\n- *sphere* - clip to the projected sphere (*e.g.*, front hemisphere)\n- null or false - do not clip\n\nThe *sphere* clip option requires a geographic projection." + }, + "curve": { + "anyOf": [ + { + "$ref": "#/definitions/Curve" + }, + { + "const": "auto", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The curve (interpolation) method for connecting adjacent points. One of:\n\n- *basis* - a cubic basis spline (repeating the end points)\n- *basis-open* - an open cubic basis spline\n- *basis-closed* - a closed cubic basis spline\n- *bump-x* - a Bézier curve with horizontal tangents\n- *bump-y* - a Bézier curve with vertical tangents\n- *bundle* - a straightened cubic basis spline (suitable for lines only, not areas)\n- *cardinal* - a cubic cardinal spline (with one-sided differences at the ends)\n- *cardinal-open* - an open cubic cardinal spline\n- *cardinal-closed* - an closed cubic cardinal spline\n- *catmull-rom* - a cubic Catmull–Rom spline (with one-sided differences at the ends)\n- *catmull-rom-open* - an open cubic Catmull–Rom spline\n- *catmull-rom-closed* - a closed cubic Catmull–Rom spline\n- *linear* - a piecewise linear curve (*i.e.*, straight line segments)\n- *linear-closed* - a closed piecewise linear curve (*i.e.*, straight line segments)\n- *monotone-x* - a cubic spline that preserves monotonicity in *x*\n- *monotone-y* - a cubic spline that preserves monotonicity in *y*\n- *natural* - a natural cubic spline\n- *step* - a piecewise constant function where *y* changes at the midpoint of *x*\n- *step-after* - a piecewise constant function where *y* changes after *x*\n- *step-before* - a piecewise constant function where *x* changes after *y*\n- *auto* (default) - like *linear*, but use the (possibly spherical) projection, if any\n\nThe *auto* curve is typically used in conjunction with a spherical projection to interpolate along geodesics." + }, + "data": { + "$ref": "#/definitions/PlotMarkData", + "description": "The data source for the mark." + }, + "dx": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The horizontal offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "dy": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The vertical offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "facet": { + "anyOf": [ + { + "const": "auto", + "type": "string" + }, + { + "const": "include", + "type": "string" + }, + { + "const": "exclude", + "type": "string" + }, + { + "const": "super", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to enable or disable faceting; one of:\n\n- *auto* (default) - automatically determine if this mark should be faceted\n- *include* (or true) - draw the subset of the mark’s data in the current facet\n- *exclude* - draw the subset of the mark’s data *not* in the current facet\n- *super* - draw this mark in a single frame that covers all facets\n- null (or false) - repeat this mark’s data across all facets (*i.e.*, no faceting)\n\nWhen a mark uses *super* faceting, it is not allowed to use position scales (*x*, *y*, *fx*, or *fy*); *super* faceting is intended for decorations, such as labels and legends.\n\nWhen top-level faceting is used, the default *auto* setting is equivalent to *include* when the mark data is strictly equal to the top-level facet data; otherwise it is equivalent to null. When the *include* or *exclude* facet mode is chosen, the mark data must be parallel to the top-level facet data: the data must have the same length and order. If the data are not parallel, then the wrong data may be shown in each facet. The default\n*auto* therefore requires strict equality (`===`) for safety, and using the facet data as mark data is recommended when using the *exclude* facet mode. (To construct parallel data safely, consider using [*array*.map][1] on the facet data.)\n\nWhen mark-level faceting is used, the default *auto* setting is equivalent to *include*: the mark will be faceted if either the **fx** or **fy** channel option (or both) is specified. The null or false option will disable faceting, while *exclude* draws the subset of the mark’s data *not* in the current facet.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map" + }, + "facetAnchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "right", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "const": "left", + "type": "string" + }, + { + "const": "top-left", + "type": "string" + }, + { + "const": "top-right", + "type": "string" + }, + { + "const": "bottom-left", + "type": "string" + }, + { + "const": "bottom-right", + "type": "string" + }, + { + "const": "top-empty", + "type": "string" + }, + { + "const": "right-empty", + "type": "string" + }, + { + "const": "bottom-empty", + "type": "string" + }, + { + "const": "left-empty", + "type": "string" + }, + { + "const": "empty", + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to place the mark with respect to facets; one of:\n\n- null (default for most marks) - display the mark in each non-empty facet\n- *top*, *right*, *bottom*, or *left* - display the mark only in facets on the given side\n- *top-empty*, *right-empty*, *bottom-empty*, or *left-empty* (default for axis marks) - display the mark only in facets that have empty space on the given side: either the margin, or an empty facet\n- *empty* - display the mark in empty facets only" + }, + "fill": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill" + }, + "fillOpacity": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill-opacity][1]; a constant number between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill-opacity" + }, + "filter": { + "$ref": "#/definitions/ChannelValue", + "description": "Applies a transform to filter the mark’s index according to the given channel values; only truthy values are retained.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "fx": { + "$ref": "#/definitions/ChannelValue", + "description": "The horizontal facet position channel, for mark-level faceting, bound to the *fx* scale." + }, + "fy": { + "$ref": "#/definitions/ChannelValue", + "description": "The vertical facet position channel, for mark-level faceting, bound to the\n*fy* scale." + }, + "href": { + "$ref": "#/definitions/ChannelValue", + "description": "The [href][1]; a channel specifying URLs for clickable links. May be used in conjunction with the **target** option to open links in another window.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/href" + }, + "imageFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A CSS [filter][1]; a constant string used to adjust the rendering of images, such as *blur(5px)*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/filter" + }, + "margin": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four mark margins: **marginTop**,\n**marginRight**, **marginBottom**, and **marginLeft**; typically defaults to 0, except for axis marks." + }, + "marginBottom": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s bottom margin; the minimum distance in pixels between the bottom edges of the inner and outer plot area." + }, + "marginLeft": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s left margin; the minimum distance in pixels between the left edges of the inner and outer plot area." + }, + "marginRight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s right margin; the minimum distance in pixels between the right edges of the mark’s inner and outer plot area." + }, + "marginTop": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s top margin; the minimum distance in pixels between the top edges of the inner and outer plot area." + }, + "mark": { + "const": "lineX", + "description": "Like line, except that **x** defaults to the identity function assuming that *data* = [*x₀*, *x₁*, *x₂*, …] and **y** defaults to the zero-based index [0, 1, 2, …].", + "type": "string" + }, + "marker": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for markerStart, markerMid, and markerEnd; one of:\n\n- a marker name such as *arrow* or *circle*\n- *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*" + }, + "markerEnd": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The marker for the ending point of a line segment; one of:\n\n- a marker name such as *arrow* or *circle*\n* *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*" + }, + "markerMid": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The marker for any middle (interior) points of a line segment. If the line segment only has a start and end point, this option has no effect. One of:\n\n- a marker name such as *arrow* or *circle*\n* *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*\n* a function - a custom marker function; see below" + }, + "markerStart": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The marker for the starting point of a line segment; one of:\n\n- a marker name such as *arrow* or *circle*\n* *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*" + }, + "mixBlendMode": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [mix-blend-mode][1]; a constant string specifying how to blend content such as *multiply*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode" + }, + "opacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally. For faster rendering, prefer the **strokeOpacity** or **fillOpacity** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/opacity" + }, + "paintOrder": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [paint-order][1]; a constant string specifying the order in which the\n**fill**, **stroke**, and any markers are drawn; defaults to *normal*, which draws the fill, then stroke, then markers; defaults to *stroke* for the text mark to create a “halo” around text to improve legibility.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/paint-order" + }, + "pointerEvents": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [pointer-events][1] property; a constant string such as *none*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/pointer-events" + }, + "reverse": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Applies a transform to reverse the order of the mark’s index, say for reverse input order." + }, + "select": { + "$ref": "#/definitions/SelectFilter", + "description": "Applies a filter transform after data is loaded to highlight selected values only. For example, `first` and `last` select the first or last values of series only (using the *z* channel to separate series). Meanwhile, `nearestX` and `nearestY` select the point nearest to the pointer along the *x* or *y* channel dimension. Unlike Mosaic selections, a mark level *select* is internal to the mark only, and does not populate a param or selection value to be shared across clients.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "shapeRendering": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [shape-rendering][1]; a constant string such as *crispEdges*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/shape-rendering" + }, + "sort": { + "anyOf": [ + { + "$ref": "#/definitions/SortOrder" + }, + { + "$ref": "#/definitions/ChannelDomainSort" + } + ], + "description": "Either applies a transform to sort the mark’s index by the specified channel values, or imputes ordinal scale domains from this mark’s channels.\n\nWhen imputing ordinal scale domains from channel values, the **sort** option is an object whose keys are ordinal scale names such as *x* or *fx*, and whose values are channel names such as *y*, *y1*, or *y2*. For example, to impute the *y* scale’s domain from the associated *x* channel values in ascending order:\n\n```js sort: {y: \"x\"} ```\n\nFor different sort options for different scales, replace the channel name with a *value* object and per-scale options:\n\n```js sort: {y: {value: \"-x\"}} ```\n\nWhen sorting the mark’s index, the **sort** option is instead one of:\n\n- a channel value definition for sorting given values in ascending order\n- a {value, order} object for sorting given values\n- a {channel, order} object for sorting the named channel’s values" + }, + "stroke": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke" + }, + "strokeDasharray": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dasharray][1]; a constant number indicating the length in pixels of alternating dashes and gaps, or a constant string of numbers separated by spaces or commas (_e.g._, *10 2* for dashes of 10 pixels separated by gaps of 2 pixels), or *none* (the default) for no dashing\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dasharray" + }, + "strokeDashoffset": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dashoffset][1]; a constant indicating the offset in pixels of the first dash along the stroke; defaults to zero.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dashoffset" + }, + "strokeLinecap": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linecap][1]; a constant specifying how to cap stroked paths, such as *butt*, *round*, or *square*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linecap" + }, + "strokeLinejoin": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linejoin][1]; a constant specifying how to join stroked paths, such as *bevel*, *miter*, *miter-clip*, or *round*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linejoin" + }, + "strokeMiterlimit": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-miterlimit][1]; a constant number specifying how to limit the length of *miter* joins on stroked paths.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-miterlimit" + }, + "strokeOpacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-opacity" + }, + "strokeWidth": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-width][1]; a constant number in pixels, or a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-width" + }, + "target": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [target][1]; a constant string specifying the target window (_e.g._,\n*_blank*) for clickable links; used in conjunction with the **href** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/target" + }, + "tension": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The tension option only has an effect on bundle, cardinal and Catmull–Rom splines (*bundle*, *cardinal*, *cardinal-open*, *cardinal-closed*,\n*catmull-rom*, *catmull-rom-open*, and *catmull-rom-closed*). For bundle splines, it corresponds to [beta][1]; for cardinal splines, [tension][2]; for Catmull–Rom splines, [alpha][3].\n\n[1]: https://d3js.org/d3-shape/curve#curveBundle_beta [2]: https://d3js.org/d3-shape/curve#curveCardinal_tension [3]: https://d3js.org/d3-shape/curve#curveCatmullRom_alpha" + }, + "tip": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/TipPointer" + }, + { + "properties": { + "anchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The tip anchor specifies how to orient the tip box relative to its anchor position; it refers to the part of the tip box that is attached to the anchor point. For example, the *top-left* anchor places the top-left corner of tip box near the anchor position, hence placing the tip box below and to the right of the anchor position." + }, + "fontFamily": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font-family][1]; a constant; defaults to the plot’s font family, which is typically [*system-ui*][2].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-family [2]: https://drafts.csswg.org/css-fonts-4/#valdef-font-family-system-ui" + }, + "fontSize": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font size][1] in pixels; either a constant or a channel; defaults to the plot’s font size, which is typically 10. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-size" + }, + "fontStyle": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font style][1]; a constant; defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-style" + }, + "fontVariant": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font variant][1]; a constant; if the **text** channel contains numbers or dates, defaults to *tabular-nums* to facilitate comparing numbers; otherwise defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant" + }, + "fontWeight": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font weight][1]; a constant; defaults to the plot’s font weight, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight" + }, + "format": { + "additionalProperties": false, + "description": "How channel values are formatted for display. If a format is a string, it is interpreted as a (UTC) time format for temporal channels, and otherwise a number format.", + "properties": { + "ariaLabel": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fill": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fillOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fontSize": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fx": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fy": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "geometry": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "height": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "href": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "length": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "opacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "path": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "r": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "rotate": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "src": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "stroke": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeWidth": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "symbol": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "text": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "title": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "weight": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "width": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "z": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + } + }, + "type": "object" + }, + "frameAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The frame anchor specifies defaults for **x** and **y** based on the plot’s frame; it may be one of the four sides (*top*, *right*, *bottom*, *left*), one of the four corners (*top-left*, *top-right*, *bottom-right*,\n*bottom-left*), or the *middle* of the frame. For example, for tips distributed horizontally at the top of the frame:\n\n```js Plot.tip(data, {x: \"date\", frameAnchor: \"top\"}) ```" + }, + "lineHeight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line height in ems; defaults to 1. The line height affects the (typically vertical) separation between adjacent baselines of text, as well as the separation between the text and its anchor point." + }, + "lineWidth": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line width in ems (e.g., 10 for about 20 characters); defaults to infinity, disabling wrapping and clipping.\n\nIf **textOverflow** is null, lines will be wrapped at the specified length. If a line is split at a soft hyphen (\\xad), a hyphen (-) will be displayed at the end of the line. If **textOverflow** is not null, lines will be clipped according to the given strategy." + }, + "monospace": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, changes the default **fontFamily** to *monospace*, and uses simplified monospaced text metrics calculations." + }, + "pathFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The image filter for the tip’s box; defaults to a drop shadow." + }, + "pointer": { + "$ref": "#/definitions/TipPointer" + }, + "pointerSize": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The size of the tip’s pointer in pixels; defaults to 12." + }, + "preferredAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If an explicit tip anchor is not specified, an anchor is chosen automatically such that the tip fits within the plot’s frame; if the preferred anchor fits, it is chosen." + }, + "textAnchor": { + "anyOf": [ + { + "const": "start", + "type": "string" + }, + { + "const": "middle", + "type": "string" + }, + { + "const": "end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [text anchor][1] controls how text is aligned (typically horizontally) relative to its anchor point; it is one of *start*, *end*, or *middle*. If the frame anchor is *left*, *top-left*, or *bottom-left*, the default text anchor is *start*; if the frame anchor is *right*, *top-right*, or\n*bottom-right*, the default is *end*; otherwise it is *middle*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/text-anchor" + }, + "textOverflow": { + "anyOf": [ + { + "type": "null" + }, + { + "const": "clip", + "type": "string" + }, + { + "const": "ellipsis", + "type": "string" + }, + { + "const": "clip-start", + "type": "string" + }, + { + "const": "clip-end", + "type": "string" + }, + { + "const": "ellipsis-start", + "type": "string" + }, + { + "const": "ellipsis-middle", + "type": "string" + }, + { + "const": "ellipsis-end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How truncate (or wrap) lines of text longer than the given **lineWidth**; one of:\n\n- null (default) - preserve overflowing characters (and wrap if needed)\n- *clip* or *clip-end* - remove characters from the end\n- *clip-start* - remove characters from the start\n- *ellipsis* or *ellipsis-end* - replace characters from the end with an ellipsis (…)\n- *ellipsis-start* - replace characters from the start with an ellipsis (…)\n- *ellipsis-middle* - replace characters from the middle with an ellipsis (…)\n\nIf no **title** was specified, if text requires truncation, a title containing the non-truncated text will be implicitly added." + }, + "textPadding": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The padding around the text in pixels; defaults to 8." + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + } + }, + "type": "object" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to generate a tooltip for this mark, and any tip options." + }, + "title": { + "$ref": "#/definitions/ChannelValue", + "description": "The title; a channel specifying accessible, short textual descriptions as strings (possibly with newlines). If the tip option is specified, the title will be displayed with an interactive tooltip instead of using the SVG [title element][1].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/title" + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The required horizontal position channel, typically bound to the *x* scale." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel, typically bound to the *y* scale; defaults to the zero-based index of the data [0, 1, 2, …]." + }, + "z": { + "$ref": "#/definitions/ChannelValue", + "description": "An optional ordinal channel for grouping data into (possibly stacked) series to be drawn as separate lines. If not specified, it defaults to\n**fill** if a channel, or **stroke** if a channel." + } + }, + "required": [ + "data", + "mark" + ], + "type": "object" + }, + "LineY": { + "additionalProperties": false, + "description": "The lineY mark.", + "properties": { + "ariaDescription": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-description][1]; a constant textual description.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-description" + }, + "ariaHidden": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-hidden][1] state; a constant indicating whether the element is exposed to an accessibility API.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-hidden" + }, + "ariaLabel": { + "$ref": "#/definitions/ChannelValue", + "description": "The [aria-label][1]; a channel specifying short textual labels representing the value in the accessibility tree.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-label" + }, + "clip": { + "anyOf": [ + { + "const": "frame", + "type": "string" + }, + { + "const": "sphere", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to clip the mark; one of:\n\n- *frame* or true - clip to the plot’s frame (inner area)\n- *sphere* - clip to the projected sphere (*e.g.*, front hemisphere)\n- null or false - do not clip\n\nThe *sphere* clip option requires a geographic projection." + }, + "curve": { + "anyOf": [ + { + "$ref": "#/definitions/Curve" + }, + { + "const": "auto", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The curve (interpolation) method for connecting adjacent points. One of:\n\n- *basis* - a cubic basis spline (repeating the end points)\n- *basis-open* - an open cubic basis spline\n- *basis-closed* - a closed cubic basis spline\n- *bump-x* - a Bézier curve with horizontal tangents\n- *bump-y* - a Bézier curve with vertical tangents\n- *bundle* - a straightened cubic basis spline (suitable for lines only, not areas)\n- *cardinal* - a cubic cardinal spline (with one-sided differences at the ends)\n- *cardinal-open* - an open cubic cardinal spline\n- *cardinal-closed* - an closed cubic cardinal spline\n- *catmull-rom* - a cubic Catmull–Rom spline (with one-sided differences at the ends)\n- *catmull-rom-open* - an open cubic Catmull–Rom spline\n- *catmull-rom-closed* - a closed cubic Catmull–Rom spline\n- *linear* - a piecewise linear curve (*i.e.*, straight line segments)\n- *linear-closed* - a closed piecewise linear curve (*i.e.*, straight line segments)\n- *monotone-x* - a cubic spline that preserves monotonicity in *x*\n- *monotone-y* - a cubic spline that preserves monotonicity in *y*\n- *natural* - a natural cubic spline\n- *step* - a piecewise constant function where *y* changes at the midpoint of *x*\n- *step-after* - a piecewise constant function where *y* changes after *x*\n- *step-before* - a piecewise constant function where *x* changes after *y*\n- *auto* (default) - like *linear*, but use the (possibly spherical) projection, if any\n\nThe *auto* curve is typically used in conjunction with a spherical projection to interpolate along geodesics." + }, + "data": { + "$ref": "#/definitions/PlotMarkData", + "description": "The data source for the mark." + }, + "dx": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The horizontal offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "dy": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The vertical offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "facet": { + "anyOf": [ + { + "const": "auto", + "type": "string" + }, + { + "const": "include", + "type": "string" + }, + { + "const": "exclude", + "type": "string" + }, + { + "const": "super", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to enable or disable faceting; one of:\n\n- *auto* (default) - automatically determine if this mark should be faceted\n- *include* (or true) - draw the subset of the mark’s data in the current facet\n- *exclude* - draw the subset of the mark’s data *not* in the current facet\n- *super* - draw this mark in a single frame that covers all facets\n- null (or false) - repeat this mark’s data across all facets (*i.e.*, no faceting)\n\nWhen a mark uses *super* faceting, it is not allowed to use position scales (*x*, *y*, *fx*, or *fy*); *super* faceting is intended for decorations, such as labels and legends.\n\nWhen top-level faceting is used, the default *auto* setting is equivalent to *include* when the mark data is strictly equal to the top-level facet data; otherwise it is equivalent to null. When the *include* or *exclude* facet mode is chosen, the mark data must be parallel to the top-level facet data: the data must have the same length and order. If the data are not parallel, then the wrong data may be shown in each facet. The default\n*auto* therefore requires strict equality (`===`) for safety, and using the facet data as mark data is recommended when using the *exclude* facet mode. (To construct parallel data safely, consider using [*array*.map][1] on the facet data.)\n\nWhen mark-level faceting is used, the default *auto* setting is equivalent to *include*: the mark will be faceted if either the **fx** or **fy** channel option (or both) is specified. The null or false option will disable faceting, while *exclude* draws the subset of the mark’s data *not* in the current facet.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map" + }, + "facetAnchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "right", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "const": "left", + "type": "string" + }, + { + "const": "top-left", + "type": "string" + }, + { + "const": "top-right", + "type": "string" + }, + { + "const": "bottom-left", + "type": "string" + }, + { + "const": "bottom-right", + "type": "string" + }, + { + "const": "top-empty", + "type": "string" + }, + { + "const": "right-empty", + "type": "string" + }, + { + "const": "bottom-empty", + "type": "string" + }, + { + "const": "left-empty", + "type": "string" + }, + { + "const": "empty", + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to place the mark with respect to facets; one of:\n\n- null (default for most marks) - display the mark in each non-empty facet\n- *top*, *right*, *bottom*, or *left* - display the mark only in facets on the given side\n- *top-empty*, *right-empty*, *bottom-empty*, or *left-empty* (default for axis marks) - display the mark only in facets that have empty space on the given side: either the margin, or an empty facet\n- *empty* - display the mark in empty facets only" + }, + "fill": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill" + }, + "fillOpacity": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill-opacity][1]; a constant number between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill-opacity" + }, + "filter": { + "$ref": "#/definitions/ChannelValue", + "description": "Applies a transform to filter the mark’s index according to the given channel values; only truthy values are retained.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "fx": { + "$ref": "#/definitions/ChannelValue", + "description": "The horizontal facet position channel, for mark-level faceting, bound to the *fx* scale." + }, + "fy": { + "$ref": "#/definitions/ChannelValue", + "description": "The vertical facet position channel, for mark-level faceting, bound to the\n*fy* scale." + }, + "href": { + "$ref": "#/definitions/ChannelValue", + "description": "The [href][1]; a channel specifying URLs for clickable links. May be used in conjunction with the **target** option to open links in another window.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/href" + }, + "imageFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A CSS [filter][1]; a constant string used to adjust the rendering of images, such as *blur(5px)*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/filter" + }, + "margin": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four mark margins: **marginTop**,\n**marginRight**, **marginBottom**, and **marginLeft**; typically defaults to 0, except for axis marks." + }, + "marginBottom": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s bottom margin; the minimum distance in pixels between the bottom edges of the inner and outer plot area." + }, + "marginLeft": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s left margin; the minimum distance in pixels between the left edges of the inner and outer plot area." + }, + "marginRight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s right margin; the minimum distance in pixels between the right edges of the mark’s inner and outer plot area." + }, + "marginTop": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s top margin; the minimum distance in pixels between the top edges of the inner and outer plot area." + }, + "mark": { + "const": "lineY", + "description": "Like line, except **y** defaults to the identity function and assumes that *data* = [*y₀*, *y₁*, *y₂*, …] and **x** defaults to the zero-based index [0, 1, 2, …].", + "type": "string" + }, + "marker": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for markerStart, markerMid, and markerEnd; one of:\n\n- a marker name such as *arrow* or *circle*\n- *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*" + }, + "markerEnd": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The marker for the ending point of a line segment; one of:\n\n- a marker name such as *arrow* or *circle*\n* *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*" + }, + "markerMid": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The marker for any middle (interior) points of a line segment. If the line segment only has a start and end point, this option has no effect. One of:\n\n- a marker name such as *arrow* or *circle*\n* *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*\n* a function - a custom marker function; see below" + }, + "markerStart": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The marker for the starting point of a line segment; one of:\n\n- a marker name such as *arrow* or *circle*\n* *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*" + }, + "mixBlendMode": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [mix-blend-mode][1]; a constant string specifying how to blend content such as *multiply*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode" + }, + "opacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally. For faster rendering, prefer the **strokeOpacity** or **fillOpacity** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/opacity" + }, + "paintOrder": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [paint-order][1]; a constant string specifying the order in which the\n**fill**, **stroke**, and any markers are drawn; defaults to *normal*, which draws the fill, then stroke, then markers; defaults to *stroke* for the text mark to create a “halo” around text to improve legibility.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/paint-order" + }, + "pointerEvents": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [pointer-events][1] property; a constant string such as *none*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/pointer-events" + }, + "reverse": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Applies a transform to reverse the order of the mark’s index, say for reverse input order." + }, + "select": { + "$ref": "#/definitions/SelectFilter", + "description": "Applies a filter transform after data is loaded to highlight selected values only. For example, `first` and `last` select the first or last values of series only (using the *z* channel to separate series). Meanwhile, `nearestX` and `nearestY` select the point nearest to the pointer along the *x* or *y* channel dimension. Unlike Mosaic selections, a mark level *select* is internal to the mark only, and does not populate a param or selection value to be shared across clients.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "shapeRendering": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [shape-rendering][1]; a constant string such as *crispEdges*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/shape-rendering" + }, + "sort": { + "anyOf": [ + { + "$ref": "#/definitions/SortOrder" + }, + { + "$ref": "#/definitions/ChannelDomainSort" + } + ], + "description": "Either applies a transform to sort the mark’s index by the specified channel values, or imputes ordinal scale domains from this mark’s channels.\n\nWhen imputing ordinal scale domains from channel values, the **sort** option is an object whose keys are ordinal scale names such as *x* or *fx*, and whose values are channel names such as *y*, *y1*, or *y2*. For example, to impute the *y* scale’s domain from the associated *x* channel values in ascending order:\n\n```js sort: {y: \"x\"} ```\n\nFor different sort options for different scales, replace the channel name with a *value* object and per-scale options:\n\n```js sort: {y: {value: \"-x\"}} ```\n\nWhen sorting the mark’s index, the **sort** option is instead one of:\n\n- a channel value definition for sorting given values in ascending order\n- a {value, order} object for sorting given values\n- a {channel, order} object for sorting the named channel’s values" + }, + "stroke": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke" + }, + "strokeDasharray": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dasharray][1]; a constant number indicating the length in pixels of alternating dashes and gaps, or a constant string of numbers separated by spaces or commas (_e.g._, *10 2* for dashes of 10 pixels separated by gaps of 2 pixels), or *none* (the default) for no dashing\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dasharray" + }, + "strokeDashoffset": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dashoffset][1]; a constant indicating the offset in pixels of the first dash along the stroke; defaults to zero.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dashoffset" + }, + "strokeLinecap": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linecap][1]; a constant specifying how to cap stroked paths, such as *butt*, *round*, or *square*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linecap" + }, + "strokeLinejoin": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linejoin][1]; a constant specifying how to join stroked paths, such as *bevel*, *miter*, *miter-clip*, or *round*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linejoin" + }, + "strokeMiterlimit": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-miterlimit][1]; a constant number specifying how to limit the length of *miter* joins on stroked paths.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-miterlimit" + }, + "strokeOpacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-opacity" + }, + "strokeWidth": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-width][1]; a constant number in pixels, or a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-width" + }, + "target": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [target][1]; a constant string specifying the target window (_e.g._,\n*_blank*) for clickable links; used in conjunction with the **href** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/target" + }, + "tension": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The tension option only has an effect on bundle, cardinal and Catmull–Rom splines (*bundle*, *cardinal*, *cardinal-open*, *cardinal-closed*,\n*catmull-rom*, *catmull-rom-open*, and *catmull-rom-closed*). For bundle splines, it corresponds to [beta][1]; for cardinal splines, [tension][2]; for Catmull–Rom splines, [alpha][3].\n\n[1]: https://d3js.org/d3-shape/curve#curveBundle_beta [2]: https://d3js.org/d3-shape/curve#curveCardinal_tension [3]: https://d3js.org/d3-shape/curve#curveCatmullRom_alpha" + }, + "tip": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/TipPointer" + }, + { + "properties": { + "anchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The tip anchor specifies how to orient the tip box relative to its anchor position; it refers to the part of the tip box that is attached to the anchor point. For example, the *top-left* anchor places the top-left corner of tip box near the anchor position, hence placing the tip box below and to the right of the anchor position." + }, + "fontFamily": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font-family][1]; a constant; defaults to the plot’s font family, which is typically [*system-ui*][2].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-family [2]: https://drafts.csswg.org/css-fonts-4/#valdef-font-family-system-ui" + }, + "fontSize": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font size][1] in pixels; either a constant or a channel; defaults to the plot’s font size, which is typically 10. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-size" + }, + "fontStyle": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font style][1]; a constant; defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-style" + }, + "fontVariant": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font variant][1]; a constant; if the **text** channel contains numbers or dates, defaults to *tabular-nums* to facilitate comparing numbers; otherwise defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant" + }, + "fontWeight": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font weight][1]; a constant; defaults to the plot’s font weight, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight" + }, + "format": { + "additionalProperties": false, + "description": "How channel values are formatted for display. If a format is a string, it is interpreted as a (UTC) time format for temporal channels, and otherwise a number format.", + "properties": { + "ariaLabel": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fill": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fillOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fontSize": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fx": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fy": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "geometry": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "height": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "href": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "length": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "opacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "path": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "r": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "rotate": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "src": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "stroke": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeWidth": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "symbol": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "text": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "title": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "weight": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "width": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "z": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + } + }, + "type": "object" + }, + "frameAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The frame anchor specifies defaults for **x** and **y** based on the plot’s frame; it may be one of the four sides (*top*, *right*, *bottom*, *left*), one of the four corners (*top-left*, *top-right*, *bottom-right*,\n*bottom-left*), or the *middle* of the frame. For example, for tips distributed horizontally at the top of the frame:\n\n```js Plot.tip(data, {x: \"date\", frameAnchor: \"top\"}) ```" + }, + "lineHeight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line height in ems; defaults to 1. The line height affects the (typically vertical) separation between adjacent baselines of text, as well as the separation between the text and its anchor point." + }, + "lineWidth": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line width in ems (e.g., 10 for about 20 characters); defaults to infinity, disabling wrapping and clipping.\n\nIf **textOverflow** is null, lines will be wrapped at the specified length. If a line is split at a soft hyphen (\\xad), a hyphen (-) will be displayed at the end of the line. If **textOverflow** is not null, lines will be clipped according to the given strategy." + }, + "monospace": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, changes the default **fontFamily** to *monospace*, and uses simplified monospaced text metrics calculations." + }, + "pathFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The image filter for the tip’s box; defaults to a drop shadow." + }, + "pointer": { + "$ref": "#/definitions/TipPointer" + }, + "pointerSize": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The size of the tip’s pointer in pixels; defaults to 12." + }, + "preferredAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If an explicit tip anchor is not specified, an anchor is chosen automatically such that the tip fits within the plot’s frame; if the preferred anchor fits, it is chosen." + }, + "textAnchor": { + "anyOf": [ + { + "const": "start", + "type": "string" + }, + { + "const": "middle", + "type": "string" + }, + { + "const": "end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [text anchor][1] controls how text is aligned (typically horizontally) relative to its anchor point; it is one of *start*, *end*, or *middle*. If the frame anchor is *left*, *top-left*, or *bottom-left*, the default text anchor is *start*; if the frame anchor is *right*, *top-right*, or\n*bottom-right*, the default is *end*; otherwise it is *middle*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/text-anchor" + }, + "textOverflow": { + "anyOf": [ + { + "type": "null" + }, + { + "const": "clip", + "type": "string" + }, + { + "const": "ellipsis", + "type": "string" + }, + { + "const": "clip-start", + "type": "string" + }, + { + "const": "clip-end", + "type": "string" + }, + { + "const": "ellipsis-start", + "type": "string" + }, + { + "const": "ellipsis-middle", + "type": "string" + }, + { + "const": "ellipsis-end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How truncate (or wrap) lines of text longer than the given **lineWidth**; one of:\n\n- null (default) - preserve overflowing characters (and wrap if needed)\n- *clip* or *clip-end* - remove characters from the end\n- *clip-start* - remove characters from the start\n- *ellipsis* or *ellipsis-end* - replace characters from the end with an ellipsis (…)\n- *ellipsis-start* - replace characters from the start with an ellipsis (…)\n- *ellipsis-middle* - replace characters from the middle with an ellipsis (…)\n\nIf no **title** was specified, if text requires truncation, a title containing the non-truncated text will be implicitly added." + }, + "textPadding": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The padding around the text in pixels; defaults to 8." + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + } + }, + "type": "object" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to generate a tooltip for this mark, and any tip options." + }, + "title": { + "$ref": "#/definitions/ChannelValue", + "description": "The title; a channel specifying accessible, short textual descriptions as strings (possibly with newlines). If the tip option is specified, the title will be displayed with an interactive tooltip instead of using the SVG [title element][1].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/title" + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel, typically bound to the *x* scale; defaults to the zero-based index of the data [0, 1, 2, …]." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The required vertical position channel, typically bound to the *y* scale." + }, + "z": { + "$ref": "#/definitions/ChannelValue", + "description": "An optional ordinal channel for grouping data into (possibly stacked) series to be drawn as separate lines. If not specified, it defaults to\n**fill** if a channel, or **stroke** if a channel." + } + }, + "required": [ + "data", + "mark" + ], + "type": "object" + }, + "Link": { + "additionalProperties": false, + "description": "The link mark.", + "properties": { + "ariaDescription": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-description][1]; a constant textual description.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-description" + }, + "ariaHidden": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-hidden][1] state; a constant indicating whether the element is exposed to an accessibility API.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-hidden" + }, + "ariaLabel": { + "$ref": "#/definitions/ChannelValue", + "description": "The [aria-label][1]; a channel specifying short textual labels representing the value in the accessibility tree.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-label" + }, + "clip": { + "anyOf": [ + { + "const": "frame", + "type": "string" + }, + { + "const": "sphere", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to clip the mark; one of:\n\n- *frame* or true - clip to the plot’s frame (inner area)\n- *sphere* - clip to the projected sphere (*e.g.*, front hemisphere)\n- null or false - do not clip\n\nThe *sphere* clip option requires a geographic projection." + }, + "curve": { + "anyOf": [ + { + "anyOf": [ + { + "$ref": "#/definitions/Curve" + }, + { + "const": "auto", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The curve (interpolation) method for connecting adjacent points. One of:\n\n- *basis* - a cubic basis spline (repeating the end points)\n- *basis-open* - an open cubic basis spline\n- *basis-closed* - a closed cubic basis spline\n- *bump-x* - a Bézier curve with horizontal tangents\n- *bump-y* - a Bézier curve with vertical tangents\n- *bundle* - a straightened cubic basis spline (suitable for lines only, not areas)\n- *cardinal* - a cubic cardinal spline (with one-sided differences at the ends)\n- *cardinal-open* - an open cubic cardinal spline\n- *cardinal-closed* - an closed cubic cardinal spline\n- *catmull-rom* - a cubic Catmull–Rom spline (with one-sided differences at the ends)\n- *catmull-rom-open* - an open cubic Catmull–Rom spline\n- *catmull-rom-closed* - a closed cubic Catmull–Rom spline\n- *linear* - a piecewise linear curve (*i.e.*, straight line segments)\n- *linear-closed* - a closed piecewise linear curve (*i.e.*, straight line segments)\n- *monotone-x* - a cubic spline that preserves monotonicity in *x*\n- *monotone-y* - a cubic spline that preserves monotonicity in *y*\n- *natural* - a natural cubic spline\n- *step* - a piecewise constant function where *y* changes at the midpoint of *x*\n- *step-after* - a piecewise constant function where *y* changes after *x*\n- *step-before* - a piecewise constant function where *x* changes after *y*\n- *auto* (default) - like *linear*, but use the (possibly spherical) projection, if any\n\nThe *auto* curve is typically used in conjunction with a spherical projection to interpolate along geodesics." + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The curve (interpolation) method for connecting adjacent points.\n\nSince a link has exactly two points, only the following curves (or a custom curve) are recommended: *linear*, *step*, *step-after*, *step-before*,\n*bump-x*, or *bump-y*. Note that the *linear* curve is incapable of showing a fill since a straight line has zero area. For a curved link, use an arrow mark with the **bend** option.\n\nIf the plot uses a spherical **projection**, the default *auto* **curve** will render links as geodesics; to draw a straight line instead, use the\n*linear* **curve**." + }, + "data": { + "$ref": "#/definitions/PlotMarkData", + "description": "The data source for the mark." + }, + "dx": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The horizontal offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "dy": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The vertical offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "facet": { + "anyOf": [ + { + "const": "auto", + "type": "string" + }, + { + "const": "include", + "type": "string" + }, + { + "const": "exclude", + "type": "string" + }, + { + "const": "super", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to enable or disable faceting; one of:\n\n- *auto* (default) - automatically determine if this mark should be faceted\n- *include* (or true) - draw the subset of the mark’s data in the current facet\n- *exclude* - draw the subset of the mark’s data *not* in the current facet\n- *super* - draw this mark in a single frame that covers all facets\n- null (or false) - repeat this mark’s data across all facets (*i.e.*, no faceting)\n\nWhen a mark uses *super* faceting, it is not allowed to use position scales (*x*, *y*, *fx*, or *fy*); *super* faceting is intended for decorations, such as labels and legends.\n\nWhen top-level faceting is used, the default *auto* setting is equivalent to *include* when the mark data is strictly equal to the top-level facet data; otherwise it is equivalent to null. When the *include* or *exclude* facet mode is chosen, the mark data must be parallel to the top-level facet data: the data must have the same length and order. If the data are not parallel, then the wrong data may be shown in each facet. The default\n*auto* therefore requires strict equality (`===`) for safety, and using the facet data as mark data is recommended when using the *exclude* facet mode. (To construct parallel data safely, consider using [*array*.map][1] on the facet data.)\n\nWhen mark-level faceting is used, the default *auto* setting is equivalent to *include*: the mark will be faceted if either the **fx** or **fy** channel option (or both) is specified. The null or false option will disable faceting, while *exclude* draws the subset of the mark’s data *not* in the current facet.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map" + }, + "facetAnchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "right", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "const": "left", + "type": "string" + }, + { + "const": "top-left", + "type": "string" + }, + { + "const": "top-right", + "type": "string" + }, + { + "const": "bottom-left", + "type": "string" + }, + { + "const": "bottom-right", + "type": "string" + }, + { + "const": "top-empty", + "type": "string" + }, + { + "const": "right-empty", + "type": "string" + }, + { + "const": "bottom-empty", + "type": "string" + }, + { + "const": "left-empty", + "type": "string" + }, + { + "const": "empty", + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to place the mark with respect to facets; one of:\n\n- null (default for most marks) - display the mark in each non-empty facet\n- *top*, *right*, *bottom*, or *left* - display the mark only in facets on the given side\n- *top-empty*, *right-empty*, *bottom-empty*, or *left-empty* (default for axis marks) - display the mark only in facets that have empty space on the given side: either the margin, or an empty facet\n- *empty* - display the mark in empty facets only" + }, + "fill": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill" + }, + "fillOpacity": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill-opacity][1]; a constant number between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill-opacity" + }, + "filter": { + "$ref": "#/definitions/ChannelValue", + "description": "Applies a transform to filter the mark’s index according to the given channel values; only truthy values are retained.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "fx": { + "$ref": "#/definitions/ChannelValue", + "description": "The horizontal facet position channel, for mark-level faceting, bound to the *fx* scale." + }, + "fy": { + "$ref": "#/definitions/ChannelValue", + "description": "The vertical facet position channel, for mark-level faceting, bound to the\n*fy* scale." + }, + "href": { + "$ref": "#/definitions/ChannelValue", + "description": "The [href][1]; a channel specifying URLs for clickable links. May be used in conjunction with the **target** option to open links in another window.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/href" + }, + "imageFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A CSS [filter][1]; a constant string used to adjust the rendering of images, such as *blur(5px)*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/filter" + }, + "margin": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four mark margins: **marginTop**,\n**marginRight**, **marginBottom**, and **marginLeft**; typically defaults to 0, except for axis marks." + }, + "marginBottom": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s bottom margin; the minimum distance in pixels between the bottom edges of the inner and outer plot area." + }, + "marginLeft": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s left margin; the minimum distance in pixels between the left edges of the inner and outer plot area." + }, + "marginRight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s right margin; the minimum distance in pixels between the right edges of the mark’s inner and outer plot area." + }, + "marginTop": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s top margin; the minimum distance in pixels between the top edges of the inner and outer plot area." + }, + "mark": { + "const": "link", + "description": "A link mark, drawing line segments (curves) connecting pairs of points.\n\nIf the plot uses a spherical **projection**, the default *auto* **curve** will render links as geodesics; to draw a straight line instead, use the\n*linear* **curve**.", + "type": "string" + }, + "marker": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for markerStart, markerMid, and markerEnd; one of:\n\n- a marker name such as *arrow* or *circle*\n- *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*" + }, + "markerEnd": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The marker for the ending point of a line segment; one of:\n\n- a marker name such as *arrow* or *circle*\n* *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*" + }, + "markerMid": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The marker for any middle (interior) points of a line segment. If the line segment only has a start and end point, this option has no effect. One of:\n\n- a marker name such as *arrow* or *circle*\n* *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*\n* a function - a custom marker function; see below" + }, + "markerStart": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The marker for the starting point of a line segment; one of:\n\n- a marker name such as *arrow* or *circle*\n* *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*" + }, + "mixBlendMode": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [mix-blend-mode][1]; a constant string specifying how to blend content such as *multiply*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode" + }, + "opacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally. For faster rendering, prefer the **strokeOpacity** or **fillOpacity** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/opacity" + }, + "paintOrder": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [paint-order][1]; a constant string specifying the order in which the\n**fill**, **stroke**, and any markers are drawn; defaults to *normal*, which draws the fill, then stroke, then markers; defaults to *stroke* for the text mark to create a “halo” around text to improve legibility.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/paint-order" + }, + "pointerEvents": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [pointer-events][1] property; a constant string such as *none*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/pointer-events" + }, + "reverse": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Applies a transform to reverse the order of the mark’s index, say for reverse input order." + }, + "select": { + "$ref": "#/definitions/SelectFilter", + "description": "Applies a filter transform after data is loaded to highlight selected values only. For example, `first` and `last` select the first or last values of series only (using the *z* channel to separate series). Meanwhile, `nearestX` and `nearestY` select the point nearest to the pointer along the *x* or *y* channel dimension. Unlike Mosaic selections, a mark level *select* is internal to the mark only, and does not populate a param or selection value to be shared across clients.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "shapeRendering": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [shape-rendering][1]; a constant string such as *crispEdges*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/shape-rendering" + }, + "sort": { + "anyOf": [ + { + "$ref": "#/definitions/SortOrder" + }, + { + "$ref": "#/definitions/ChannelDomainSort" + } + ], + "description": "Either applies a transform to sort the mark’s index by the specified channel values, or imputes ordinal scale domains from this mark’s channels.\n\nWhen imputing ordinal scale domains from channel values, the **sort** option is an object whose keys are ordinal scale names such as *x* or *fx*, and whose values are channel names such as *y*, *y1*, or *y2*. For example, to impute the *y* scale’s domain from the associated *x* channel values in ascending order:\n\n```js sort: {y: \"x\"} ```\n\nFor different sort options for different scales, replace the channel name with a *value* object and per-scale options:\n\n```js sort: {y: {value: \"-x\"}} ```\n\nWhen sorting the mark’s index, the **sort** option is instead one of:\n\n- a channel value definition for sorting given values in ascending order\n- a {value, order} object for sorting given values\n- a {channel, order} object for sorting the named channel’s values" + }, + "stroke": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke" + }, + "strokeDasharray": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dasharray][1]; a constant number indicating the length in pixels of alternating dashes and gaps, or a constant string of numbers separated by spaces or commas (_e.g._, *10 2* for dashes of 10 pixels separated by gaps of 2 pixels), or *none* (the default) for no dashing\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dasharray" + }, + "strokeDashoffset": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dashoffset][1]; a constant indicating the offset in pixels of the first dash along the stroke; defaults to zero.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dashoffset" + }, + "strokeLinecap": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linecap][1]; a constant specifying how to cap stroked paths, such as *butt*, *round*, or *square*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linecap" + }, + "strokeLinejoin": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linejoin][1]; a constant specifying how to join stroked paths, such as *bevel*, *miter*, *miter-clip*, or *round*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linejoin" + }, + "strokeMiterlimit": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-miterlimit][1]; a constant number specifying how to limit the length of *miter* joins on stroked paths.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-miterlimit" + }, + "strokeOpacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-opacity" + }, + "strokeWidth": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-width][1]; a constant number in pixels, or a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-width" + }, + "target": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [target][1]; a constant string specifying the target window (_e.g._,\n*_blank*) for clickable links; used in conjunction with the **href** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/target" + }, + "tension": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The tension option only has an effect on bundle, cardinal and Catmull–Rom splines (*bundle*, *cardinal*, *cardinal-open*, *cardinal-closed*,\n*catmull-rom*, *catmull-rom-open*, and *catmull-rom-closed*). For bundle splines, it corresponds to [beta][1]; for cardinal splines, [tension][2]; for Catmull–Rom splines, [alpha][3].\n\n[1]: https://d3js.org/d3-shape/curve#curveBundle_beta [2]: https://d3js.org/d3-shape/curve#curveCardinal_tension [3]: https://d3js.org/d3-shape/curve#curveCatmullRom_alpha" + }, + "tip": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/TipPointer" + }, + { + "properties": { + "anchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The tip anchor specifies how to orient the tip box relative to its anchor position; it refers to the part of the tip box that is attached to the anchor point. For example, the *top-left* anchor places the top-left corner of tip box near the anchor position, hence placing the tip box below and to the right of the anchor position." + }, + "fontFamily": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font-family][1]; a constant; defaults to the plot’s font family, which is typically [*system-ui*][2].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-family [2]: https://drafts.csswg.org/css-fonts-4/#valdef-font-family-system-ui" + }, + "fontSize": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font size][1] in pixels; either a constant or a channel; defaults to the plot’s font size, which is typically 10. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-size" + }, + "fontStyle": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font style][1]; a constant; defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-style" + }, + "fontVariant": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font variant][1]; a constant; if the **text** channel contains numbers or dates, defaults to *tabular-nums* to facilitate comparing numbers; otherwise defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant" + }, + "fontWeight": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font weight][1]; a constant; defaults to the plot’s font weight, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight" + }, + "format": { + "additionalProperties": false, + "description": "How channel values are formatted for display. If a format is a string, it is interpreted as a (UTC) time format for temporal channels, and otherwise a number format.", + "properties": { + "ariaLabel": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fill": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fillOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fontSize": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fx": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fy": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "geometry": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "height": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "href": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "length": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "opacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "path": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "r": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "rotate": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "src": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "stroke": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeWidth": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "symbol": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "text": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "title": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "weight": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "width": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "z": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + } + }, + "type": "object" + }, + "frameAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The frame anchor specifies defaults for **x** and **y** based on the plot’s frame; it may be one of the four sides (*top*, *right*, *bottom*, *left*), one of the four corners (*top-left*, *top-right*, *bottom-right*,\n*bottom-left*), or the *middle* of the frame. For example, for tips distributed horizontally at the top of the frame:\n\n```js Plot.tip(data, {x: \"date\", frameAnchor: \"top\"}) ```" + }, + "lineHeight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line height in ems; defaults to 1. The line height affects the (typically vertical) separation between adjacent baselines of text, as well as the separation between the text and its anchor point." + }, + "lineWidth": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line width in ems (e.g., 10 for about 20 characters); defaults to infinity, disabling wrapping and clipping.\n\nIf **textOverflow** is null, lines will be wrapped at the specified length. If a line is split at a soft hyphen (\\xad), a hyphen (-) will be displayed at the end of the line. If **textOverflow** is not null, lines will be clipped according to the given strategy." + }, + "monospace": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, changes the default **fontFamily** to *monospace*, and uses simplified monospaced text metrics calculations." + }, + "pathFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The image filter for the tip’s box; defaults to a drop shadow." + }, + "pointer": { + "$ref": "#/definitions/TipPointer" + }, + "pointerSize": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The size of the tip’s pointer in pixels; defaults to 12." + }, + "preferredAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If an explicit tip anchor is not specified, an anchor is chosen automatically such that the tip fits within the plot’s frame; if the preferred anchor fits, it is chosen." + }, + "textAnchor": { + "anyOf": [ + { + "const": "start", + "type": "string" + }, + { + "const": "middle", + "type": "string" + }, + { + "const": "end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [text anchor][1] controls how text is aligned (typically horizontally) relative to its anchor point; it is one of *start*, *end*, or *middle*. If the frame anchor is *left*, *top-left*, or *bottom-left*, the default text anchor is *start*; if the frame anchor is *right*, *top-right*, or\n*bottom-right*, the default is *end*; otherwise it is *middle*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/text-anchor" + }, + "textOverflow": { + "anyOf": [ + { + "type": "null" + }, + { + "const": "clip", + "type": "string" + }, + { + "const": "ellipsis", + "type": "string" + }, + { + "const": "clip-start", + "type": "string" + }, + { + "const": "clip-end", + "type": "string" + }, + { + "const": "ellipsis-start", + "type": "string" + }, + { + "const": "ellipsis-middle", + "type": "string" + }, + { + "const": "ellipsis-end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How truncate (or wrap) lines of text longer than the given **lineWidth**; one of:\n\n- null (default) - preserve overflowing characters (and wrap if needed)\n- *clip* or *clip-end* - remove characters from the end\n- *clip-start* - remove characters from the start\n- *ellipsis* or *ellipsis-end* - replace characters from the end with an ellipsis (…)\n- *ellipsis-start* - replace characters from the start with an ellipsis (…)\n- *ellipsis-middle* - replace characters from the middle with an ellipsis (…)\n\nIf no **title** was specified, if text requires truncation, a title containing the non-truncated text will be implicitly added." + }, + "textPadding": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The padding around the text in pixels; defaults to 8." + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + } + }, + "type": "object" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to generate a tooltip for this mark, and any tip options." + }, + "title": { + "$ref": "#/definitions/ChannelValue", + "description": "The title; a channel specifying accessible, short textual descriptions as strings (possibly with newlines). If the tip option is specified, the title will be displayed with an interactive tooltip instead of using the SVG [title element][1].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/title" + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position, for vertical links; typically bound to the *x* scale; shorthand for setting defaults for both **x1** and **x2**." + }, + "x1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting horizontal position; typically bound to the *x* scale; also sets a default for **x2**." + }, + "x2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending horizontal position; typically bound to the *x* scale; also sets a default for **x1**." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position, for horizontal links; typically bound to the *y* scale; shorthand for setting defaults for both **y1** and **y2**." + }, + "y1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting vertical position; typically bound to the *y* scale; also sets a default for **y2**." + }, + "y2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending vertical position; typically bound to the *y* scale; also sets a default for **y1**." + } + }, + "required": [ + "data", + "mark" + ], + "type": "object" + }, + "LiteralTimeInterval": { + "anyOf": [ + { + "const": "3 months", + "type": "string" + }, + { + "const": "10 years", + "type": "string" + }, + { + "$ref": "#/definitions/TimeIntervalName" + }, + { + "const": "seconds", + "type": "string" + }, + { + "const": "minutes", + "type": "string" + }, + { + "const": "hours", + "type": "string" + }, + { + "const": "days", + "type": "string" + }, + { + "const": "weeks", + "type": "string" + }, + { + "const": "months", + "type": "string" + }, + { + "const": "quarters", + "type": "string" + }, + { + "const": "halfs", + "type": "string" + }, + { + "const": "years", + "type": "string" + }, + { + "const": "mondays", + "type": "string" + }, + { + "const": "tuesdays", + "type": "string" + }, + { + "const": "wednesdays", + "type": "string" + }, + { + "const": "thursdays", + "type": "string" + }, + { + "const": "fridays", + "type": "string" + }, + { + "const": "saturdays", + "type": "string" + }, + { + "const": "sundays", + "type": "string" + }, + { + "type": "string" + } + ] + }, + "MarkerName": { + "description": "The built-in marker implementations; one of:\n\n- *arrow* - an arrowhead with *auto* orientation\n- *arrow-reverse* - an arrowhead with *auto-start-reverse* orientation\n- *dot* - a filled *circle* with no stroke and 2.5px radius\n- *circle-fill* - a filled circle with a white stroke and 3px radius\n- *circle-stroke* - a stroked circle with a white fill and 3px radius\n- *circle* - alias for *circle-fill*\n- *tick* - a small opposing line\n- *tick-x* - a small horizontal line\n- *tick-y* - a small vertical line", + "enum": [ + "arrow", + "arrow-reverse", + "dot", + "circle", + "circle-fill", + "circle-stroke", + "tick", + "tick-x", + "tick-y" + ], + "type": "string" + }, + "Max": { + "additionalProperties": false, + "properties": { + "distinct": { + "type": "boolean" + }, + "max": { + "anyOf": [ + { + "description": "A transform argument.", + "type": [ + "string", + "number", + "boolean" + ] + }, + { + "items": { + "description": "A transform argument.", + "type": [ + "string", + "number", + "boolean" + ] + }, + "maxItems": 1, + "minItems": 1, + "type": "array" + } + ], + "description": "Compute the maximum value of the given column." + }, + "orderby": { + "anyOf": [ + { + "$ref": "#/definitions/TransformField" + }, + { + "items": { + "$ref": "#/definitions/TransformField" + }, + "type": "array" + } + ] + }, + "partitionby": { + "anyOf": [ + { + "$ref": "#/definitions/TransformField" + }, + { + "items": { + "$ref": "#/definitions/TransformField" + }, + "type": "array" + } + ] + }, + "range": { + "anyOf": [ + { + "items": { + "type": [ + "number", + "null" + ] + }, + "type": "array" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "rows": { + "anyOf": [ + { + "items": { + "type": [ + "number", + "null" + ] + }, + "type": "array" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + } + }, + "required": [ + "max" + ], + "type": "object" + }, + "Median": { + "additionalProperties": false, + "properties": { + "distinct": { + "type": "boolean" + }, + "median": { + "anyOf": [ + { + "description": "A transform argument.", + "type": [ + "string", + "number", + "boolean" + ] + }, + { + "items": { + "description": "A transform argument.", + "type": [ + "string", + "number", + "boolean" + ] + }, + "maxItems": 1, + "minItems": 1, + "type": "array" + } + ], + "description": "Compute the median value of the given column." + }, + "orderby": { + "anyOf": [ + { + "$ref": "#/definitions/TransformField" + }, + { + "items": { + "$ref": "#/definitions/TransformField" + }, + "type": "array" + } + ] + }, + "partitionby": { + "anyOf": [ + { + "$ref": "#/definitions/TransformField" + }, + { + "items": { + "$ref": "#/definitions/TransformField" + }, + "type": "array" + } + ] + }, + "range": { + "anyOf": [ + { + "items": { + "type": [ + "number", + "null" + ] + }, + "type": "array" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "rows": { + "anyOf": [ + { + "items": { + "type": [ + "number", + "null" + ] + }, + "type": "array" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + } + }, + "required": [ + "median" + ], + "type": "object" + }, + "Menu": { + "additionalProperties": false, + "description": "A menu input component.", + "properties": { + "as": { + "$ref": "#/definitions/ParamRef", + "description": "The output selection. A selection clause is added for the currently selected menu option." + }, + "column": { + "description": "The name of a database column from which to pull menu options. The unique column values are used as menu options. Used in conjunction with the `from` property.", + "type": "string" + }, + "field": { + "description": "The database column name to use within generated selection clause predicates. Defaults to the `column` property.", + "type": "string" + }, + "filterBy": { + "$ref": "#/definitions/ParamRef", + "description": "A selection to filter the database table indicated by the `from` property." + }, + "from": { + "description": "The name of a database table to use as a data source for this widget. Used in conjunction with the `column` property.", + "type": "string" + }, + "input": { + "const": "menu", + "description": "A menu input widget.", + "type": "string" + }, + "label": { + "description": "A text label for this input.", + "type": "string" + }, + "options": { + "description": "An array of menu options, as literal values or option objects. Option objects have a `value` property and an optional `label` property. If no label is provided, the string-coerced value is used.", + "items": { + "anyOf": [ + {}, + { + "additionalProperties": false, + "properties": { + "label": { + "type": "string" + }, + "value": {} + }, + "required": [ + "value" + ], + "type": "object" + } + ] + }, + "type": "array" + }, + "value": { + "description": "The initial selected menu value." + } + }, + "required": [ + "input" + ], + "type": "object" + }, + "Meta": { + "description": "Specification metadata.", + "properties": { + "credit": { + "description": "Credits or other acknowledgements.", + "type": "string" + }, + "description": { + "description": "A description of the specification content.", + "type": "string" + }, + "title": { + "description": "The specification title.", + "type": "string" + } + }, + "type": "object" + }, + "Min": { + "additionalProperties": false, + "properties": { + "distinct": { + "type": "boolean" + }, + "min": { + "anyOf": [ + { + "description": "A transform argument.", + "type": [ + "string", + "number", + "boolean" + ] + }, + { + "items": { + "description": "A transform argument.", + "type": [ + "string", + "number", + "boolean" + ] + }, + "maxItems": 1, + "minItems": 1, + "type": "array" + } + ], + "description": "Compute the minimum value of the given column." + }, + "orderby": { + "anyOf": [ + { + "$ref": "#/definitions/TransformField" + }, + { + "items": { + "$ref": "#/definitions/TransformField" + }, + "type": "array" + } + ] + }, + "partitionby": { + "anyOf": [ + { + "$ref": "#/definitions/TransformField" + }, + { + "items": { + "$ref": "#/definitions/TransformField" + }, + "type": "array" + } + ] + }, + "range": { + "anyOf": [ + { + "items": { + "type": [ + "number", + "null" + ] + }, + "type": "array" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "rows": { + "anyOf": [ + { + "items": { + "type": [ + "number", + "null" + ] + }, + "type": "array" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + } + }, + "required": [ + "min" + ], + "type": "object" + }, + "Mode": { + "additionalProperties": false, + "properties": { + "distinct": { + "type": "boolean" + }, + "mode": { + "anyOf": [ + { + "description": "A transform argument.", + "type": [ + "string", + "number", + "boolean" + ] + }, + { + "items": { + "description": "A transform argument.", + "type": [ + "string", + "number", + "boolean" + ] + }, + "maxItems": 1, + "minItems": 1, + "type": "array" + } + ], + "description": "Compute the mode value of the given column." + }, + "orderby": { + "anyOf": [ + { + "$ref": "#/definitions/TransformField" + }, + { + "items": { + "$ref": "#/definitions/TransformField" + }, + "type": "array" + } + ] + }, + "partitionby": { + "anyOf": [ + { + "$ref": "#/definitions/TransformField" + }, + { + "items": { + "$ref": "#/definitions/TransformField" + }, + "type": "array" + } + ] + }, + "range": { + "anyOf": [ + { + "items": { + "type": [ + "number", + "null" + ] + }, + "type": "array" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "rows": { + "anyOf": [ + { + "items": { + "type": [ + "number", + "null" + ] + }, + "type": "array" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + } + }, + "required": [ + "mode" + ], + "type": "object" + }, + "NTile": { + "additionalProperties": false, + "properties": { + "ntile": { + "anyOf": [ + { + "description": "A transform argument.", + "type": [ + "string", + "number", + "boolean" + ] + }, + { + "items": { + "description": "A transform argument.", + "type": [ + "string", + "number", + "boolean" + ] + }, + "maxItems": 1, + "minItems": 1, + "type": "array" + } + ], + "description": "Compute an n-tile integer ranging from 1 to the provided argument (num_buckets), dividing the partition as equally as possible." + }, + "orderby": { + "anyOf": [ + { + "$ref": "#/definitions/TransformField" + }, + { + "items": { + "$ref": "#/definitions/TransformField" + }, + "type": "array" + } + ] + }, + "partitionby": { + "anyOf": [ + { + "$ref": "#/definitions/TransformField" + }, + { + "items": { + "$ref": "#/definitions/TransformField" + }, + "type": "array" + } + ] + }, + "range": { + "anyOf": [ + { + "items": { + "type": [ + "number", + "null" + ] + }, + "type": "array" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "rows": { + "anyOf": [ + { + "items": { + "type": [ + "number", + "null" + ] + }, + "type": "array" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + } + }, + "required": [ + "ntile" + ], + "type": "object" + }, + "NearestX": { + "additionalProperties": false, + "description": "A nearestX interactor.", + "properties": { + "as": { + "$ref": "#/definitions/ParamRef", + "description": "The output selection. A clause of the form `field = value` is added for the currently nearest value." + }, + "channels": { + "description": "The encoding channels whose domain values should be selected. For example, a setting of `['color']` selects the data value backing the color channel, whereas `['x', 'z']` selects both x and z channel domain values. If unspecified, the selected channels default to match the current pointer settings: a `nearestX` interactor selects the `['x']` channels, while a `nearest` interactor selects the `['x', 'y']` channels.", + "items": { + "type": "string" + }, + "type": "array" + }, + "fields": { + "description": "The fields (database column names) to use in generated selection clause predicates. If unspecified, the fields backing the selected *channels* in the first valid prior mark definition are used by default.", + "items": { + "type": "string" + }, + "type": "array" + }, + "maxRadius": { + "description": "The maximum radius of a nearest selection (default 40). Marks with (x, y) coordinates outside this radius will not be selected as nearest points.", + "type": "number" + }, + "select": { + "const": "nearestX", + "description": "Select values from the mark closest to the pointer *x* location.", + "type": "string" + } + }, + "required": [ + "as", + "select" + ], + "type": "object" + }, + "NearestY": { + "additionalProperties": false, + "description": "A nearestY interactor.", + "properties": { + "as": { + "$ref": "#/definitions/ParamRef", + "description": "The output selection. A clause of the form `field = value` is added for the currently nearest value." + }, + "channels": { + "description": "The encoding channels whose domain values should be selected. For example, a setting of `['color']` selects the data value backing the color channel, whereas `['x', 'z']` selects both x and z channel domain values. If unspecified, the selected channels default to match the current pointer settings: a `nearestX` interactor selects the `['x']` channels, while a `nearest` interactor selects the `['x', 'y']` channels.", + "items": { + "type": "string" + }, + "type": "array" + }, + "fields": { + "description": "The fields (database column names) to use in generated selection clause predicates. If unspecified, the fields backing the selected *channels* in the first valid prior mark definition are used by default.", + "items": { + "type": "string" + }, + "type": "array" + }, + "maxRadius": { + "description": "The maximum radius of a nearest selection (default 40). Marks with (x, y) coordinates outside this radius will not be selected as nearest points.", + "type": "number" + }, + "select": { + "const": "nearestY", + "description": "Select values from the mark closest to the pointer *y* location.", + "type": "string" + } + }, + "required": [ + "as", + "select" + ], + "type": "object" + }, + "NthValue": { + "additionalProperties": false, + "properties": { + "nth_value": { + "anyOf": [ + { + "description": "A transform argument.", + "type": [ + "string", + "number", + "boolean" + ] + }, + { + "items": { + "description": "A transform argument.", + "type": [ + "string", + "number", + "boolean" + ] + }, + "maxItems": 2, + "minItems": 1, + "type": "array" + } + ], + "description": "Get the nth value of the given column in the current window frame, counting from one. The second argument is the offset for the nth row." + }, + "orderby": { + "anyOf": [ + { + "$ref": "#/definitions/TransformField" + }, + { + "items": { + "$ref": "#/definitions/TransformField" + }, + "type": "array" + } + ] + }, + "partitionby": { + "anyOf": [ + { + "$ref": "#/definitions/TransformField" + }, + { + "items": { + "$ref": "#/definitions/TransformField" + }, + "type": "array" + } + ] + }, + "range": { + "anyOf": [ + { + "items": { + "type": [ + "number", + "null" + ] + }, + "type": "array" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "rows": { + "anyOf": [ + { + "items": { + "type": [ + "number", + "null" + ] + }, + "type": "array" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + } + }, + "required": [ + "nth_value" + ], + "type": "object" + }, + "Pan": { + "additionalProperties": false, + "description": "A pan interactor.", + "properties": { + "select": { + "const": "pan", + "description": "Pan a plot along both the `x` and `y` scales.", + "type": "string" + }, + "x": { + "$ref": "#/definitions/ParamRef", + "description": "The output selection for the `x` domain. A clause of the form `field BETWEEN x1 AND x2` is added for the current pan/zom interval [x1, x2]." + }, + "xfield": { + "description": "The name of the field (database column) over which the `x`-component of the pan/zoom interval should be defined. If unspecified, the `x` channel field of the first valid prior mark definition is used.", + "type": "string" + }, + "y": { + "$ref": "#/definitions/ParamRef", + "description": "The output selection for the `y` domain. A clause of the form `field BETWEEN y1 AND y2` is added for the current pan/zom interval [y1, y2]." + }, + "yfield": { + "description": "The name of the field (database column) over which the `y`-component of the pan/zoom interval should be defined. If unspecified, the `y` channel field of the first valid prior mark definition is used.", + "type": "string" + } + }, + "required": [ + "select" + ], + "type": "object" + }, + "PanX": { + "additionalProperties": false, + "description": "A panX interactor.", + "properties": { + "select": { + "const": "panX", + "description": "Pan a plot along the `x` scale only.", + "type": "string" + }, + "x": { + "$ref": "#/definitions/ParamRef", + "description": "The output selection for the `x` domain. A clause of the form `field BETWEEN x1 AND x2` is added for the current pan/zom interval [x1, x2]." + }, + "xfield": { + "description": "The name of the field (database column) over which the `x`-component of the pan/zoom interval should be defined. If unspecified, the `x` channel field of the first valid prior mark definition is used.", + "type": "string" + }, + "y": { + "$ref": "#/definitions/ParamRef", + "description": "The output selection for the `y` domain. A clause of the form `field BETWEEN y1 AND y2` is added for the current pan/zom interval [y1, y2]." + }, + "yfield": { + "description": "The name of the field (database column) over which the `y`-component of the pan/zoom interval should be defined. If unspecified, the `y` channel field of the first valid prior mark definition is used.", + "type": "string" + } + }, + "required": [ + "select" + ], + "type": "object" + }, + "PanY": { + "additionalProperties": false, + "description": "A panY interactor.", + "properties": { + "select": { + "const": "panY", + "description": "Pan a plot along the `y` scale only.", + "type": "string" + }, + "x": { + "$ref": "#/definitions/ParamRef", + "description": "The output selection for the `x` domain. A clause of the form `field BETWEEN x1 AND x2` is added for the current pan/zom interval [x1, x2]." + }, + "xfield": { + "description": "The name of the field (database column) over which the `x`-component of the pan/zoom interval should be defined. If unspecified, the `x` channel field of the first valid prior mark definition is used.", + "type": "string" + }, + "y": { + "$ref": "#/definitions/ParamRef", + "description": "The output selection for the `y` domain. A clause of the form `field BETWEEN y1 AND y2` is added for the current pan/zom interval [y1, y2]." + }, + "yfield": { + "description": "The name of the field (database column) over which the `y`-component of the pan/zoom interval should be defined. If unspecified, the `y` channel field of the first valid prior mark definition is used.", + "type": "string" + } + }, + "required": [ + "select" + ], + "type": "object" + }, + "PanZoom": { + "additionalProperties": false, + "description": "A panZoom interactor.", + "properties": { + "select": { + "const": "panZoom", + "description": "Pan and zoom a plot along both the `x` and `y` scales.", + "type": "string" + }, + "x": { + "$ref": "#/definitions/ParamRef", + "description": "The output selection for the `x` domain. A clause of the form `field BETWEEN x1 AND x2` is added for the current pan/zom interval [x1, x2]." + }, + "xfield": { + "description": "The name of the field (database column) over which the `x`-component of the pan/zoom interval should be defined. If unspecified, the `x` channel field of the first valid prior mark definition is used.", + "type": "string" + }, + "y": { + "$ref": "#/definitions/ParamRef", + "description": "The output selection for the `y` domain. A clause of the form `field BETWEEN y1 AND y2` is added for the current pan/zom interval [y1, y2]." + }, + "yfield": { + "description": "The name of the field (database column) over which the `y`-component of the pan/zoom interval should be defined. If unspecified, the `y` channel field of the first valid prior mark definition is used.", + "type": "string" + } + }, + "required": [ + "select" + ], + "type": "object" + }, + "PanZoomX": { + "additionalProperties": false, + "description": "A panZoomX interactor.", + "properties": { + "select": { + "const": "panZoomX", + "description": "Pan and zoom a plot along the `x` scale only.", + "type": "string" + }, + "x": { + "$ref": "#/definitions/ParamRef", + "description": "The output selection for the `x` domain. A clause of the form `field BETWEEN x1 AND x2` is added for the current pan/zom interval [x1, x2]." + }, + "xfield": { + "description": "The name of the field (database column) over which the `x`-component of the pan/zoom interval should be defined. If unspecified, the `x` channel field of the first valid prior mark definition is used.", + "type": "string" + }, + "y": { + "$ref": "#/definitions/ParamRef", + "description": "The output selection for the `y` domain. A clause of the form `field BETWEEN y1 AND y2` is added for the current pan/zom interval [y1, y2]." + }, + "yfield": { + "description": "The name of the field (database column) over which the `y`-component of the pan/zoom interval should be defined. If unspecified, the `y` channel field of the first valid prior mark definition is used.", + "type": "string" + } + }, + "required": [ + "select" + ], + "type": "object" + }, + "PanZoomY": { + "additionalProperties": false, + "description": "A panZoomY interactor.", + "properties": { + "select": { + "const": "panZoomY", + "description": "Pan and zoom a plot along the `y` scale only.", + "type": "string" + }, + "x": { + "$ref": "#/definitions/ParamRef", + "description": "The output selection for the `x` domain. A clause of the form `field BETWEEN x1 AND x2` is added for the current pan/zom interval [x1, x2]." + }, + "xfield": { + "description": "The name of the field (database column) over which the `x`-component of the pan/zoom interval should be defined. If unspecified, the `x` channel field of the first valid prior mark definition is used.", + "type": "string" + }, + "y": { + "$ref": "#/definitions/ParamRef", + "description": "The output selection for the `y` domain. A clause of the form `field BETWEEN y1 AND y2` is added for the current pan/zom interval [y1, y2]." + }, + "yfield": { + "description": "The name of the field (database column) over which the `y`-component of the pan/zoom interval should be defined. If unspecified, the `y` channel field of the first valid prior mark definition is used.", + "type": "string" + } + }, + "required": [ + "select" + ], + "type": "object" + }, + "Param": { + "additionalProperties": false, + "description": "A Param definition.", + "properties": { + "select": { + "const": "value", + "description": "The type of reactive parameter. One of:\n- `\"value\"` (default) for a standard `Param`\n- `\"intersect\"` for a `Selection` that intersects clauses (logical \"and\")\n- `\"union\"` for a `Selection` that unions clauses (logical \"or\")\n- `\"single\"` for a `Selection` that retains a single clause only\n- `\"crossfilter\"` for a cross-filtered intersection `Selection`", + "type": "string" + }, + "value": { + "$ref": "#/definitions/ParamValue", + "description": "The initial parameter value." + } + }, + "required": [ + "value" + ], + "type": "object" + }, + "ParamDate": { + "additionalProperties": false, + "description": "A Date-valued Param definition.", + "properties": { + "date": { + "description": "The initial parameter value as an ISO date/time string to be parsed to a Date object.", + "type": "string" + }, + "select": { + "const": "value", + "description": "The type of reactive parameter. One of:\n- `\"value\"` (default) for a standard `Param`\n- `\"intersect\"` for a `Selection` that intersects clauses (logical \"and\")\n- `\"union\"` for a `Selection` that unions clauses (logical \"or\")\n- `\"single\"` for a `Selection` that retains a single clause only\n- `\"crossfilter\"` for a cross-filtered intersection `Selection`", + "type": "string" + } + }, + "required": [ + "date" + ], + "type": "object" + }, + "ParamDefinition": { + "anyOf": [ + { + "$ref": "#/definitions/ParamValue" + }, + { + "$ref": "#/definitions/Param" + }, + { + "$ref": "#/definitions/ParamDate" + }, + { + "$ref": "#/definitions/Selection" + } + ], + "description": "A Param or Selection definition." + }, + "ParamLiteral": { + "description": "Literal Param values.", + "type": [ + "string", + "number", + "boolean" + ] + }, + "ParamRef": { + "type": "string" + }, + "ParamValue": { + "anyOf": [ + { + "$ref": "#/definitions/ParamLiteral" + }, + { + "items": { + "anyOf": [ + { + "$ref": "#/definitions/ParamLiteral" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "type": "array" + } + ], + "description": "Valid Param values." + }, + "Params": { + "additionalProperties": { + "$ref": "#/definitions/ParamDefinition" + }, + "description": "Top-level Param and Selection definitions.", + "type": "object" + }, + "PercentRank": { + "additionalProperties": false, + "properties": { + "orderby": { + "anyOf": [ + { + "$ref": "#/definitions/TransformField" + }, + { + "items": { + "$ref": "#/definitions/TransformField" + }, + "type": "array" + } + ] + }, + "partitionby": { + "anyOf": [ + { + "$ref": "#/definitions/TransformField" + }, + { + "items": { + "$ref": "#/definitions/TransformField" + }, + "type": "array" + } + ] + }, + "percent_rank": { + "anyOf": [ + { + "type": "null" + }, + { + "maxItems": 0, + "minItems": 0, + "type": "array" + } + ], + "description": "Compute the percetange rank over an ordered window partition." + }, + "range": { + "anyOf": [ + { + "items": { + "type": [ + "number", + "null" + ] + }, + "type": "array" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "rows": { + "anyOf": [ + { + "items": { + "type": [ + "number", + "null" + ] + }, + "type": "array" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + } + }, + "required": [ + "percent_rank" + ], + "type": "object" + }, + "Plot": { + "additionalProperties": false, + "description": "A plot component.", + "properties": { + "align": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to distribute unused space in the **range** for *point* and *band* scales. A number in [0, 1], such as:\n\n- 0 - use the start of the range, putting unused space at the end\n- 0.5 (default) - use the middle, distributing unused space evenly\n- 1 use the end, putting unused space at the start\n\nFor ordinal position scales only." + }, + "aspectRatio": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The desired aspect ratio of the *x* and *y* scales, affecting the default height. Given an aspect ratio of *dx* / *dy*, and assuming that the *x* and\n*y* scales represent equivalent units (say, degrees Celsius or meters), computes a default height such that *dx* pixels along *x* represents the same variation as *dy* pixels along *y*. Note: when faceting, set the *fx* and *fy* scales’ **round** option to false for an exact aspect ratio." + }, + "axis": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "right", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "const": "left", + "type": "string" + }, + { + "const": "both", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The side of the frame on which to place the implicit axis: *top* or\n*bottom* for *x* or *fx*, or *left* or *right* for *y* or *fy*. The default depends on the scale:\n\n- *x* - *bottom*\n- *y* - *left*\n- *fx* - *top* if there is a *bottom* *x* axis, and otherwise *bottom*\n- *fy* - *right* if there is a *left* *y* axis, and otherwise *right*\n\nIf *both*, an implicit axis will be rendered on both sides of the plot (*top* and *bottom* for *x* or *fx*, or *left* and *right* for *y* or\n*fy*). If null, the implicit axis is suppressed.\n\nFor position axes only." + }, + "colorBase": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A log scale’s base; defaults to 10. Does not affect the scale’s encoding, but rather the default ticks. For *log* and *diverging-log* scales only." + }, + "colorClamp": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, values below the domain minimum are treated as the domain minimum, and values above the domain maximum are treated as the domain maximum.\n\nClamping is useful for focusing on a subset of the data while ensuring that extreme values remain visible, but use caution: clamped values may need an annotation to avoid misinterpretation. Clamping typically requires setting an explicit **domain** since if the domain is inferred, no values will be outside the domain.\n\nFor continuous scales only." + }, + "colorConstant": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A symlog scale’s constant, expressing the magnitude of the linear region around the origin; defaults to 1. For *symlog* and *diverging-symlog* scales only." + }, + "colorDomain": { + "anyOf": [ + { + "items": {}, + "type": "array" + }, + { + "$ref": "#/definitions/Fixed" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The extent of the scale’s inputs (abstract values). By default inferred from channel values. For continuous data (numbers and dates), it is typically [*min*, *max*]; it can be [*max*, *min*] to reverse the scale. For ordinal data (strings or booleans), it is an array (or iterable) of values is the desired order, defaulting to natural ascending order." + }, + "colorExponent": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A power scale’s exponent (*e.g.*, 0.5 for sqrt); defaults to 1 for a linear scale. For *pow* and *diverging-pow* scales only." + }, + "colorInterpolate": { + "anyOf": [ + { + "$ref": "#/definitions/Interpolate" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to interpolate color range values. For quantitative scales only. This attribute can be used to specify a color space for interpolating colors specified in the **colorRange**." + }, + "colorLabel": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A textual label to show on the axis or legend; if null, show no label. By default the scale label is inferred from channel definitions, possibly with an arrow (↑, →, ↓, or ←) to indicate the direction of increasing value.\n\nFor axes and legends only." + }, + "colorN": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "For a *quantile* scale, the number of quantiles (creates *n* - 1 thresholds); for a *quantize* scale, the approximate number of thresholds; defaults to 5." + }, + "colorNice": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/Interval" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, or a tick count or interval, extend the domain to nice round values. Defaults to 1, 2 or 5 times a power of 10 for *linear* scales, and nice time intervals for *utc* and *time* scales. Pass an interval such as\n*minute*, *wednesday* or *month* to specify what constitutes a nice interval.\n\nFor continuous scales only." + }, + "colorPercent": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, shorthand for a transform suitable for percentages, mapping proportions in [0, 1] to [0, 100]." + }, + "colorPivot": { + "anyOf": [ + {}, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "For a diverging color scale, the input value (abstract value) that divides the domain into two parts; defaults to 0 for *diverging* scales, dividing the domain into negative and positive parts; defaults to 1 for\n*diverging-log* scales. By default, diverging scales are symmetric around the pivot; see the **symmetric** option." + }, + "colorRange": { + "anyOf": [ + { + "items": {}, + "type": "array" + }, + { + "$ref": "#/definitions/Fixed" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The extent of the scale’s outputs (visual values). By default inferred from the scale’s **type** and **domain**. For other ordinal data, it is an array (or iterable) of output values in the same order as the **domain**." + }, + "colorReverse": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to reverse the scale’s encoding; equivalent to reversing either the\n**domain** or **range**." + }, + "colorScale": { + "anyOf": [ + { + "$ref": "#/definitions/ColorScaleType" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The *color* scale type, affecting how the scale encodes abstract data, say by applying a mathematical transformation. If null, the scale is disabled.\n\nFor quantitative data (numbers), defaults to *linear*; for temporal data (dates), defaults to *utc*; for ordinal data (strings or booleans), defaults to *point* for position scales, *categorical* for color scales, and otherwise *ordinal*." + }, + "colorScheme": { + "anyOf": [ + { + "$ref": "#/definitions/ColorScheme" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If specified, shorthand for setting the **colorRange** or **colorInterpolate** option of a *color* scale." + }, + "colorSymmetric": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "For a diverging color scale, if true (the default), extend the domain to ensure that the lower part of the domain (below the **pivot**) is commensurate with the upper part of the domain (above the **pivot**).\n\nA symmetric diverging color scale may not use all of its output **range**; this reduces contrast but ensures that deviations both below and above the\n**pivot** are represented proportionally. Otherwise if false, the full output **range** will be used; this increases contrast but values on opposite sides of the **pivot** may not be meaningfully compared." + }, + "colorTickFormat": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to format inputs (abstract values) for axis tick labels; one of:\n\n- a [d3-format][1] string for numeric scales\n- a [d3-time-format][2] string for temporal scales\n\n[1]: https://d3js.org/d3-time [2]: https://d3js.org/d3-time-format" + }, + "colorZero": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether the **domain** must include zero. If the domain minimum is positive, it will be set to zero; otherwise if the domain maximum is negative, it will be set to zero.\n\nFor quantitative scales only." + }, + "facetGrid": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/Interval" + }, + { + "items": {}, + "type": "array" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Default axis grid for fx and fy scales; typically set to true to enable." + }, + "facetLabel": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Default axis label for fx and fy scales; typically set to null to disable." + }, + "facetMargin": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four facet margins: marginTop, marginRight, marginBottom, and marginLeft." + }, + "facetMarginBottom": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The right facet margin; the (minimum) distance in pixels between the right edges of the inner and outer plot area." + }, + "facetMarginLeft": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The bottom facet margin; the (minimum) distance in pixels between the bottom edges of the inner and outer plot area." + }, + "facetMarginRight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The left facet margin; the (minimum) distance in pixels between the left edges of the inner and outer plot area." + }, + "facetMarginTop": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The top facet margin; the (minimum) distance in pixels between the top edges of the inner and outer plot area." + }, + "fxAlign": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to distribute unused space in the **range** for *point* and *band* scales. A number in [0, 1], such as:\n\n- 0 - use the start of the range, putting unused space at the end\n- 0.5 (default) - use the middle, distributing unused space evenly\n- 1 use the end, putting unused space at the start\n\nFor ordinal position scales only." + }, + "fxAriaDescription": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A textual description for the axis in the accessibility tree." + }, + "fxAriaLabel": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A short label representing the axis in the accessibility tree." + }, + "fxAxis": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "const": "both", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The side of the frame on which to place the implicit axis: *top* or\n*bottom* for *fx*. Defaults to *top* if there is a *bottom* *x* axis, and otherwise *bottom*.\n\nIf *both*, an implicit axis will be rendered on both sides of the plot (*top* and *bottom* for *fx*). If null, the implicit axis is suppressed." + }, + "fxDomain": { + "anyOf": [ + { + "items": {}, + "type": "array" + }, + { + "$ref": "#/definitions/Fixed" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The extent of the scale’s inputs (abstract values). By default inferred from channel values. For ordinal data (strings or booleans), it is an array (or iterable) of values is the desired order, defaulting to natural ascending order." + }, + "fxFontVariant": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The font-variant attribute for axis ticks; defaults to *tabular-nums* for quantitative axes." + }, + "fxGrid": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/Interval" + }, + { + "items": {}, + "type": "array" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to show a grid aligned with the scale’s ticks. If true, show a grid with the currentColor stroke; if a string, show a grid with the specified stroke color; if an approximate number of ticks, an interval, or an array of tick values, show corresponding grid lines. See also the grid mark.\n\nFor axes only." + }, + "fxInset": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four insets: **insetTop**,\n**insetRight**, **insetBottom**, and **insetLeft**. All insets typically default to zero, though not always (say when using bin transform). A positive inset reduces effective area, while a negative inset increases it." + }, + "fxInsetLeft": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Insets the left edge by the specified number of pixels. A positive value insets towards the right edge (reducing effective area), while a negative value insets away from the right edge (increasing it)." + }, + "fxInsetRight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Insets the right edge by the specified number of pixels. A positive value insets towards the left edge (reducing effective area), while a negative value insets away from the left edge (increasing it)." + }, + "fxLabel": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A textual label to show on the axis or legend; if null, show no label. By default the scale label is inferred from channel definitions, possibly with an arrow (↑, →, ↓, or ←) to indicate the direction of increasing value.\n\nFor axes and legends only." + }, + "fxLabelAnchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "right", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "const": "left", + "type": "string" + }, + { + "const": "center", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Where to place the axis **label** relative to the plot’s frame. For vertical position scales (*y* and *fy*), may be *top*, *bottom*, or\n*center*; for horizontal position scales (*x* and *fx*), may be *left*,\n*right*, or *center*. Defaults to *center* for ordinal scales (including\n*fx* and *fy*), and otherwise *top* for *y*, and *right* for *x*." + }, + "fxLabelOffset": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The axis **label** position offset (in pixels); default depends on margins and orientation." + }, + "fxLine": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, draw a line along the axis; if false (default), do not." + }, + "fxPadding": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "For *band* scales, how much of the **range** to reserve to separate adjacent bands; defaults to 0.1 (10%). For *point* scales, the amount of inset for the first and last value as a proportion of the bandwidth; defaults to 0.5 (50%).\n\nFor ordinal position scales only." + }, + "fxPaddingInner": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "For a *band* scale, how much of the range to reserve to separate adjacent bands." + }, + "fxPaddingOuter": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "For a *band* scale, how much of the range to reserve to inset first and last bands." + }, + "fxRange": { + "anyOf": [ + { + "items": {}, + "type": "array" + }, + { + "$ref": "#/definitions/Fixed" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The extent of the scale’s outputs (visual values). By default inferred from the scale’s **type** and **domain**, and the plot’s dimensions. For ordinal position scales (*point* and *band*), it is typically [*min*, *max*]; it can be [*max*, *min*] to reverse the scale." + }, + "fxReverse": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to reverse the scale’s encoding; equivalent to reversing either the\n**domain** or **range**." + }, + "fxRound": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, round the output value to the nearest integer (pixel); useful for crisp edges when rendering.\n\nFor position scales only." + }, + "fxTickFormat": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to format inputs (abstract values) for axis tick labels; one of:\n\n- a [d3-format][1] string for numeric scales\n- a [d3-time-format][2] string for temporal scales\n\n[1]: https://d3js.org/d3-time [2]: https://d3js.org/d3-time-format" + }, + "fxTickPadding": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The distance between an axis tick mark and its associated text label (in pixels); often defaults to 3, but may be affected by **fxTickSize** and\n**fxTickRotate**." + }, + "fxTickRotate": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The rotation angle of axis tick labels in degrees clocksize; defaults to 0." + }, + "fxTickSize": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The length of axis tick marks in pixels; negative values extend in the opposite direction. Defaults to 6 for *x* and *y* axes and *color* and\n*opacity* *ramp* legends, and 0 for *fx* and *fy* axes." + }, + "fxTickSpacing": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The desired approximate spacing between adjacent axis ticks, affecting the default **ticks**; defaults to 80 pixels for *x* and *fx*, and 35 pixels for *y* and *fy*." + }, + "fxTicks": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/Interval" + }, + { + "items": {}, + "type": "array" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The desired approximate number of axis ticks, or an explicit array of tick values, or an interval such as *day* or *month*." + }, + "fyAlign": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to distribute unused space in the **range** for *point* and *band* scales. A number in [0, 1], such as:\n\n- 0 - use the start of the range, putting unused space at the end\n- 0.5 (default) - use the middle, distributing unused space evenly\n- 1 use the end, putting unused space at the start\n\nFor ordinal position scales only." + }, + "fyAriaDescription": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A textual description for the axis in the accessibility tree." + }, + "fyAriaLabel": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A short label representing the axis in the accessibility tree." + }, + "fyAxis": { + "anyOf": [ + { + "const": "left", + "type": "string" + }, + { + "const": "right", + "type": "string" + }, + { + "const": "both", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The side of the frame on which to place the implicit axis: *left* or\n*right* for *fy*. Defaults to *left* for an *fy* scale.\n\nIf *both*, an implicit axis will be rendered on both sides of the plot (*left* and *right* for *fy*). If null, the implicit axis is suppressed." + }, + "fyDomain": { + "anyOf": [ + { + "items": {}, + "type": "array" + }, + { + "$ref": "#/definitions/Fixed" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The extent of the scale’s inputs (abstract values). By default inferred from channel values. For ordinal data (strings or booleans), it is an array (or iterable) of values is the desired order, defaulting to natural ascending order." + }, + "fyFontVariant": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The font-variant attribute for axis ticks; defaults to *tabular-nums* for quantitative axes." + }, + "fyGrid": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/Interval" + }, + { + "items": {}, + "type": "array" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to show a grid aligned with the scale’s ticks. If true, show a grid with the currentColor stroke; if a string, show a grid with the specified stroke color; if an approximate number of ticks, an interval, or an array of tick values, show corresponding grid lines. See also the grid mark.\n\nFor axes only." + }, + "fyInset": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four insets: **insetTop**,\n**insetRight**, **insetBottom**, and **insetLeft**. All insets typically default to zero, though not always (say when using bin transform). A positive inset reduces effective area, while a negative inset increases it." + }, + "fyInsetBottom": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Insets the bottom edge by the specified number of pixels. A positive value insets towards the top edge (reducing effective area), while a negative value insets away from the top edge (increasing it)." + }, + "fyInsetTop": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Insets the top edge by the specified number of pixels. A positive value insets towards the bottom edge (reducing effective area), while a negative value insets away from the bottom edge (increasing it)." + }, + "fyLabel": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A textual label to show on the axis or legend; if null, show no label. By default the scale label is inferred from channel definitions, possibly with an arrow (↑, →, ↓, or ←) to indicate the direction of increasing value.\n\nFor axes and legends only." + }, + "fyLabelAnchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "right", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "const": "left", + "type": "string" + }, + { + "const": "center", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Where to place the axis **label** relative to the plot’s frame. For vertical position scales (*y* and *fy*), may be *top*, *bottom*, or\n*center*; for horizontal position scales (*x* and *fx*), may be *left*,\n*right*, or *center*. Defaults to *center* for ordinal scales (including\n*fx* and *fy*), and otherwise *top* for *y*, and *right* for *x*." + }, + "fyLabelOffset": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The axis **label** position offset (in pixels); default depends on margins and orientation." + }, + "fyLine": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, draw a line along the axis; if false (default), do not." + }, + "fyPadding": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "For *band* scales, how much of the **range** to reserve to separate adjacent bands; defaults to 0.1 (10%). For *point* scales, the amount of inset for the first and last value as a proportion of the bandwidth; defaults to 0.5 (50%).\n\nFor ordinal position scales only." + }, + "fyPaddingInner": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "For a *band* scale, how much of the range to reserve to separate adjacent bands." + }, + "fyPaddingOuter": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "For a *band* scale, how much of the range to reserve to inset first and last bands." + }, + "fyRange": { + "anyOf": [ + { + "items": {}, + "type": "array" + }, + { + "$ref": "#/definitions/Fixed" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The extent of the scale’s outputs (visual values). By default inferred from the scale’s **type** and **domain**, and the plot’s dimensions. For ordinal position scales (*point* and *band*), it is typically [*min*, *max*]; it can be [*max*, *min*] to reverse the scale." + }, + "fyReverse": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to reverse the scale’s encoding; equivalent to reversing either the\n**domain** or **range**." + }, + "fyRound": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, round the output value to the nearest integer (pixel); useful for crisp edges when rendering.\n\nFor position scales only." + }, + "fyTickFormat": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to format inputs (abstract values) for axis tick labels; one of:\n\n- a [d3-format][1] string for numeric scales\n- a [d3-time-format][2] string for temporal scales\n\n[1]: https://d3js.org/d3-time [2]: https://d3js.org/d3-time-format" + }, + "fyTickPadding": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The distance between an axis tick mark and its associated text label (in pixels); often defaults to 3, but may be affected by **fyTickSize** and\n**fyTickRotate**." + }, + "fyTickRotate": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The rotation angle of axis tick labels in degrees clocksize; defaults to 0." + }, + "fyTickSize": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The length of axis tick marks in pixels; negative values extend in the opposite direction. Defaults to 6 for *x* and *y* axes and *color* and\n*opacity* *ramp* legends, and 0 for *fx* and *fy* axes." + }, + "fyTickSpacing": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The desired approximate spacing between adjacent axis ticks, affecting the default **ticks**; defaults to 80 pixels for *x* and *fx*, and 35 pixels for *y* and *fy*." + }, + "fyTicks": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/Interval" + }, + { + "items": {}, + "type": "array" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The desired approximate number of axis ticks, or an explicit array of tick values, or an interval such as *day* or *month*." + }, + "grid": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to show a grid aligned with the scale’s ticks. If true, show a grid with the currentColor stroke; if a string, show a grid with the specified stroke color; if an approximate number of ticks, an interval, or an array of tick values, show corresponding grid lines. See also the grid mark.\n\nFor axes only." + }, + "height": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The outer height of the plot in pixels, including margins. The default depends on the plot’s scales, and the plot’s width if an aspectRatio is specified. For example, if the *y* scale is linear and there is no *fy* scale, it might be 396." + }, + "inset": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four insets: **insetTop**,\n**insetRight**, **insetBottom**, and **insetLeft**. All insets typically default to zero, though not always (say when using bin transform). A positive inset reduces effective area, while a negative inset increases it." + }, + "label": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A textual label to show on the axis or legend; if null, show no label. By default the scale label is inferred from channel definitions, possibly with an arrow (↑, →, ↓, or ←) to indicate the direction of increasing value.\n\nFor axes and legends only." + }, + "lengthBase": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A log scale’s base; defaults to 10. Does not affect the scale’s encoding, but rather the default ticks. For *log* scales only." + }, + "lengthClamp": { + "description": "If true, values below the domain minimum are treated as the domain minimum, and values above the domain maximum are treated as the domain maximum.\n\nClamping is useful for focusing on a subset of the data while ensuring that extreme values remain visible, but use caution: clamped values may need an annotation to avoid misinterpretation. Clamping typically requires setting an explicit **domain** since if the domain is inferred, no values will be outside the domain.\n\nFor continuous scales only." + }, + "lengthConstant": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A symlog scale’s constant, expressing the magnitude of the linear region around the origin; defaults to 1. For *symlog* scales only." + }, + "lengthDomain": { + "anyOf": [ + { + "items": {}, + "type": "array" + }, + { + "$ref": "#/definitions/Fixed" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The extent of the scale’s inputs (abstract values). By default inferred from channel values. For continuous data (numbers and dates), it is typically [*min*, *max*]; it can be [*max*, *min*] to reverse the scale. For ordinal data (strings or booleans), it is an array (or iterable) of values is the desired order, defaulting to natural ascending order.\n\nLinear scales have a default domain of [0, 1]. Log scales have a default domain of [1, 10] and cannot include zero. Radius scales have a default domain from 0 to the median first quartile of associated channels. Length have a default domain from 0 to the median median of associated channels. Opacity scales have a default domain from 0 to the maximum value of associated channels." + }, + "lengthExponent": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A power scale’s exponent (*e.g.*, 0.5 for sqrt); defaults to 1 for a linear scale. For *pow* scales only." + }, + "lengthNice": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/Interval" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, or a tick count or interval, extend the domain to nice round values. Defaults to 1, 2 or 5 times a power of 10 for *linear* scales, and nice time intervals for *utc* and *time* scales. Pass an interval such as\n*minute*, *wednesday* or *month* to specify what constitutes a nice interval.\n\nFor continuous scales only." + }, + "lengthPercent": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, shorthand for a transform suitable for percentages, mapping proportions in [0, 1] to [0, 100]." + }, + "lengthRange": { + "anyOf": [ + { + "items": {}, + "type": "array" + }, + { + "$ref": "#/definitions/Fixed" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The extent of the scale’s outputs (visual values). By default inferred from the scale’s **type** and **domain**, and for position scales, the plot’s dimensions. For continuous data (numbers and dates), and for ordinal position scales (*point* and *band*), it is typically [*min*, *max*]; it can be [*max*, *min*] to reverse the scale. For other ordinal data, such as for a *color* scale, it is an array (or iterable) of output values in the same order as the **domain**.\n\nLength scales have a default range of [0, 12]." + }, + "lengthScale": { + "anyOf": [ + { + "$ref": "#/definitions/ContinuousScaleType" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The *length* scale type, affecting how the scale encodes abstract data, say by applying a mathematical transformation. If null, the scale is disabled. The length scale defaults to *linear*, as this scale is intended for quantitative data." + }, + "lengthZero": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether the **domain** must include zero. If the domain minimum is positive, it will be set to zero; otherwise if the domain maximum is negative, it will be set to zero.\n\nFor quantitative scales only." + }, + "margin": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four margins: **marginTop**,\n**marginRight**, **marginBottom**, and **marginLeft**. Otherwise, the default margins depend on the maximum margins of the plot’s marks. While most marks default to zero margins (because they are drawn inside the chart area), Plot’s axis marks have non-zero default margins." + }, + "marginBottom": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The bottom margin; the distance in pixels between the bottom edges of the inner and outer plot area. Defaults to the maximum bottom margin of the plot’s marks." + }, + "marginLeft": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The left margin; the distance in pixels between the left edges of the inner and outer plot area. Defaults to the maximum left margin of the plot’s marks." + }, + "marginRight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The right margin; the distance in pixels between the right edges of the inner and outer plot area. Defaults to the maximum right margin of the plot’s marks." + }, + "marginTop": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The top margin; the distance in pixels between the top edges of the inner and outer plot area. Defaults to the maximum top margin of the plot’s marks." + }, + "margins": { + "additionalProperties": false, + "description": "A shorthand object notation for setting multiple margin values. The object keys are margin names (top, right, etc).", + "properties": { + "bottom": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "left": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "right": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "top": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + } + }, + "type": "object" + }, + "name": { + "description": "A unique name for the plot. The name is used by standalone legend components to to lookup the plot and access scale mappings.", + "type": "string" + }, + "opacityBase": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A log scale’s base; defaults to 10. Does not affect the scale’s encoding, but rather the default ticks. For *log* scales only." + }, + "opacityClamp": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, values below the domain minimum are treated as the domain minimum, and values above the domain maximum are treated as the domain maximum.\n\nClamping is useful for focusing on a subset of the data while ensuring that extreme values remain visible, but use caution: clamped values may need an annotation to avoid misinterpretation. Clamping typically requires setting an explicit **domain** since if the domain is inferred, no values will be outside the domain.\n\nFor continuous scales only." + }, + "opacityConstant": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A symlog scale’s constant, expressing the magnitude of the linear region around the origin; defaults to 1. For *symlog* scales only." + }, + "opacityDomain": { + "anyOf": [ + { + "items": {}, + "type": "array" + }, + { + "$ref": "#/definitions/Fixed" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The extent of the scale’s inputs (abstract values). By default inferred from channel values. For continuous data (numbers and dates), it is typically [*min*, *max*]; it can be [*max*, *min*] to reverse the scale. For ordinal data (strings or booleans), it is an array (or iterable) of values is the desired order, defaulting to natural ascending order.\n\nOpacity scales have a default domain from 0 to the maximum value of associated channels." + }, + "opacityExponent": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A power scale’s exponent (*e.g.*, 0.5 for sqrt); defaults to 1 for a linear scale. For *pow* scales only." + }, + "opacityLabel": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A textual label to show on the axis or legend; if null, show no label. By default the scale label is inferred from channel definitions, possibly with an arrow (↑, →, ↓, or ←) to indicate the direction of increasing value.\n\nFor axes and legends only." + }, + "opacityNice": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/Interval" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, or a tick count or interval, extend the domain to nice round values. Defaults to 1, 2 or 5 times a power of 10 for *linear* scales, and nice time intervals for *utc* and *time* scales. Pass an interval such as\n*minute*, *wednesday* or *month* to specify what constitutes a nice interval.\n\nFor continuous scales only." + }, + "opacityPercent": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, shorthand for a transform suitable for percentages, mapping proportions in [0, 1] to [0, 100]." + }, + "opacityRange": { + "anyOf": [ + { + "items": {}, + "type": "array" + }, + { + "$ref": "#/definitions/Fixed" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The extent of the scale’s outputs (visual values).\n\nOpacity scales have a default range of [0, 1]." + }, + "opacityReverse": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to reverse the scale’s encoding; equivalent to reversing either the\n**domain** or **range**." + }, + "opacityScale": { + "anyOf": [ + { + "$ref": "#/definitions/ContinuousScaleType" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The *opacity* scale type, affecting how the scale encodes abstract data, say by applying a mathematical transformation. If null, the scale is disabled. The opacity scale defaults to *linear*; this scales is intended for quantitative data." + }, + "opacityTickFormat": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to format inputs (abstract values) for axis tick labels; one of:\n\n- a [d3-format][1] string for numeric scales\n- a [d3-time-format][2] string for temporal scales\n\n[1]: https://d3js.org/d3-time [2]: https://d3js.org/d3-time-format" + }, + "opacityZero": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether the **domain** must include zero. If the domain minimum is positive, it will be set to zero; otherwise if the domain maximum is negative, it will be set to zero.\n\nFor quantitative scales only." + }, + "padding": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "For *band* scales, how much of the **range** to reserve to separate adjacent bands; defaults to 0.1 (10%). For *point* scales, the amount of inset for the first and last value as a proportion of the bandwidth; defaults to 0.5 (50%).\n\nFor ordinal position scales only." + }, + "plot": { + "description": "An array of plot marks, interactors, or legends. Marks are graphical elements that make up plot layers. Unless otherwise configured, interactors will use the nearest previous mark as a basis for which data fields to select.", + "items": { + "anyOf": [ + { + "$ref": "#/definitions/PlotMark" + }, + { + "$ref": "#/definitions/PlotInteractor" + }, + { + "$ref": "#/definitions/PlotLegend" + } + ] + }, + "type": "array" + }, + "projectionClip": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "number" + }, + { + "const": "frame", + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The projection’s clipping method; one of:\n\n- *frame* or true (default) - clip to the plot’s frame (including margins but not insets)\n- a number - clip to a circle of the given radius in degrees centered around the origin\n- null or false - do not clip\n\nSome projections (such as [*armadillo*][1] and [*berghaus*][2]) require spherical clipping: in that case set the marks’ **clip** option to\n*sphere*.\n\n[1]: https://observablehq.com/@d3/armadillo [2]: https://observablehq.com/@d3/berghaus-star" + }, + "projectionDomain": { + "anyOf": [ + { + "type": "object" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A GeoJSON object to fit to the plot’s frame (minus insets); defaults to a Sphere for spherical projections (outline of the the whole globe)." + }, + "projectionInset": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four projection insets. All insets typically default to zero, though not always. A positive inset reduces effective area, while a negative inset increases it." + }, + "projectionInsetBottom": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Insets the bottom edge of the projection by the specified number of pixels. A positive value insets towards the top edge (reducing effective area), while a negative value insets away from the top edge (increasing it)." + }, + "projectionInsetLeft": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Insets the left edge of the projection by the specified number of pixels. A positive value insets towards the right edge (reducing effective area), while a negative value insets away from the right edge (increasing it)." + }, + "projectionInsetRight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Insets the right edge of the projection by the specified number of pixels. A positive value insets towards the left edge (reducing effective area), while a negative value insets away from the left edge (increasing it)." + }, + "projectionInsetTop": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Insets the top edge of the projection by the specified number of pixels. A positive value insets towards the bottom edge (reducing effective area), while a negative value insets away from the bottom edge (increasing it)." + }, + "projectionParallels": { + "anyOf": [ + { + "items": [ + { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "title": "y1" + }, + { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "title": "y2" + } + ], + "maxItems": 2, + "minItems": 2, + "type": "array" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [standard parallels][1]. For conic projections only.\n\n[1]: https://d3js.org/d3-geo/conic#conic_parallels" + }, + "projectionPrecision": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The projection’s [sampling threshold][1].\n\n[1]: https://d3js.org/d3-geo/projection#projection_precision" + }, + "projectionRotate": { + "anyOf": [ + { + "items": [ + { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "title": "x" + }, + { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "title": "y" + }, + { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "title": "z" + } + ], + "maxItems": 3, + "minItems": 3, + "type": "array" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A rotation of the sphere before projection; defaults to [0, 0, 0]. Specified as Euler angles λ (yaw, or reference longitude), φ (pitch, or reference latitude), and optionally γ (roll), in degrees." + }, + "projectionType": { + "anyOf": [ + { + "$ref": "#/definitions/ProjectionName" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The desired projection; one of:\n\n- a named built-in projection such as *albers-usa*\n- null, for no projection\n\nNamed projections are scaled and translated to fit the **domain** to the plot’s frame (minus insets)." + }, + "rBase": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A log scale’s base; defaults to 10. Does not affect the scale’s encoding, but rather the default ticks. For *log* scales only." + }, + "rClamp": { + "description": "If true, values below the domain minimum are treated as the domain minimum, and values above the domain maximum are treated as the domain maximum.\n\nClamping is useful for focusing on a subset of the data while ensuring that extreme values remain visible, but use caution: clamped values may need an annotation to avoid misinterpretation. Clamping typically requires setting an explicit **domain** since if the domain is inferred, no values will be outside the domain.\n\nFor continuous scales only." + }, + "rConstant": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A symlog scale’s constant, expressing the magnitude of the linear region around the origin; defaults to 1. For *symlog* scales only." + }, + "rDomain": { + "anyOf": [ + { + "items": {}, + "type": "array" + }, + { + "$ref": "#/definitions/Fixed" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The extent of the scale’s inputs (abstract values). By default inferred from channel values. For continuous data (numbers and dates), it is typically [*min*, *max*]; it can be [*max*, *min*] to reverse the scale. For ordinal data (strings or booleans), it is an array (or iterable) of values is the desired order, defaulting to natural ascending order.\n\nRadius scales have a default domain from 0 to the median first quartile of associated channels." + }, + "rExponent": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A power scale’s exponent (*e.g.*, 0.5 for sqrt); defaults to 1 for a linear scale. For *pow* scales only." + }, + "rLabel": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A textual label to show on the axis or legend; if null, show no label. By default the scale label is inferred from channel definitions, possibly with an arrow (↑, →, ↓, or ←) to indicate the direction of increasing value." + }, + "rNice": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/Interval" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, or a tick count or interval, extend the domain to nice round values. Defaults to 1, 2 or 5 times a power of 10 for *linear* scales, and nice time intervals for *utc* and *time* scales. Pass an interval such as\n*minute*, *wednesday* or *month* to specify what constitutes a nice interval.\n\nFor continuous scales only." + }, + "rPercent": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, shorthand for a transform suitable for percentages, mapping proportions in [0, 1] to [0, 100]." + }, + "rRange": { + "anyOf": [ + { + "items": {}, + "type": "array" + }, + { + "$ref": "#/definitions/Fixed" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The extent of the scale’s outputs (visual values). By default inferred from the scale’s **type** and **domain**, and for position scales, the plot’s dimensions. For continuous data (numbers and dates), and for ordinal position scales (*point* and *band*), it is typically [*min*, *max*]; it can be [*max*, *min*] to reverse the scale. For other ordinal data, such as for a *color* scale, it is an array (or iterable) of output values in the same order as the **domain**.\n\nRadius scales have a default range of [0, 3]." + }, + "rScale": { + "anyOf": [ + { + "$ref": "#/definitions/ContinuousScaleType" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The *r* (radius) scale type, affecting how the scale encodes abstract data, say by applying a mathematical transformation. If null, the scale is disabled. The radius scale defaults to *sqrt*; this scale is intended for quantitative data." + }, + "rZero": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether the **domain** must include zero. If the domain minimum is positive, it will be set to zero; otherwise if the domain maximum is negative, it will be set to zero.\n\nFor quantitative scales only." + }, + "style": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/CSSStyles" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Custom styles to override Plot’s defaults. Styles may be specified either as a string of inline styles (*e.g.*, `\"color: red;\"`, in the same fashion as assigning [*element*.style][1]) or an object of properties (*e.g.*, `{color: \"red\"}`, in the same fashion as assigning [*element*.style properties][2]). Note that unitless numbers ([quirky lengths][3]) such as `{padding: 20}` may not supported by some browsers; you should instead specify a string with units such as `{padding: \"20px\"}`. By default, the returned plot has a max-width of 100%, and the system-ui font. Plot’s marks and axes default to [currentColor][4], meaning that they will inherit the surrounding content’s color.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/style [2]: https://developer.mozilla.org/en-US/docs/Web/API/CSSStyleDeclaration [3]: https://www.w3.org/TR/css-values-4/#deprecated-quirky-length [4]: https://developer.mozilla.org/en-US/docs/Web/CSS/color_value#currentcolor_keyword" + }, + "symbolDomain": { + "anyOf": [ + { + "items": {}, + "type": "array" + }, + { + "$ref": "#/definitions/Fixed" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The extent of the scale’s inputs (abstract values). By default inferred from channel values. As symbol scales are discrete, the domain is an array (or iterable) of values is the desired order, defaulting to natural ascending order." + }, + "symbolRange": { + "anyOf": [ + { + "items": {}, + "type": "array" + }, + { + "$ref": "#/definitions/Fixed" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The extent of the scale’s outputs (visual values). By default inferred from the scale’s **type** and **domain**, and for position scales, the plot’s dimensions. For continuous data (numbers and dates), and for ordinal position scales (*point* and *band*), it is typically [*min*, *max*]; it can be [*max*, *min*] to reverse the scale. For other ordinal data, such as for a *color* scale, it is an array (or iterable) of output values in the same order as the **domain**.\n\nSymbol scales have a default range of categorical symbols; the choice of symbols depends on whether the associated dot mark is filled or stroked." + }, + "symbolScale": { + "anyOf": [ + { + "$ref": "#/definitions/DiscreteScaleType" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The *symbol* scale type, affecting how the scale encodes abstract data, say by applying a mathematical transformation. If null, the scale is disabled. Defaults to an *ordinal* scale type." + }, + "width": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The outer width of the plot in pixels, including margins. Defaults to 640. On Observable, this can be set to the built-in [width][1] for full-width responsive plots. Note: the default style has a max-width of 100%; the plot will automatically shrink to fit even when a fixed width is specified.\n\n[1]: https://github.com/observablehq/stdlib/blob/main/README.md#width" + }, + "xAlign": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to distribute unused space in the **range** for *point* and *band* scales. A number in [0, 1], such as:\n\n- 0 - use the start of the range, putting unused space at the end\n- 0.5 (default) - use the middle, distributing unused space evenly\n- 1 use the end, putting unused space at the start\n\nFor ordinal position scales only." + }, + "xAriaDescription": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A textual description for the axis in the accessibility tree." + }, + "xAriaLabel": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A short label representing the axis in the accessibility tree." + }, + "xAxis": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "const": "both", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The side of the frame on which to place the implicit axis: *top* or\n*bottom* for *x*. Defaults to *bottom* for an *x* scale.\n\nIf *both*, an implicit axis will be rendered on both sides of the plot (*top* and *bottom* for *x*). If null, the implicit axis is suppressed." + }, + "xBase": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A log scale’s base; defaults to 10. Does not affect the scale’s encoding, but rather the default ticks. For *log* scales only." + }, + "xClamp": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, values below the domain minimum are treated as the domain minimum, and values above the domain maximum are treated as the domain maximum.\n\nClamping is useful for focusing on a subset of the data while ensuring that extreme values remain visible, but use caution: clamped values may need an annotation to avoid misinterpretation. Clamping typically requires setting an explicit **domain** since if the domain is inferred, no values will be outside the domain.\n\nFor continuous scales only." + }, + "xConstant": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A symlog scale’s constant, expressing the magnitude of the linear region around the origin; defaults to 1. For *symlog* scales only." + }, + "xDomain": { + "anyOf": [ + { + "items": {}, + "type": "array" + }, + { + "$ref": "#/definitions/Fixed" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The extent of the scale’s inputs (abstract values). By default inferred from channel values. For continuous data (numbers and dates), it is typically [*min*, *max*]; it can be [*max*, *min*] to reverse the scale. For ordinal data (strings or booleans), it is an array (or iterable) of values is the desired order, defaulting to natural ascending order.\n\nLinear scales have a default domain of [0, 1]. Log scales have a default domain of [1, 10] and cannot include zero. Radius scales have a default domain from 0 to the median first quartile of associated channels. Length have a default domain from 0 to the median median of associated channels. Opacity scales have a default domain from 0 to the maximum value of associated channels." + }, + "xExponent": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A power scale’s exponent (*e.g.*, 0.5 for sqrt); defaults to 1 for a linear scale. For *pow* scales only." + }, + "xFontVariant": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The font-variant attribute for axis ticks; defaults to *tabular-nums* for quantitative axes." + }, + "xGrid": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/Interval" + }, + { + "items": {}, + "type": "array" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to show a grid aligned with the scale’s ticks. If true, show a grid with the currentColor stroke; if a string, show a grid with the specified stroke color; if an approximate number of ticks, an interval, or an array of tick values, show corresponding grid lines. See also the grid mark.\n\nFor axes only." + }, + "xInset": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four insets: **insetTop**,\n**insetRight**, **insetBottom**, and **insetLeft**. All insets typically default to zero, though not always (say when using bin transform). A positive inset reduces effective area, while a negative inset increases it." + }, + "xInsetLeft": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Insets the left edge by the specified number of pixels. A positive value insets towards the right edge (reducing effective area), while a negative value insets away from the right edge (increasing it)." + }, + "xInsetRight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Insets the right edge by the specified number of pixels. A positive value insets towards the left edge (reducing effective area), while a negative value insets away from the left edge (increasing it)." + }, + "xLabel": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A textual label to show on the axis or legend; if null, show no label. By default the scale label is inferred from channel definitions, possibly with an arrow (↑, →, ↓, or ←) to indicate the direction of increasing value.\n\nFor axes and legends only." + }, + "xLabelAnchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "right", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "const": "left", + "type": "string" + }, + { + "const": "center", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Where to place the axis **label** relative to the plot’s frame. For vertical position scales (*y* and *fy*), may be *top*, *bottom*, or\n*center*; for horizontal position scales (*x* and *fx*), may be *left*,\n*right*, or *center*. Defaults to *center* for ordinal scales (including\n*fx* and *fy*), and otherwise *top* for *y*, and *right* for *x*." + }, + "xLabelArrow": { + "anyOf": [ + { + "$ref": "#/definitions/LabelArrow" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to apply a directional arrow such as → or ↑ to the x-axis scale label. If *auto* (the default), the presence of the arrow depends on whether the scale is ordinal." + }, + "xLabelOffset": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The axis **label** position offset (in pixels); default depends on margins and orientation." + }, + "xLine": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, draw a line along the axis; if false (default), do not." + }, + "xNice": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/Interval" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, or a tick count or interval, extend the domain to nice round values. Defaults to 1, 2 or 5 times a power of 10 for *linear* scales, and nice time intervals for *utc* and *time* scales. Pass an interval such as\n*minute*, *wednesday* or *month* to specify what constitutes a nice interval.\n\nFor continuous scales only." + }, + "xPadding": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "For *band* scales, how much of the **range** to reserve to separate adjacent bands; defaults to 0.1 (10%). For *point* scales, the amount of inset for the first and last value as a proportion of the bandwidth; defaults to 0.5 (50%).\n\nFor ordinal position scales only." + }, + "xPaddingInner": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "For a *band* scale, how much of the range to reserve to separate adjacent bands." + }, + "xPaddingOuter": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "For a *band* scale, how much of the range to reserve to inset first and last bands." + }, + "xPercent": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, shorthand for a transform suitable for percentages, mapping proportions in [0, 1] to [0, 100]." + }, + "xRange": { + "anyOf": [ + { + "items": {}, + "type": "array" + }, + { + "$ref": "#/definitions/Fixed" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The extent of the scale’s outputs (visual values). By default inferred from the scale’s **type** and **domain**, and for position scales, the plot’s dimensions. For continuous data (numbers and dates), and for ordinal position scales (*point* and *band*), it is typically [*min*, *max*]; it can be [*max*, *min*] to reverse the scale." + }, + "xReverse": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to reverse the scale’s encoding; equivalent to reversing either the\n**domain** or **range**." + }, + "xRound": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, round the output value to the nearest integer (pixel); useful for crisp edges when rendering.\n\nFor position scales only." + }, + "xScale": { + "anyOf": [ + { + "$ref": "#/definitions/PositionScaleType" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The *x* scale type, affecting how the scale encodes abstract data, say by applying a mathematical transformation. If null, the scale is disabled.\n\nFor quantitative data (numbers), defaults to *linear*; for temporal data (dates), defaults to *utc*; for ordinal data (strings or booleans), defaults to *point* for position scales, *categorical* for color scales, and otherwise *ordinal*. However, the radius scale defaults to *sqrt*, and the length and opacity scales default to *linear*; these scales are intended for quantitative data. The plot’s marks may also impose a scale type; for example, the barY mark requires that *x* is a *band* scale." + }, + "xTickFormat": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to format inputs (abstract values) for axis tick labels; one of:\n\n- a [d3-format][1] string for numeric scales\n- a [d3-time-format][2] string for temporal scales\n\n[1]: https://d3js.org/d3-time [2]: https://d3js.org/d3-time-format" + }, + "xTickPadding": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The distance between an axis tick mark and its associated text label (in pixels); often defaults to 3, but may be affected by **xTickSize** and\n**xTickRotate**." + }, + "xTickRotate": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The rotation angle of axis tick labels in degrees clocksize; defaults to 0." + }, + "xTickSize": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The length of axis tick marks in pixels; negative values extend in the opposite direction. Defaults to 6 for *x* and *y* axes and *color* and\n*opacity* *ramp* legends, and 0 for *fx* and *fy* axes." + }, + "xTickSpacing": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The desired approximate spacing between adjacent axis ticks, affecting the default **ticks**; defaults to 80 pixels for *x* and *fx*, and 35 pixels for *y* and *fy*." + }, + "xTicks": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/Interval" + }, + { + "items": {}, + "type": "array" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The desired approximate number of axis ticks, or an explicit array of tick values, or an interval such as *day* or *month*." + }, + "xZero": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether the **domain** must include zero. If the domain minimum is positive, it will be set to zero; otherwise if the domain maximum is negative, it will be set to zero.\n\nFor quantitative scales only." + }, + "xyDomain": { + "anyOf": [ + { + "items": {}, + "type": "array" + }, + { + "$ref": "#/definitions/Fixed" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Set the *x* and *y* scale domains." + }, + "yAlign": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to distribute unused space in the **range** for *point* and *band* scales. A number in [0, 1], such as:\n\n- 0 - use the start of the range, putting unused space at the end\n- 0.5 (default) - use the middle, distributing unused space evenly\n- 1 use the end, putting unused space at the start\n\nFor ordinal position scales only." + }, + "yAriaDescription": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A textual description for the axis in the accessibility tree." + }, + "yAriaLabel": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A short label representing the axis in the accessibility tree." + }, + "yAxis": { + "anyOf": [ + { + "const": "left", + "type": "string" + }, + { + "const": "right", + "type": "string" + }, + { + "const": "both", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The side of the frame on which to place the implicit axis: *left* or\n*right* for *y*. Defaults to *left* for a *y* scale.\n\nIf *both*, an implicit axis will be rendered on both sides of the plot (*left* and *right* for *y*). If null, the implicit axis is suppressed." + }, + "yBase": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A log scale’s base; defaults to 10. Does not affect the scale’s encoding, but rather the default ticks. For *log* scales only." + }, + "yClamp": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, values below the domain minimum are treated as the domain minimum, and values above the domain maximum are treated as the domain maximum.\n\nClamping is useful for focusing on a subset of the data while ensuring that extreme values remain visible, but use caution: clamped values may need an annotation to avoid misinterpretation. Clamping typically requires setting an explicit **domain** since if the domain is inferred, no values will be outside the domain.\n\nFor continuous scales only." + }, + "yConstant": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A symlog scale’s constant, expressing the magnitude of the linear region around the origin; defaults to 1. For *symlog* scales only." + }, + "yDomain": { + "anyOf": [ + { + "items": {}, + "type": "array" + }, + { + "$ref": "#/definitions/Fixed" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The extent of the scale’s inputs (abstract values). By default inferred from channel values. For continuous data (numbers and dates), it is typically [*min*, *max*]; it can be [*max*, *min*] to reverse the scale. For ordinal data (strings or booleans), it is an array (or iterable) of values is the desired order, defaulting to natural ascending order.\n\nLinear scales have a default domain of [0, 1]. Log scales have a default domain of [1, 10] and cannot include zero." + }, + "yExponent": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A power scale’s exponent (*e.g.*, 0.5 for sqrt); defaults to 1 for a linear scale. For *pow* scales only." + }, + "yFontVariant": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The font-variant attribute for axis ticks; defaults to *tabular-nums* for quantitative axes." + }, + "yGrid": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/Interval" + }, + { + "items": {}, + "type": "array" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to show a grid aligned with the scale’s ticks. If true, show a grid with the currentColor stroke; if a string, show a grid with the specified stroke color; if an approximate number of ticks, an interval, or an array of tick values, show corresponding grid lines. See also the grid mark.\n\nFor axes only." + }, + "yInset": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four insets: **insetTop**,\n**insetRight**, **insetBottom**, and **insetLeft**. All insets typically default to zero, though not always (say when using bin transform). A positive inset reduces effective area, while a negative inset increases it." + }, + "yInsetBottom": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Insets the bottom edge by the specified number of pixels. A positive value insets towards the top edge (reducing effective area), while a negative value insets away from the top edge (increasing it)." + }, + "yInsetTop": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Insets the top edge by the specified number of pixels. A positive value insets towards the bottom edge (reducing effective area), while a negative value insets away from the bottom edge (increasing it)." + }, + "yLabel": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A textual label to show on the axis or legend; if null, show no label. By default the scale label is inferred from channel definitions, possibly with an arrow (↑, →, ↓, or ←) to indicate the direction of increasing value.\n\nFor axes and legends only." + }, + "yLabelAnchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "right", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "const": "left", + "type": "string" + }, + { + "const": "center", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Where to place the axis **label** relative to the plot’s frame. For vertical position scales (*y* and *fy*), may be *top*, *bottom*, or\n*center*; for horizontal position scales (*x* and *fx*), may be *left*,\n*right*, or *center*. Defaults to *center* for ordinal scales (including\n*fx* and *fy*), and otherwise *top* for *y*, and *right* for *x*." + }, + "yLabelArrow": { + "anyOf": [ + { + "$ref": "#/definitions/LabelArrow" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to apply a directional arrow such as → or ↑ to the x-axis scale label. If *auto* (the default), the presence of the arrow depends on whether the scale is ordinal." + }, + "yLabelOffset": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The axis **label** position offset (in pixels); default depends on margins and orientation." + }, + "yLine": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, draw a line along the axis; if false (default), do not." + }, + "yNice": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/Interval" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, or a tick count or interval, extend the domain to nice round values. Defaults to 1, 2 or 5 times a power of 10 for *linear* scales, and nice time intervals for *utc* and *time* scales. Pass an interval such as\n*minute*, *wednesday* or *month* to specify what constitutes a nice interval.\n\nFor continuous scales only." + }, + "yPadding": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "For *band* scales, how much of the **range** to reserve to separate adjacent bands; defaults to 0.1 (10%). For *point* scales, the amount of inset for the first and last value as a proportion of the bandwidth; defaults to 0.5 (50%).\n\nFor ordinal position scales only." + }, + "yPaddingInner": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "For a *band* scale, how much of the range to reserve to separate adjacent bands." + }, + "yPaddingOuter": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "For a *band* scale, how much of the range to reserve to inset first and last bands." + }, + "yPercent": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, shorthand for a transform suitable for percentages, mapping proportions in [0, 1] to [0, 100]." + }, + "yRange": { + "anyOf": [ + { + "items": {}, + "type": "array" + }, + { + "$ref": "#/definitions/Fixed" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The extent of the scale’s outputs (visual values). By default inferred from the scale’s **type** and **domain**, and for position scales, the plot’s dimensions. For continuous data (numbers and dates), and for ordinal position scales (*point* and *band*), it is typically [*min*,\n*max*]; it can be [*max*, *min*] to reverse the scale." + }, + "yReverse": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to reverse the scale’s encoding; equivalent to reversing either the\n**domain** or **range**. Note that by default, when the *y* scale is continuous, the *max* value points to the top of the screen, whereas ordinal values are ranked from top to bottom." + }, + "yRound": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, round the output value to the nearest integer (pixel); useful for crisp edges when rendering.\n\nFor position scales only." + }, + "yScale": { + "anyOf": [ + { + "$ref": "#/definitions/PositionScaleType" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The *y* scale type, affecting how the scale encodes abstract data, say by applying a mathematical transformation. If null, the scale is disabled.\n\nFor quantitative data (numbers), defaults to *linear*; for temporal data (dates), defaults to *utc*; for ordinal data (strings or booleans), defaults to *point* for position scales, The plot’s marks may also impose a scale type; for example, the barY mark requires that *x* is a *band* scale." + }, + "yTickFormat": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to format inputs (abstract values) for axis tick labels; one of:\n\n- a [d3-format][1] string for numeric scales\n- a [d3-time-format][2] string for temporal scales\n\n[1]: https://d3js.org/d3-time [2]: https://d3js.org/d3-time-format" + }, + "yTickPadding": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The distance between an axis tick mark and its associated text label (in pixels); often defaults to 3, but may be affected by **yTickSize** and\n**yTickRotate**." + }, + "yTickRotate": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The rotation angle of axis tick labels in degrees clocksize; defaults to 0." + }, + "yTickSize": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The length of axis tick marks in pixels; negative values extend in the opposite direction. Defaults to 6 for *x* and *y* axes and *color* and\n*opacity* *ramp* legends, and 0 for *fx* and *fy* axes." + }, + "yTickSpacing": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The desired approximate spacing between adjacent axis ticks, affecting the default **ticks**; defaults to 80 pixels for *x* and *fx*, and 35 pixels for *y* and *fy*." + }, + "yTicks": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/Interval" + }, + { + "items": {}, + "type": "array" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The desired approximate number of axis ticks, or an explicit array of tick values, or an interval such as *day* or *month*." + }, + "yZero": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether the **domain** must include zero. If the domain minimum is positive, it will be set to zero; otherwise if the domain maximum is negative, it will be set to zero.\n\nFor quantitative scales only." + } + }, + "required": [ + "plot" + ], + "type": "object" + }, + "PlotAttributes": { + "additionalProperties": false, + "description": "Plot attributes.", + "properties": { + "align": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to distribute unused space in the **range** for *point* and *band* scales. A number in [0, 1], such as:\n\n- 0 - use the start of the range, putting unused space at the end\n- 0.5 (default) - use the middle, distributing unused space evenly\n- 1 use the end, putting unused space at the start\n\nFor ordinal position scales only." + }, + "aspectRatio": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The desired aspect ratio of the *x* and *y* scales, affecting the default height. Given an aspect ratio of *dx* / *dy*, and assuming that the *x* and\n*y* scales represent equivalent units (say, degrees Celsius or meters), computes a default height such that *dx* pixels along *x* represents the same variation as *dy* pixels along *y*. Note: when faceting, set the *fx* and *fy* scales’ **round** option to false for an exact aspect ratio." + }, + "axis": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "right", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "const": "left", + "type": "string" + }, + { + "const": "both", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The side of the frame on which to place the implicit axis: *top* or\n*bottom* for *x* or *fx*, or *left* or *right* for *y* or *fy*. The default depends on the scale:\n\n- *x* - *bottom*\n- *y* - *left*\n- *fx* - *top* if there is a *bottom* *x* axis, and otherwise *bottom*\n- *fy* - *right* if there is a *left* *y* axis, and otherwise *right*\n\nIf *both*, an implicit axis will be rendered on both sides of the plot (*top* and *bottom* for *x* or *fx*, or *left* and *right* for *y* or\n*fy*). If null, the implicit axis is suppressed.\n\nFor position axes only." + }, + "colorBase": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A log scale’s base; defaults to 10. Does not affect the scale’s encoding, but rather the default ticks. For *log* and *diverging-log* scales only." + }, + "colorClamp": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, values below the domain minimum are treated as the domain minimum, and values above the domain maximum are treated as the domain maximum.\n\nClamping is useful for focusing on a subset of the data while ensuring that extreme values remain visible, but use caution: clamped values may need an annotation to avoid misinterpretation. Clamping typically requires setting an explicit **domain** since if the domain is inferred, no values will be outside the domain.\n\nFor continuous scales only." + }, + "colorConstant": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A symlog scale’s constant, expressing the magnitude of the linear region around the origin; defaults to 1. For *symlog* and *diverging-symlog* scales only." + }, + "colorDomain": { + "anyOf": [ + { + "items": {}, + "type": "array" + }, + { + "$ref": "#/definitions/Fixed" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The extent of the scale’s inputs (abstract values). By default inferred from channel values. For continuous data (numbers and dates), it is typically [*min*, *max*]; it can be [*max*, *min*] to reverse the scale. For ordinal data (strings or booleans), it is an array (or iterable) of values is the desired order, defaulting to natural ascending order." + }, + "colorExponent": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A power scale’s exponent (*e.g.*, 0.5 for sqrt); defaults to 1 for a linear scale. For *pow* and *diverging-pow* scales only." + }, + "colorInterpolate": { + "anyOf": [ + { + "$ref": "#/definitions/Interpolate" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to interpolate color range values. For quantitative scales only. This attribute can be used to specify a color space for interpolating colors specified in the **colorRange**." + }, + "colorLabel": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A textual label to show on the axis or legend; if null, show no label. By default the scale label is inferred from channel definitions, possibly with an arrow (↑, →, ↓, or ←) to indicate the direction of increasing value.\n\nFor axes and legends only." + }, + "colorN": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "For a *quantile* scale, the number of quantiles (creates *n* - 1 thresholds); for a *quantize* scale, the approximate number of thresholds; defaults to 5." + }, + "colorNice": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/Interval" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, or a tick count or interval, extend the domain to nice round values. Defaults to 1, 2 or 5 times a power of 10 for *linear* scales, and nice time intervals for *utc* and *time* scales. Pass an interval such as\n*minute*, *wednesday* or *month* to specify what constitutes a nice interval.\n\nFor continuous scales only." + }, + "colorPercent": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, shorthand for a transform suitable for percentages, mapping proportions in [0, 1] to [0, 100]." + }, + "colorPivot": { + "anyOf": [ + {}, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "For a diverging color scale, the input value (abstract value) that divides the domain into two parts; defaults to 0 for *diverging* scales, dividing the domain into negative and positive parts; defaults to 1 for\n*diverging-log* scales. By default, diverging scales are symmetric around the pivot; see the **symmetric** option." + }, + "colorRange": { + "anyOf": [ + { + "items": {}, + "type": "array" + }, + { + "$ref": "#/definitions/Fixed" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The extent of the scale’s outputs (visual values). By default inferred from the scale’s **type** and **domain**. For other ordinal data, it is an array (or iterable) of output values in the same order as the **domain**." + }, + "colorReverse": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to reverse the scale’s encoding; equivalent to reversing either the\n**domain** or **range**." + }, + "colorScale": { + "anyOf": [ + { + "$ref": "#/definitions/ColorScaleType" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The *color* scale type, affecting how the scale encodes abstract data, say by applying a mathematical transformation. If null, the scale is disabled.\n\nFor quantitative data (numbers), defaults to *linear*; for temporal data (dates), defaults to *utc*; for ordinal data (strings or booleans), defaults to *point* for position scales, *categorical* for color scales, and otherwise *ordinal*." + }, + "colorScheme": { + "anyOf": [ + { + "$ref": "#/definitions/ColorScheme" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If specified, shorthand for setting the **colorRange** or **colorInterpolate** option of a *color* scale." + }, + "colorSymmetric": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "For a diverging color scale, if true (the default), extend the domain to ensure that the lower part of the domain (below the **pivot**) is commensurate with the upper part of the domain (above the **pivot**).\n\nA symmetric diverging color scale may not use all of its output **range**; this reduces contrast but ensures that deviations both below and above the\n**pivot** are represented proportionally. Otherwise if false, the full output **range** will be used; this increases contrast but values on opposite sides of the **pivot** may not be meaningfully compared." + }, + "colorTickFormat": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to format inputs (abstract values) for axis tick labels; one of:\n\n- a [d3-format][1] string for numeric scales\n- a [d3-time-format][2] string for temporal scales\n\n[1]: https://d3js.org/d3-time [2]: https://d3js.org/d3-time-format" + }, + "colorZero": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether the **domain** must include zero. If the domain minimum is positive, it will be set to zero; otherwise if the domain maximum is negative, it will be set to zero.\n\nFor quantitative scales only." + }, + "facetGrid": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/Interval" + }, + { + "items": {}, + "type": "array" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Default axis grid for fx and fy scales; typically set to true to enable." + }, + "facetLabel": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Default axis label for fx and fy scales; typically set to null to disable." + }, + "facetMargin": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four facet margins: marginTop, marginRight, marginBottom, and marginLeft." + }, + "facetMarginBottom": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The right facet margin; the (minimum) distance in pixels between the right edges of the inner and outer plot area." + }, + "facetMarginLeft": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The bottom facet margin; the (minimum) distance in pixels between the bottom edges of the inner and outer plot area." + }, + "facetMarginRight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The left facet margin; the (minimum) distance in pixels between the left edges of the inner and outer plot area." + }, + "facetMarginTop": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The top facet margin; the (minimum) distance in pixels between the top edges of the inner and outer plot area." + }, + "fxAlign": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to distribute unused space in the **range** for *point* and *band* scales. A number in [0, 1], such as:\n\n- 0 - use the start of the range, putting unused space at the end\n- 0.5 (default) - use the middle, distributing unused space evenly\n- 1 use the end, putting unused space at the start\n\nFor ordinal position scales only." + }, + "fxAriaDescription": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A textual description for the axis in the accessibility tree." + }, + "fxAriaLabel": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A short label representing the axis in the accessibility tree." + }, + "fxAxis": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "const": "both", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The side of the frame on which to place the implicit axis: *top* or\n*bottom* for *fx*. Defaults to *top* if there is a *bottom* *x* axis, and otherwise *bottom*.\n\nIf *both*, an implicit axis will be rendered on both sides of the plot (*top* and *bottom* for *fx*). If null, the implicit axis is suppressed." + }, + "fxDomain": { + "anyOf": [ + { + "items": {}, + "type": "array" + }, + { + "$ref": "#/definitions/Fixed" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The extent of the scale’s inputs (abstract values). By default inferred from channel values. For ordinal data (strings or booleans), it is an array (or iterable) of values is the desired order, defaulting to natural ascending order." + }, + "fxFontVariant": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The font-variant attribute for axis ticks; defaults to *tabular-nums* for quantitative axes." + }, + "fxGrid": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/Interval" + }, + { + "items": {}, + "type": "array" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to show a grid aligned with the scale’s ticks. If true, show a grid with the currentColor stroke; if a string, show a grid with the specified stroke color; if an approximate number of ticks, an interval, or an array of tick values, show corresponding grid lines. See also the grid mark.\n\nFor axes only." + }, + "fxInset": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four insets: **insetTop**,\n**insetRight**, **insetBottom**, and **insetLeft**. All insets typically default to zero, though not always (say when using bin transform). A positive inset reduces effective area, while a negative inset increases it." + }, + "fxInsetLeft": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Insets the left edge by the specified number of pixels. A positive value insets towards the right edge (reducing effective area), while a negative value insets away from the right edge (increasing it)." + }, + "fxInsetRight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Insets the right edge by the specified number of pixels. A positive value insets towards the left edge (reducing effective area), while a negative value insets away from the left edge (increasing it)." + }, + "fxLabel": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A textual label to show on the axis or legend; if null, show no label. By default the scale label is inferred from channel definitions, possibly with an arrow (↑, →, ↓, or ←) to indicate the direction of increasing value.\n\nFor axes and legends only." + }, + "fxLabelAnchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "right", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "const": "left", + "type": "string" + }, + { + "const": "center", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Where to place the axis **label** relative to the plot’s frame. For vertical position scales (*y* and *fy*), may be *top*, *bottom*, or\n*center*; for horizontal position scales (*x* and *fx*), may be *left*,\n*right*, or *center*. Defaults to *center* for ordinal scales (including\n*fx* and *fy*), and otherwise *top* for *y*, and *right* for *x*." + }, + "fxLabelOffset": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The axis **label** position offset (in pixels); default depends on margins and orientation." + }, + "fxLine": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, draw a line along the axis; if false (default), do not." + }, + "fxPadding": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "For *band* scales, how much of the **range** to reserve to separate adjacent bands; defaults to 0.1 (10%). For *point* scales, the amount of inset for the first and last value as a proportion of the bandwidth; defaults to 0.5 (50%).\n\nFor ordinal position scales only." + }, + "fxPaddingInner": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "For a *band* scale, how much of the range to reserve to separate adjacent bands." + }, + "fxPaddingOuter": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "For a *band* scale, how much of the range to reserve to inset first and last bands." + }, + "fxRange": { + "anyOf": [ + { + "items": {}, + "type": "array" + }, + { + "$ref": "#/definitions/Fixed" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The extent of the scale’s outputs (visual values). By default inferred from the scale’s **type** and **domain**, and the plot’s dimensions. For ordinal position scales (*point* and *band*), it is typically [*min*, *max*]; it can be [*max*, *min*] to reverse the scale." + }, + "fxReverse": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to reverse the scale’s encoding; equivalent to reversing either the\n**domain** or **range**." + }, + "fxRound": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, round the output value to the nearest integer (pixel); useful for crisp edges when rendering.\n\nFor position scales only." + }, + "fxTickFormat": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to format inputs (abstract values) for axis tick labels; one of:\n\n- a [d3-format][1] string for numeric scales\n- a [d3-time-format][2] string for temporal scales\n\n[1]: https://d3js.org/d3-time [2]: https://d3js.org/d3-time-format" + }, + "fxTickPadding": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The distance between an axis tick mark and its associated text label (in pixels); often defaults to 3, but may be affected by **fxTickSize** and\n**fxTickRotate**." + }, + "fxTickRotate": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The rotation angle of axis tick labels in degrees clocksize; defaults to 0." + }, + "fxTickSize": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The length of axis tick marks in pixels; negative values extend in the opposite direction. Defaults to 6 for *x* and *y* axes and *color* and\n*opacity* *ramp* legends, and 0 for *fx* and *fy* axes." + }, + "fxTickSpacing": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The desired approximate spacing between adjacent axis ticks, affecting the default **ticks**; defaults to 80 pixels for *x* and *fx*, and 35 pixels for *y* and *fy*." + }, + "fxTicks": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/Interval" + }, + { + "items": {}, + "type": "array" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The desired approximate number of axis ticks, or an explicit array of tick values, or an interval such as *day* or *month*." + }, + "fyAlign": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to distribute unused space in the **range** for *point* and *band* scales. A number in [0, 1], such as:\n\n- 0 - use the start of the range, putting unused space at the end\n- 0.5 (default) - use the middle, distributing unused space evenly\n- 1 use the end, putting unused space at the start\n\nFor ordinal position scales only." + }, + "fyAriaDescription": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A textual description for the axis in the accessibility tree." + }, + "fyAriaLabel": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A short label representing the axis in the accessibility tree." + }, + "fyAxis": { + "anyOf": [ + { + "const": "left", + "type": "string" + }, + { + "const": "right", + "type": "string" + }, + { + "const": "both", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The side of the frame on which to place the implicit axis: *left* or\n*right* for *fy*. Defaults to *left* for an *fy* scale.\n\nIf *both*, an implicit axis will be rendered on both sides of the plot (*left* and *right* for *fy*). If null, the implicit axis is suppressed." + }, + "fyDomain": { + "anyOf": [ + { + "items": {}, + "type": "array" + }, + { + "$ref": "#/definitions/Fixed" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The extent of the scale’s inputs (abstract values). By default inferred from channel values. For ordinal data (strings or booleans), it is an array (or iterable) of values is the desired order, defaulting to natural ascending order." + }, + "fyFontVariant": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The font-variant attribute for axis ticks; defaults to *tabular-nums* for quantitative axes." + }, + "fyGrid": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/Interval" + }, + { + "items": {}, + "type": "array" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to show a grid aligned with the scale’s ticks. If true, show a grid with the currentColor stroke; if a string, show a grid with the specified stroke color; if an approximate number of ticks, an interval, or an array of tick values, show corresponding grid lines. See also the grid mark.\n\nFor axes only." + }, + "fyInset": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four insets: **insetTop**,\n**insetRight**, **insetBottom**, and **insetLeft**. All insets typically default to zero, though not always (say when using bin transform). A positive inset reduces effective area, while a negative inset increases it." + }, + "fyInsetBottom": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Insets the bottom edge by the specified number of pixels. A positive value insets towards the top edge (reducing effective area), while a negative value insets away from the top edge (increasing it)." + }, + "fyInsetTop": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Insets the top edge by the specified number of pixels. A positive value insets towards the bottom edge (reducing effective area), while a negative value insets away from the bottom edge (increasing it)." + }, + "fyLabel": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A textual label to show on the axis or legend; if null, show no label. By default the scale label is inferred from channel definitions, possibly with an arrow (↑, →, ↓, or ←) to indicate the direction of increasing value.\n\nFor axes and legends only." + }, + "fyLabelAnchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "right", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "const": "left", + "type": "string" + }, + { + "const": "center", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Where to place the axis **label** relative to the plot’s frame. For vertical position scales (*y* and *fy*), may be *top*, *bottom*, or\n*center*; for horizontal position scales (*x* and *fx*), may be *left*,\n*right*, or *center*. Defaults to *center* for ordinal scales (including\n*fx* and *fy*), and otherwise *top* for *y*, and *right* for *x*." + }, + "fyLabelOffset": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The axis **label** position offset (in pixels); default depends on margins and orientation." + }, + "fyLine": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, draw a line along the axis; if false (default), do not." + }, + "fyPadding": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "For *band* scales, how much of the **range** to reserve to separate adjacent bands; defaults to 0.1 (10%). For *point* scales, the amount of inset for the first and last value as a proportion of the bandwidth; defaults to 0.5 (50%).\n\nFor ordinal position scales only." + }, + "fyPaddingInner": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "For a *band* scale, how much of the range to reserve to separate adjacent bands." + }, + "fyPaddingOuter": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "For a *band* scale, how much of the range to reserve to inset first and last bands." + }, + "fyRange": { + "anyOf": [ + { + "items": {}, + "type": "array" + }, + { + "$ref": "#/definitions/Fixed" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The extent of the scale’s outputs (visual values). By default inferred from the scale’s **type** and **domain**, and the plot’s dimensions. For ordinal position scales (*point* and *band*), it is typically [*min*, *max*]; it can be [*max*, *min*] to reverse the scale." + }, + "fyReverse": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to reverse the scale’s encoding; equivalent to reversing either the\n**domain** or **range**." + }, + "fyRound": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, round the output value to the nearest integer (pixel); useful for crisp edges when rendering.\n\nFor position scales only." + }, + "fyTickFormat": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to format inputs (abstract values) for axis tick labels; one of:\n\n- a [d3-format][1] string for numeric scales\n- a [d3-time-format][2] string for temporal scales\n\n[1]: https://d3js.org/d3-time [2]: https://d3js.org/d3-time-format" + }, + "fyTickPadding": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The distance between an axis tick mark and its associated text label (in pixels); often defaults to 3, but may be affected by **fyTickSize** and\n**fyTickRotate**." + }, + "fyTickRotate": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The rotation angle of axis tick labels in degrees clocksize; defaults to 0." + }, + "fyTickSize": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The length of axis tick marks in pixels; negative values extend in the opposite direction. Defaults to 6 for *x* and *y* axes and *color* and\n*opacity* *ramp* legends, and 0 for *fx* and *fy* axes." + }, + "fyTickSpacing": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The desired approximate spacing between adjacent axis ticks, affecting the default **ticks**; defaults to 80 pixels for *x* and *fx*, and 35 pixels for *y* and *fy*." + }, + "fyTicks": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/Interval" + }, + { + "items": {}, + "type": "array" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The desired approximate number of axis ticks, or an explicit array of tick values, or an interval such as *day* or *month*." + }, + "grid": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to show a grid aligned with the scale’s ticks. If true, show a grid with the currentColor stroke; if a string, show a grid with the specified stroke color; if an approximate number of ticks, an interval, or an array of tick values, show corresponding grid lines. See also the grid mark.\n\nFor axes only." + }, + "height": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The outer height of the plot in pixels, including margins. The default depends on the plot’s scales, and the plot’s width if an aspectRatio is specified. For example, if the *y* scale is linear and there is no *fy* scale, it might be 396." + }, + "inset": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four insets: **insetTop**,\n**insetRight**, **insetBottom**, and **insetLeft**. All insets typically default to zero, though not always (say when using bin transform). A positive inset reduces effective area, while a negative inset increases it." + }, + "label": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A textual label to show on the axis or legend; if null, show no label. By default the scale label is inferred from channel definitions, possibly with an arrow (↑, →, ↓, or ←) to indicate the direction of increasing value.\n\nFor axes and legends only." + }, + "lengthBase": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A log scale’s base; defaults to 10. Does not affect the scale’s encoding, but rather the default ticks. For *log* scales only." + }, + "lengthClamp": { + "description": "If true, values below the domain minimum are treated as the domain minimum, and values above the domain maximum are treated as the domain maximum.\n\nClamping is useful for focusing on a subset of the data while ensuring that extreme values remain visible, but use caution: clamped values may need an annotation to avoid misinterpretation. Clamping typically requires setting an explicit **domain** since if the domain is inferred, no values will be outside the domain.\n\nFor continuous scales only." + }, + "lengthConstant": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A symlog scale’s constant, expressing the magnitude of the linear region around the origin; defaults to 1. For *symlog* scales only." + }, + "lengthDomain": { + "anyOf": [ + { + "items": {}, + "type": "array" + }, + { + "$ref": "#/definitions/Fixed" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The extent of the scale’s inputs (abstract values). By default inferred from channel values. For continuous data (numbers and dates), it is typically [*min*, *max*]; it can be [*max*, *min*] to reverse the scale. For ordinal data (strings or booleans), it is an array (or iterable) of values is the desired order, defaulting to natural ascending order.\n\nLinear scales have a default domain of [0, 1]. Log scales have a default domain of [1, 10] and cannot include zero. Radius scales have a default domain from 0 to the median first quartile of associated channels. Length have a default domain from 0 to the median median of associated channels. Opacity scales have a default domain from 0 to the maximum value of associated channels." + }, + "lengthExponent": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A power scale’s exponent (*e.g.*, 0.5 for sqrt); defaults to 1 for a linear scale. For *pow* scales only." + }, + "lengthNice": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/Interval" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, or a tick count or interval, extend the domain to nice round values. Defaults to 1, 2 or 5 times a power of 10 for *linear* scales, and nice time intervals for *utc* and *time* scales. Pass an interval such as\n*minute*, *wednesday* or *month* to specify what constitutes a nice interval.\n\nFor continuous scales only." + }, + "lengthPercent": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, shorthand for a transform suitable for percentages, mapping proportions in [0, 1] to [0, 100]." + }, + "lengthRange": { + "anyOf": [ + { + "items": {}, + "type": "array" + }, + { + "$ref": "#/definitions/Fixed" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The extent of the scale’s outputs (visual values). By default inferred from the scale’s **type** and **domain**, and for position scales, the plot’s dimensions. For continuous data (numbers and dates), and for ordinal position scales (*point* and *band*), it is typically [*min*, *max*]; it can be [*max*, *min*] to reverse the scale. For other ordinal data, such as for a *color* scale, it is an array (or iterable) of output values in the same order as the **domain**.\n\nLength scales have a default range of [0, 12]." + }, + "lengthScale": { + "anyOf": [ + { + "$ref": "#/definitions/ContinuousScaleType" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The *length* scale type, affecting how the scale encodes abstract data, say by applying a mathematical transformation. If null, the scale is disabled. The length scale defaults to *linear*, as this scale is intended for quantitative data." + }, + "lengthZero": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether the **domain** must include zero. If the domain minimum is positive, it will be set to zero; otherwise if the domain maximum is negative, it will be set to zero.\n\nFor quantitative scales only." + }, + "margin": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four margins: **marginTop**,\n**marginRight**, **marginBottom**, and **marginLeft**. Otherwise, the default margins depend on the maximum margins of the plot’s marks. While most marks default to zero margins (because they are drawn inside the chart area), Plot’s axis marks have non-zero default margins." + }, + "marginBottom": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The bottom margin; the distance in pixels between the bottom edges of the inner and outer plot area. Defaults to the maximum bottom margin of the plot’s marks." + }, + "marginLeft": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The left margin; the distance in pixels between the left edges of the inner and outer plot area. Defaults to the maximum left margin of the plot’s marks." + }, + "marginRight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The right margin; the distance in pixels between the right edges of the inner and outer plot area. Defaults to the maximum right margin of the plot’s marks." + }, + "marginTop": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The top margin; the distance in pixels between the top edges of the inner and outer plot area. Defaults to the maximum top margin of the plot’s marks." + }, + "margins": { + "additionalProperties": false, + "description": "A shorthand object notation for setting multiple margin values. The object keys are margin names (top, right, etc).", + "properties": { + "bottom": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "left": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "right": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "top": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + } + }, + "type": "object" + }, + "name": { + "description": "A unique name for the plot. The name is used by standalone legend components to to lookup the plot and access scale mappings.", + "type": "string" + }, + "opacityBase": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A log scale’s base; defaults to 10. Does not affect the scale’s encoding, but rather the default ticks. For *log* scales only." + }, + "opacityClamp": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, values below the domain minimum are treated as the domain minimum, and values above the domain maximum are treated as the domain maximum.\n\nClamping is useful for focusing on a subset of the data while ensuring that extreme values remain visible, but use caution: clamped values may need an annotation to avoid misinterpretation. Clamping typically requires setting an explicit **domain** since if the domain is inferred, no values will be outside the domain.\n\nFor continuous scales only." + }, + "opacityConstant": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A symlog scale’s constant, expressing the magnitude of the linear region around the origin; defaults to 1. For *symlog* scales only." + }, + "opacityDomain": { + "anyOf": [ + { + "items": {}, + "type": "array" + }, + { + "$ref": "#/definitions/Fixed" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The extent of the scale’s inputs (abstract values). By default inferred from channel values. For continuous data (numbers and dates), it is typically [*min*, *max*]; it can be [*max*, *min*] to reverse the scale. For ordinal data (strings or booleans), it is an array (or iterable) of values is the desired order, defaulting to natural ascending order.\n\nOpacity scales have a default domain from 0 to the maximum value of associated channels." + }, + "opacityExponent": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A power scale’s exponent (*e.g.*, 0.5 for sqrt); defaults to 1 for a linear scale. For *pow* scales only." + }, + "opacityLabel": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A textual label to show on the axis or legend; if null, show no label. By default the scale label is inferred from channel definitions, possibly with an arrow (↑, →, ↓, or ←) to indicate the direction of increasing value.\n\nFor axes and legends only." + }, + "opacityNice": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/Interval" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, or a tick count or interval, extend the domain to nice round values. Defaults to 1, 2 or 5 times a power of 10 for *linear* scales, and nice time intervals for *utc* and *time* scales. Pass an interval such as\n*minute*, *wednesday* or *month* to specify what constitutes a nice interval.\n\nFor continuous scales only." + }, + "opacityPercent": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, shorthand for a transform suitable for percentages, mapping proportions in [0, 1] to [0, 100]." + }, + "opacityRange": { + "anyOf": [ + { + "items": {}, + "type": "array" + }, + { + "$ref": "#/definitions/Fixed" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The extent of the scale’s outputs (visual values).\n\nOpacity scales have a default range of [0, 1]." + }, + "opacityReverse": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to reverse the scale’s encoding; equivalent to reversing either the\n**domain** or **range**." + }, + "opacityScale": { + "anyOf": [ + { + "$ref": "#/definitions/ContinuousScaleType" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The *opacity* scale type, affecting how the scale encodes abstract data, say by applying a mathematical transformation. If null, the scale is disabled. The opacity scale defaults to *linear*; this scales is intended for quantitative data." + }, + "opacityTickFormat": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to format inputs (abstract values) for axis tick labels; one of:\n\n- a [d3-format][1] string for numeric scales\n- a [d3-time-format][2] string for temporal scales\n\n[1]: https://d3js.org/d3-time [2]: https://d3js.org/d3-time-format" + }, + "opacityZero": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether the **domain** must include zero. If the domain minimum is positive, it will be set to zero; otherwise if the domain maximum is negative, it will be set to zero.\n\nFor quantitative scales only." + }, + "padding": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "For *band* scales, how much of the **range** to reserve to separate adjacent bands; defaults to 0.1 (10%). For *point* scales, the amount of inset for the first and last value as a proportion of the bandwidth; defaults to 0.5 (50%).\n\nFor ordinal position scales only." + }, + "projectionClip": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "number" + }, + { + "const": "frame", + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The projection’s clipping method; one of:\n\n- *frame* or true (default) - clip to the plot’s frame (including margins but not insets)\n- a number - clip to a circle of the given radius in degrees centered around the origin\n- null or false - do not clip\n\nSome projections (such as [*armadillo*][1] and [*berghaus*][2]) require spherical clipping: in that case set the marks’ **clip** option to\n*sphere*.\n\n[1]: https://observablehq.com/@d3/armadillo [2]: https://observablehq.com/@d3/berghaus-star" + }, + "projectionDomain": { + "anyOf": [ + { + "type": "object" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A GeoJSON object to fit to the plot’s frame (minus insets); defaults to a Sphere for spherical projections (outline of the the whole globe)." + }, + "projectionInset": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four projection insets. All insets typically default to zero, though not always. A positive inset reduces effective area, while a negative inset increases it." + }, + "projectionInsetBottom": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Insets the bottom edge of the projection by the specified number of pixels. A positive value insets towards the top edge (reducing effective area), while a negative value insets away from the top edge (increasing it)." + }, + "projectionInsetLeft": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Insets the left edge of the projection by the specified number of pixels. A positive value insets towards the right edge (reducing effective area), while a negative value insets away from the right edge (increasing it)." + }, + "projectionInsetRight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Insets the right edge of the projection by the specified number of pixels. A positive value insets towards the left edge (reducing effective area), while a negative value insets away from the left edge (increasing it)." + }, + "projectionInsetTop": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Insets the top edge of the projection by the specified number of pixels. A positive value insets towards the bottom edge (reducing effective area), while a negative value insets away from the bottom edge (increasing it)." + }, + "projectionParallels": { + "anyOf": [ + { + "items": [ + { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "title": "y1" + }, + { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "title": "y2" + } + ], + "maxItems": 2, + "minItems": 2, + "type": "array" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [standard parallels][1]. For conic projections only.\n\n[1]: https://d3js.org/d3-geo/conic#conic_parallels" + }, + "projectionPrecision": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The projection’s [sampling threshold][1].\n\n[1]: https://d3js.org/d3-geo/projection#projection_precision" + }, + "projectionRotate": { + "anyOf": [ + { + "items": [ + { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "title": "x" + }, + { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "title": "y" + }, + { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "title": "z" + } + ], + "maxItems": 3, + "minItems": 3, + "type": "array" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A rotation of the sphere before projection; defaults to [0, 0, 0]. Specified as Euler angles λ (yaw, or reference longitude), φ (pitch, or reference latitude), and optionally γ (roll), in degrees." + }, + "projectionType": { + "anyOf": [ + { + "$ref": "#/definitions/ProjectionName" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The desired projection; one of:\n\n- a named built-in projection such as *albers-usa*\n- null, for no projection\n\nNamed projections are scaled and translated to fit the **domain** to the plot’s frame (minus insets)." + }, + "rBase": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A log scale’s base; defaults to 10. Does not affect the scale’s encoding, but rather the default ticks. For *log* scales only." + }, + "rClamp": { + "description": "If true, values below the domain minimum are treated as the domain minimum, and values above the domain maximum are treated as the domain maximum.\n\nClamping is useful for focusing on a subset of the data while ensuring that extreme values remain visible, but use caution: clamped values may need an annotation to avoid misinterpretation. Clamping typically requires setting an explicit **domain** since if the domain is inferred, no values will be outside the domain.\n\nFor continuous scales only." + }, + "rConstant": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A symlog scale’s constant, expressing the magnitude of the linear region around the origin; defaults to 1. For *symlog* scales only." + }, + "rDomain": { + "anyOf": [ + { + "items": {}, + "type": "array" + }, + { + "$ref": "#/definitions/Fixed" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The extent of the scale’s inputs (abstract values). By default inferred from channel values. For continuous data (numbers and dates), it is typically [*min*, *max*]; it can be [*max*, *min*] to reverse the scale. For ordinal data (strings or booleans), it is an array (or iterable) of values is the desired order, defaulting to natural ascending order.\n\nRadius scales have a default domain from 0 to the median first quartile of associated channels." + }, + "rExponent": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A power scale’s exponent (*e.g.*, 0.5 for sqrt); defaults to 1 for a linear scale. For *pow* scales only." + }, + "rLabel": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A textual label to show on the axis or legend; if null, show no label. By default the scale label is inferred from channel definitions, possibly with an arrow (↑, →, ↓, or ←) to indicate the direction of increasing value." + }, + "rNice": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/Interval" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, or a tick count or interval, extend the domain to nice round values. Defaults to 1, 2 or 5 times a power of 10 for *linear* scales, and nice time intervals for *utc* and *time* scales. Pass an interval such as\n*minute*, *wednesday* or *month* to specify what constitutes a nice interval.\n\nFor continuous scales only." + }, + "rPercent": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, shorthand for a transform suitable for percentages, mapping proportions in [0, 1] to [0, 100]." + }, + "rRange": { + "anyOf": [ + { + "items": {}, + "type": "array" + }, + { + "$ref": "#/definitions/Fixed" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The extent of the scale’s outputs (visual values). By default inferred from the scale’s **type** and **domain**, and for position scales, the plot’s dimensions. For continuous data (numbers and dates), and for ordinal position scales (*point* and *band*), it is typically [*min*, *max*]; it can be [*max*, *min*] to reverse the scale. For other ordinal data, such as for a *color* scale, it is an array (or iterable) of output values in the same order as the **domain**.\n\nRadius scales have a default range of [0, 3]." + }, + "rScale": { + "anyOf": [ + { + "$ref": "#/definitions/ContinuousScaleType" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The *r* (radius) scale type, affecting how the scale encodes abstract data, say by applying a mathematical transformation. If null, the scale is disabled. The radius scale defaults to *sqrt*; this scale is intended for quantitative data." + }, + "rZero": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether the **domain** must include zero. If the domain minimum is positive, it will be set to zero; otherwise if the domain maximum is negative, it will be set to zero.\n\nFor quantitative scales only." + }, + "style": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/CSSStyles" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Custom styles to override Plot’s defaults. Styles may be specified either as a string of inline styles (*e.g.*, `\"color: red;\"`, in the same fashion as assigning [*element*.style][1]) or an object of properties (*e.g.*, `{color: \"red\"}`, in the same fashion as assigning [*element*.style properties][2]). Note that unitless numbers ([quirky lengths][3]) such as `{padding: 20}` may not supported by some browsers; you should instead specify a string with units such as `{padding: \"20px\"}`. By default, the returned plot has a max-width of 100%, and the system-ui font. Plot’s marks and axes default to [currentColor][4], meaning that they will inherit the surrounding content’s color.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/style [2]: https://developer.mozilla.org/en-US/docs/Web/API/CSSStyleDeclaration [3]: https://www.w3.org/TR/css-values-4/#deprecated-quirky-length [4]: https://developer.mozilla.org/en-US/docs/Web/CSS/color_value#currentcolor_keyword" + }, + "symbolDomain": { + "anyOf": [ + { + "items": {}, + "type": "array" + }, + { + "$ref": "#/definitions/Fixed" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The extent of the scale’s inputs (abstract values). By default inferred from channel values. As symbol scales are discrete, the domain is an array (or iterable) of values is the desired order, defaulting to natural ascending order." + }, + "symbolRange": { + "anyOf": [ + { + "items": {}, + "type": "array" + }, + { + "$ref": "#/definitions/Fixed" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The extent of the scale’s outputs (visual values). By default inferred from the scale’s **type** and **domain**, and for position scales, the plot’s dimensions. For continuous data (numbers and dates), and for ordinal position scales (*point* and *band*), it is typically [*min*, *max*]; it can be [*max*, *min*] to reverse the scale. For other ordinal data, such as for a *color* scale, it is an array (or iterable) of output values in the same order as the **domain**.\n\nSymbol scales have a default range of categorical symbols; the choice of symbols depends on whether the associated dot mark is filled or stroked." + }, + "symbolScale": { + "anyOf": [ + { + "$ref": "#/definitions/DiscreteScaleType" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The *symbol* scale type, affecting how the scale encodes abstract data, say by applying a mathematical transformation. If null, the scale is disabled. Defaults to an *ordinal* scale type." + }, + "width": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The outer width of the plot in pixels, including margins. Defaults to 640. On Observable, this can be set to the built-in [width][1] for full-width responsive plots. Note: the default style has a max-width of 100%; the plot will automatically shrink to fit even when a fixed width is specified.\n\n[1]: https://github.com/observablehq/stdlib/blob/main/README.md#width" + }, + "xAlign": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to distribute unused space in the **range** for *point* and *band* scales. A number in [0, 1], such as:\n\n- 0 - use the start of the range, putting unused space at the end\n- 0.5 (default) - use the middle, distributing unused space evenly\n- 1 use the end, putting unused space at the start\n\nFor ordinal position scales only." + }, + "xAriaDescription": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A textual description for the axis in the accessibility tree." + }, + "xAriaLabel": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A short label representing the axis in the accessibility tree." + }, + "xAxis": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "const": "both", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The side of the frame on which to place the implicit axis: *top* or\n*bottom* for *x*. Defaults to *bottom* for an *x* scale.\n\nIf *both*, an implicit axis will be rendered on both sides of the plot (*top* and *bottom* for *x*). If null, the implicit axis is suppressed." + }, + "xBase": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A log scale’s base; defaults to 10. Does not affect the scale’s encoding, but rather the default ticks. For *log* scales only." + }, + "xClamp": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, values below the domain minimum are treated as the domain minimum, and values above the domain maximum are treated as the domain maximum.\n\nClamping is useful for focusing on a subset of the data while ensuring that extreme values remain visible, but use caution: clamped values may need an annotation to avoid misinterpretation. Clamping typically requires setting an explicit **domain** since if the domain is inferred, no values will be outside the domain.\n\nFor continuous scales only." + }, + "xConstant": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A symlog scale’s constant, expressing the magnitude of the linear region around the origin; defaults to 1. For *symlog* scales only." + }, + "xDomain": { + "anyOf": [ + { + "items": {}, + "type": "array" + }, + { + "$ref": "#/definitions/Fixed" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The extent of the scale’s inputs (abstract values). By default inferred from channel values. For continuous data (numbers and dates), it is typically [*min*, *max*]; it can be [*max*, *min*] to reverse the scale. For ordinal data (strings or booleans), it is an array (or iterable) of values is the desired order, defaulting to natural ascending order.\n\nLinear scales have a default domain of [0, 1]. Log scales have a default domain of [1, 10] and cannot include zero. Radius scales have a default domain from 0 to the median first quartile of associated channels. Length have a default domain from 0 to the median median of associated channels. Opacity scales have a default domain from 0 to the maximum value of associated channels." + }, + "xExponent": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A power scale’s exponent (*e.g.*, 0.5 for sqrt); defaults to 1 for a linear scale. For *pow* scales only." + }, + "xFontVariant": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The font-variant attribute for axis ticks; defaults to *tabular-nums* for quantitative axes." + }, + "xGrid": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/Interval" + }, + { + "items": {}, + "type": "array" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to show a grid aligned with the scale’s ticks. If true, show a grid with the currentColor stroke; if a string, show a grid with the specified stroke color; if an approximate number of ticks, an interval, or an array of tick values, show corresponding grid lines. See also the grid mark.\n\nFor axes only." + }, + "xInset": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four insets: **insetTop**,\n**insetRight**, **insetBottom**, and **insetLeft**. All insets typically default to zero, though not always (say when using bin transform). A positive inset reduces effective area, while a negative inset increases it." + }, + "xInsetLeft": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Insets the left edge by the specified number of pixels. A positive value insets towards the right edge (reducing effective area), while a negative value insets away from the right edge (increasing it)." + }, + "xInsetRight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Insets the right edge by the specified number of pixels. A positive value insets towards the left edge (reducing effective area), while a negative value insets away from the left edge (increasing it)." + }, + "xLabel": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A textual label to show on the axis or legend; if null, show no label. By default the scale label is inferred from channel definitions, possibly with an arrow (↑, →, ↓, or ←) to indicate the direction of increasing value.\n\nFor axes and legends only." + }, + "xLabelAnchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "right", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "const": "left", + "type": "string" + }, + { + "const": "center", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Where to place the axis **label** relative to the plot’s frame. For vertical position scales (*y* and *fy*), may be *top*, *bottom*, or\n*center*; for horizontal position scales (*x* and *fx*), may be *left*,\n*right*, or *center*. Defaults to *center* for ordinal scales (including\n*fx* and *fy*), and otherwise *top* for *y*, and *right* for *x*." + }, + "xLabelArrow": { + "anyOf": [ + { + "$ref": "#/definitions/LabelArrow" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to apply a directional arrow such as → or ↑ to the x-axis scale label. If *auto* (the default), the presence of the arrow depends on whether the scale is ordinal." + }, + "xLabelOffset": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The axis **label** position offset (in pixels); default depends on margins and orientation." + }, + "xLine": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, draw a line along the axis; if false (default), do not." + }, + "xNice": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/Interval" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, or a tick count or interval, extend the domain to nice round values. Defaults to 1, 2 or 5 times a power of 10 for *linear* scales, and nice time intervals for *utc* and *time* scales. Pass an interval such as\n*minute*, *wednesday* or *month* to specify what constitutes a nice interval.\n\nFor continuous scales only." + }, + "xPadding": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "For *band* scales, how much of the **range** to reserve to separate adjacent bands; defaults to 0.1 (10%). For *point* scales, the amount of inset for the first and last value as a proportion of the bandwidth; defaults to 0.5 (50%).\n\nFor ordinal position scales only." + }, + "xPaddingInner": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "For a *band* scale, how much of the range to reserve to separate adjacent bands." + }, + "xPaddingOuter": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "For a *band* scale, how much of the range to reserve to inset first and last bands." + }, + "xPercent": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, shorthand for a transform suitable for percentages, mapping proportions in [0, 1] to [0, 100]." + }, + "xRange": { + "anyOf": [ + { + "items": {}, + "type": "array" + }, + { + "$ref": "#/definitions/Fixed" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The extent of the scale’s outputs (visual values). By default inferred from the scale’s **type** and **domain**, and for position scales, the plot’s dimensions. For continuous data (numbers and dates), and for ordinal position scales (*point* and *band*), it is typically [*min*, *max*]; it can be [*max*, *min*] to reverse the scale." + }, + "xReverse": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to reverse the scale’s encoding; equivalent to reversing either the\n**domain** or **range**." + }, + "xRound": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, round the output value to the nearest integer (pixel); useful for crisp edges when rendering.\n\nFor position scales only." + }, + "xScale": { + "anyOf": [ + { + "$ref": "#/definitions/PositionScaleType" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The *x* scale type, affecting how the scale encodes abstract data, say by applying a mathematical transformation. If null, the scale is disabled.\n\nFor quantitative data (numbers), defaults to *linear*; for temporal data (dates), defaults to *utc*; for ordinal data (strings or booleans), defaults to *point* for position scales, *categorical* for color scales, and otherwise *ordinal*. However, the radius scale defaults to *sqrt*, and the length and opacity scales default to *linear*; these scales are intended for quantitative data. The plot’s marks may also impose a scale type; for example, the barY mark requires that *x* is a *band* scale." + }, + "xTickFormat": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to format inputs (abstract values) for axis tick labels; one of:\n\n- a [d3-format][1] string for numeric scales\n- a [d3-time-format][2] string for temporal scales\n\n[1]: https://d3js.org/d3-time [2]: https://d3js.org/d3-time-format" + }, + "xTickPadding": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The distance between an axis tick mark and its associated text label (in pixels); often defaults to 3, but may be affected by **xTickSize** and\n**xTickRotate**." + }, + "xTickRotate": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The rotation angle of axis tick labels in degrees clocksize; defaults to 0." + }, + "xTickSize": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The length of axis tick marks in pixels; negative values extend in the opposite direction. Defaults to 6 for *x* and *y* axes and *color* and\n*opacity* *ramp* legends, and 0 for *fx* and *fy* axes." + }, + "xTickSpacing": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The desired approximate spacing between adjacent axis ticks, affecting the default **ticks**; defaults to 80 pixels for *x* and *fx*, and 35 pixels for *y* and *fy*." + }, + "xTicks": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/Interval" + }, + { + "items": {}, + "type": "array" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The desired approximate number of axis ticks, or an explicit array of tick values, or an interval such as *day* or *month*." + }, + "xZero": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether the **domain** must include zero. If the domain minimum is positive, it will be set to zero; otherwise if the domain maximum is negative, it will be set to zero.\n\nFor quantitative scales only." + }, + "xyDomain": { + "anyOf": [ + { + "items": {}, + "type": "array" + }, + { + "$ref": "#/definitions/Fixed" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Set the *x* and *y* scale domains." + }, + "yAlign": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to distribute unused space in the **range** for *point* and *band* scales. A number in [0, 1], such as:\n\n- 0 - use the start of the range, putting unused space at the end\n- 0.5 (default) - use the middle, distributing unused space evenly\n- 1 use the end, putting unused space at the start\n\nFor ordinal position scales only." + }, + "yAriaDescription": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A textual description for the axis in the accessibility tree." + }, + "yAriaLabel": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A short label representing the axis in the accessibility tree." + }, + "yAxis": { + "anyOf": [ + { + "const": "left", + "type": "string" + }, + { + "const": "right", + "type": "string" + }, + { + "const": "both", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The side of the frame on which to place the implicit axis: *left* or\n*right* for *y*. Defaults to *left* for a *y* scale.\n\nIf *both*, an implicit axis will be rendered on both sides of the plot (*left* and *right* for *y*). If null, the implicit axis is suppressed." + }, + "yBase": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A log scale’s base; defaults to 10. Does not affect the scale’s encoding, but rather the default ticks. For *log* scales only." + }, + "yClamp": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, values below the domain minimum are treated as the domain minimum, and values above the domain maximum are treated as the domain maximum.\n\nClamping is useful for focusing on a subset of the data while ensuring that extreme values remain visible, but use caution: clamped values may need an annotation to avoid misinterpretation. Clamping typically requires setting an explicit **domain** since if the domain is inferred, no values will be outside the domain.\n\nFor continuous scales only." + }, + "yConstant": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A symlog scale’s constant, expressing the magnitude of the linear region around the origin; defaults to 1. For *symlog* scales only." + }, + "yDomain": { + "anyOf": [ + { + "items": {}, + "type": "array" + }, + { + "$ref": "#/definitions/Fixed" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The extent of the scale’s inputs (abstract values). By default inferred from channel values. For continuous data (numbers and dates), it is typically [*min*, *max*]; it can be [*max*, *min*] to reverse the scale. For ordinal data (strings or booleans), it is an array (or iterable) of values is the desired order, defaulting to natural ascending order.\n\nLinear scales have a default domain of [0, 1]. Log scales have a default domain of [1, 10] and cannot include zero." + }, + "yExponent": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A power scale’s exponent (*e.g.*, 0.5 for sqrt); defaults to 1 for a linear scale. For *pow* scales only." + }, + "yFontVariant": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The font-variant attribute for axis ticks; defaults to *tabular-nums* for quantitative axes." + }, + "yGrid": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/Interval" + }, + { + "items": {}, + "type": "array" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to show a grid aligned with the scale’s ticks. If true, show a grid with the currentColor stroke; if a string, show a grid with the specified stroke color; if an approximate number of ticks, an interval, or an array of tick values, show corresponding grid lines. See also the grid mark.\n\nFor axes only." + }, + "yInset": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four insets: **insetTop**,\n**insetRight**, **insetBottom**, and **insetLeft**. All insets typically default to zero, though not always (say when using bin transform). A positive inset reduces effective area, while a negative inset increases it." + }, + "yInsetBottom": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Insets the bottom edge by the specified number of pixels. A positive value insets towards the top edge (reducing effective area), while a negative value insets away from the top edge (increasing it)." + }, + "yInsetTop": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Insets the top edge by the specified number of pixels. A positive value insets towards the bottom edge (reducing effective area), while a negative value insets away from the bottom edge (increasing it)." + }, + "yLabel": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A textual label to show on the axis or legend; if null, show no label. By default the scale label is inferred from channel definitions, possibly with an arrow (↑, →, ↓, or ←) to indicate the direction of increasing value.\n\nFor axes and legends only." + }, + "yLabelAnchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "right", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "const": "left", + "type": "string" + }, + { + "const": "center", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Where to place the axis **label** relative to the plot’s frame. For vertical position scales (*y* and *fy*), may be *top*, *bottom*, or\n*center*; for horizontal position scales (*x* and *fx*), may be *left*,\n*right*, or *center*. Defaults to *center* for ordinal scales (including\n*fx* and *fy*), and otherwise *top* for *y*, and *right* for *x*." + }, + "yLabelArrow": { + "anyOf": [ + { + "$ref": "#/definitions/LabelArrow" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to apply a directional arrow such as → or ↑ to the x-axis scale label. If *auto* (the default), the presence of the arrow depends on whether the scale is ordinal." + }, + "yLabelOffset": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The axis **label** position offset (in pixels); default depends on margins and orientation." + }, + "yLine": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, draw a line along the axis; if false (default), do not." + }, + "yNice": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/Interval" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, or a tick count or interval, extend the domain to nice round values. Defaults to 1, 2 or 5 times a power of 10 for *linear* scales, and nice time intervals for *utc* and *time* scales. Pass an interval such as\n*minute*, *wednesday* or *month* to specify what constitutes a nice interval.\n\nFor continuous scales only." + }, + "yPadding": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "For *band* scales, how much of the **range** to reserve to separate adjacent bands; defaults to 0.1 (10%). For *point* scales, the amount of inset for the first and last value as a proportion of the bandwidth; defaults to 0.5 (50%).\n\nFor ordinal position scales only." + }, + "yPaddingInner": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "For a *band* scale, how much of the range to reserve to separate adjacent bands." + }, + "yPaddingOuter": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "For a *band* scale, how much of the range to reserve to inset first and last bands." + }, + "yPercent": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, shorthand for a transform suitable for percentages, mapping proportions in [0, 1] to [0, 100]." + }, + "yRange": { + "anyOf": [ + { + "items": {}, + "type": "array" + }, + { + "$ref": "#/definitions/Fixed" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The extent of the scale’s outputs (visual values). By default inferred from the scale’s **type** and **domain**, and for position scales, the plot’s dimensions. For continuous data (numbers and dates), and for ordinal position scales (*point* and *band*), it is typically [*min*,\n*max*]; it can be [*max*, *min*] to reverse the scale." + }, + "yReverse": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to reverse the scale’s encoding; equivalent to reversing either the\n**domain** or **range**. Note that by default, when the *y* scale is continuous, the *max* value points to the top of the screen, whereas ordinal values are ranked from top to bottom." + }, + "yRound": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, round the output value to the nearest integer (pixel); useful for crisp edges when rendering.\n\nFor position scales only." + }, + "yScale": { + "anyOf": [ + { + "$ref": "#/definitions/PositionScaleType" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The *y* scale type, affecting how the scale encodes abstract data, say by applying a mathematical transformation. If null, the scale is disabled.\n\nFor quantitative data (numbers), defaults to *linear*; for temporal data (dates), defaults to *utc*; for ordinal data (strings or booleans), defaults to *point* for position scales, The plot’s marks may also impose a scale type; for example, the barY mark requires that *x* is a *band* scale." + }, + "yTickFormat": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to format inputs (abstract values) for axis tick labels; one of:\n\n- a [d3-format][1] string for numeric scales\n- a [d3-time-format][2] string for temporal scales\n\n[1]: https://d3js.org/d3-time [2]: https://d3js.org/d3-time-format" + }, + "yTickPadding": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The distance between an axis tick mark and its associated text label (in pixels); often defaults to 3, but may be affected by **yTickSize** and\n**yTickRotate**." + }, + "yTickRotate": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The rotation angle of axis tick labels in degrees clocksize; defaults to 0." + }, + "yTickSize": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The length of axis tick marks in pixels; negative values extend in the opposite direction. Defaults to 6 for *x* and *y* axes and *color* and\n*opacity* *ramp* legends, and 0 for *fx* and *fy* axes." + }, + "yTickSpacing": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The desired approximate spacing between adjacent axis ticks, affecting the default **ticks**; defaults to 80 pixels for *x* and *fx*, and 35 pixels for *y* and *fy*." + }, + "yTicks": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/Interval" + }, + { + "items": {}, + "type": "array" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The desired approximate number of axis ticks, or an explicit array of tick values, or an interval such as *day* or *month*." + }, + "yZero": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether the **domain** must include zero. If the domain minimum is positive, it will be set to zero; otherwise if the domain maximum is negative, it will be set to zero.\n\nFor quantitative scales only." + } + }, + "type": "object" + }, + "PlotDataInline": { + "description": "An array of inline data values to visualize. As this data does not come from a database, it can not be filtered by interactive selections.", + "items": {}, + "type": "array" + }, + "PlotFrom": { + "additionalProperties": false, + "description": "Input data specification for a plot mark.", + "properties": { + "filterBy": { + "$ref": "#/definitions/ParamRef", + "description": "A selection that filters the mark data." + }, + "from": { + "description": "The name of the backing data table.", + "type": "string" + }, + "optimize": { + "description": "A flag (default `true`) to enable any mark-specific query optimizations. If `false`, optimizations are disabled to aid testing and debugging.", + "type": "boolean" + } + }, + "required": [ + "from" + ], + "type": "object" + }, + "PlotInteractor": { + "anyOf": [ + { + "$ref": "#/definitions/Highlight" + }, + { + "$ref": "#/definitions/IntervalX" + }, + { + "$ref": "#/definitions/IntervalY" + }, + { + "$ref": "#/definitions/IntervalXY" + }, + { + "$ref": "#/definitions/NearestX" + }, + { + "$ref": "#/definitions/NearestY" + }, + { + "$ref": "#/definitions/Toggle" + }, + { + "$ref": "#/definitions/ToggleX" + }, + { + "$ref": "#/definitions/ToggleY" + }, + { + "$ref": "#/definitions/ToggleColor" + }, + { + "$ref": "#/definitions/Pan" + }, + { + "$ref": "#/definitions/PanX" + }, + { + "$ref": "#/definitions/PanY" + }, + { + "$ref": "#/definitions/PanZoom" + }, + { + "$ref": "#/definitions/PanZoomX" + }, + { + "$ref": "#/definitions/PanZoomY" + } + ], + "description": "A plot interactor entry." + }, + "PlotLegend": { + "additionalProperties": false, + "description": "A legend defined as an entry within a plot.", + "properties": { + "as": { + "$ref": "#/definitions/ParamRef", + "description": "The output selection. If specified, the legend is interactive, using a `toggle` interaction for discrete legends or an `intervalX` interaction for continuous legends." + }, + "columns": { + "description": "The number of columns to use to layout a discrete legend.", + "type": "number" + }, + "field": { + "description": "The data field over which to generate output selection clauses. If unspecified, a matching field is retrieved from existing plot marks.", + "type": "string" + }, + "height": { + "description": "The height of a continuous legend, in pixels.", + "type": "number" + }, + "label": { + "description": "The legend label.", + "type": "string" + }, + "legend": { + "description": "A legend of the given type. The valid types are `\"color\"`, `\"opacity\"`, and `\"symbol\"`.", + "enum": [ + "color", + "opacity", + "symbol" + ], + "type": "string" + }, + "marginBottom": { + "description": "The bottom margin of the legend component, in pixels.", + "type": "number" + }, + "marginLeft": { + "description": "The left margin of the legend component, in pixels.", + "type": "number" + }, + "marginRight": { + "description": "The right margin of the legend component, in pixels.", + "type": "number" + }, + "marginTop": { + "description": "The top margin of the legend component, in pixels.", + "type": "number" + }, + "tickSize": { + "description": "The size of legend ticks in a continuous legend, in pixels.", + "type": "number" + }, + "width": { + "description": "The width of a continuous legend, in pixels.", + "type": "number" + } + }, + "required": [ + "legend" + ], + "type": "object" + }, + "PlotMark": { + "anyOf": [ + { + "$ref": "#/definitions/Area" + }, + { + "$ref": "#/definitions/AreaX" + }, + { + "$ref": "#/definitions/AreaY" + }, + { + "$ref": "#/definitions/Arrow" + }, + { + "$ref": "#/definitions/AxisX" + }, + { + "$ref": "#/definitions/AxisY" + }, + { + "$ref": "#/definitions/AxisFx" + }, + { + "$ref": "#/definitions/AxisFy" + }, + { + "$ref": "#/definitions/GridX" + }, + { + "$ref": "#/definitions/GridY" + }, + { + "$ref": "#/definitions/GridFx" + }, + { + "$ref": "#/definitions/GridFy" + }, + { + "$ref": "#/definitions/BarX" + }, + { + "$ref": "#/definitions/BarY" + }, + { + "$ref": "#/definitions/Cell" + }, + { + "$ref": "#/definitions/CellX" + }, + { + "$ref": "#/definitions/CellY" + }, + { + "$ref": "#/definitions/Contour" + }, + { + "$ref": "#/definitions/DelaunayLink" + }, + { + "$ref": "#/definitions/DelaunayMesh" + }, + { + "$ref": "#/definitions/Hull" + }, + { + "$ref": "#/definitions/Voronoi" + }, + { + "$ref": "#/definitions/VoronoiMesh" + }, + { + "$ref": "#/definitions/DenseLine" + }, + { + "$ref": "#/definitions/Density" + }, + { + "$ref": "#/definitions/DensityX" + }, + { + "$ref": "#/definitions/DensityY" + }, + { + "$ref": "#/definitions/Dot" + }, + { + "$ref": "#/definitions/DotX" + }, + { + "$ref": "#/definitions/DotY" + }, + { + "$ref": "#/definitions/Circle" + }, + { + "$ref": "#/definitions/Hexagon" + }, + { + "$ref": "#/definitions/ErrorBarX" + }, + { + "$ref": "#/definitions/ErrorBarY" + }, + { + "$ref": "#/definitions/Frame" + }, + { + "$ref": "#/definitions/Geo" + }, + { + "$ref": "#/definitions/Graticule" + }, + { + "$ref": "#/definitions/Sphere" + }, + { + "$ref": "#/definitions/Hexbin" + }, + { + "$ref": "#/definitions/Hexgrid" + }, + { + "$ref": "#/definitions/Image" + }, + { + "$ref": "#/definitions/Line" + }, + { + "$ref": "#/definitions/LineX" + }, + { + "$ref": "#/definitions/LineY" + }, + { + "$ref": "#/definitions/Link" + }, + { + "$ref": "#/definitions/Raster" + }, + { + "$ref": "#/definitions/Heatmap" + }, + { + "$ref": "#/definitions/RasterTile" + }, + { + "$ref": "#/definitions/Rect" + }, + { + "$ref": "#/definitions/RectX" + }, + { + "$ref": "#/definitions/RectY" + }, + { + "$ref": "#/definitions/RegressionY" + }, + { + "$ref": "#/definitions/RuleX" + }, + { + "$ref": "#/definitions/RuleY" + }, + { + "$ref": "#/definitions/Text" + }, + { + "$ref": "#/definitions/TextX" + }, + { + "$ref": "#/definitions/TextY" + }, + { + "$ref": "#/definitions/TickX" + }, + { + "$ref": "#/definitions/TickY" + }, + { + "$ref": "#/definitions/Vector" + }, + { + "$ref": "#/definitions/VectorX" + }, + { + "$ref": "#/definitions/VectorY" + }, + { + "$ref": "#/definitions/Spike" + } + ], + "description": "A plot mark entry." + }, + "PlotMarkData": { + "anyOf": [ + { + "$ref": "#/definitions/PlotDataInline" + }, + { + "$ref": "#/definitions/PlotFrom" + } + ], + "description": "Input data for a marks" + }, + "PositionScaleType": { + "description": "The supported scale types for *x* and *y* position encodings.\n\nFor quantitative data, one of:\n\n- *linear* (default) - linear transform (translate and scale)\n- *pow* - power (exponential) transform\n- *sqrt* - square-root transform; *pow* with *exponent* = 0.5\n- *log* - logarithmic transform\n- *symlog* - bi-symmetric logarithmic transform per Webber et al.\n\nFor temporal data, one of:\n\n- *utc* (default, recommended) - UTC time\n- *time* - local time\n\nFor ordinal data, one of:\n\n- *point* (for position only) - divide a continuous range into discrete points\n- *band* (for position only) - divide a continuous range into discrete points\n\nOther scale types:\n\n- *identity* - do not transform values when encoding", + "enum": [ + "linear", + "pow", + "sqrt", + "log", + "symlog", + "utc", + "time", + "point", + "band", + "threshold", + "quantile", + "quantize", + "identity" + ], + "type": "string" + }, + "Product": { + "additionalProperties": false, + "properties": { + "distinct": { + "type": "boolean" + }, + "orderby": { + "anyOf": [ + { + "$ref": "#/definitions/TransformField" + }, + { + "items": { + "$ref": "#/definitions/TransformField" + }, + "type": "array" + } + ] + }, + "partitionby": { + "anyOf": [ + { + "$ref": "#/definitions/TransformField" + }, + { + "items": { + "$ref": "#/definitions/TransformField" + }, + "type": "array" + } + ] + }, + "product": { + "anyOf": [ + { + "description": "A transform argument.", + "type": [ + "string", + "number", + "boolean" + ] + }, + { + "items": { + "description": "A transform argument.", + "type": [ + "string", + "number", + "boolean" + ] + }, + "maxItems": 1, + "minItems": 1, + "type": "array" + } + ], + "description": "Compute the product of the given column." + }, + "range": { + "anyOf": [ + { + "items": { + "type": [ + "number", + "null" + ] + }, + "type": "array" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "rows": { + "anyOf": [ + { + "items": { + "type": [ + "number", + "null" + ] + }, + "type": "array" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + } + }, + "required": [ + "product" + ], + "type": "object" + }, + "ProjectionName": { + "description": "The built-in projection implementations; one of:\n\n- *albers-usa* - a U.S.-centric composite projection with insets for Alaska and Hawaii\n- *albers* - a U.S.-centric *conic-equal-area* projection\n- *azimuthal-equal-area* - the azimuthal equal-area projection\n- *azimuthal-equidistant* - the azimuthal equidistant projection\n- *conic-conformal* - the conic conformal projection\n- *conic-equal-area* - the conic equal-area projection\n- *conic-equidistant* - the conic equidistant projection\n- *equal-earth* - the Equal Earth projection Šavrič et al., 2018\n- *equirectangular* - the equirectangular (plate carrée) projection\n- *gnomonic* - the gnomonic projection\n- *identity* - the identity projection\n- *reflect-y* - the identity projection, but flipping *y*\n- *mercator* - the spherical Mercator projection\n- *orthographic* - the orthographic projection\n- *stereographic* - the stereographic projection\n- *transverse-mercator* - the transverse spherical Mercator projection", + "enum": [ + "albers-usa", + "albers", + "azimuthal-equal-area", + "azimuthal-equidistant", + "conic-conformal", + "conic-equal-area", + "conic-equidistant", + "equal-earth", + "equirectangular", + "gnomonic", + "identity", + "reflect-y", + "mercator", + "orthographic", + "stereographic", + "transverse-mercator" + ], + "type": "string" + }, + "Quantile": { + "additionalProperties": false, + "properties": { + "distinct": { + "type": "boolean" + }, + "orderby": { + "anyOf": [ + { + "$ref": "#/definitions/TransformField" + }, + { + "items": { + "$ref": "#/definitions/TransformField" + }, + "type": "array" + } + ] + }, + "partitionby": { + "anyOf": [ + { + "$ref": "#/definitions/TransformField" + }, + { + "items": { + "$ref": "#/definitions/TransformField" + }, + "type": "array" + } + ] + }, + "quantile": { + "description": "Compute the quantile value of the given column at the provided probability threshold. For example, 0.5 is the median.", + "items": { + "description": "A transform argument.", + "type": [ + "string", + "number", + "boolean" + ] + }, + "maxItems": 2, + "minItems": 2, + "type": "array" + }, + "range": { + "anyOf": [ + { + "items": { + "type": [ + "number", + "null" + ] + }, + "type": "array" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "rows": { + "anyOf": [ + { + "items": { + "type": [ + "number", + "null" + ] + }, + "type": "array" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + } + }, + "required": [ + "quantile" + ], + "type": "object" + }, + "Rank": { + "additionalProperties": false, + "properties": { + "orderby": { + "anyOf": [ + { + "$ref": "#/definitions/TransformField" + }, + { + "items": { + "$ref": "#/definitions/TransformField" + }, + "type": "array" + } + ] + }, + "partitionby": { + "anyOf": [ + { + "$ref": "#/definitions/TransformField" + }, + { + "items": { + "$ref": "#/definitions/TransformField" + }, + "type": "array" + } + ] + }, + "range": { + "anyOf": [ + { + "items": { + "type": [ + "number", + "null" + ] + }, + "type": "array" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "rank": { + "anyOf": [ + { + "type": "null" + }, + { + "maxItems": 0, + "minItems": 0, + "type": "array" + } + ], + "description": "Compute the row rank over an ordered window partition. Sorting ties result in gaps in the rank numbers ([1, 1, 3, ...])." + }, + "rows": { + "anyOf": [ + { + "items": { + "type": [ + "number", + "null" + ] + }, + "type": "array" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + } + }, + "required": [ + "rank" + ], + "type": "object" + }, + "Raster": { + "additionalProperties": false, + "description": "The raster mark.", + "properties": { + "ariaDescription": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-description][1]; a constant textual description.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-description" + }, + "ariaHidden": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-hidden][1] state; a constant indicating whether the element is exposed to an accessibility API.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-hidden" + }, + "ariaLabel": { + "$ref": "#/definitions/ChannelValue", + "description": "The [aria-label][1]; a channel specifying short textual labels representing the value in the accessibility tree.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-label" + }, + "bandwidth": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The kernel density bandwidth for smoothing, in pixels." + }, + "clip": { + "anyOf": [ + { + "const": "frame", + "type": "string" + }, + { + "const": "sphere", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to clip the mark; one of:\n\n- *frame* or true - clip to the plot’s frame (inner area)\n- *sphere* - clip to the projected sphere (*e.g.*, front hemisphere)\n- null or false - do not clip\n\nThe *sphere* clip option requires a geographic projection." + }, + "data": { + "$ref": "#/definitions/PlotMarkData", + "description": "The data source for the mark." + }, + "dx": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The horizontal offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "dy": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The vertical offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "facet": { + "anyOf": [ + { + "const": "auto", + "type": "string" + }, + { + "const": "include", + "type": "string" + }, + { + "const": "exclude", + "type": "string" + }, + { + "const": "super", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to enable or disable faceting; one of:\n\n- *auto* (default) - automatically determine if this mark should be faceted\n- *include* (or true) - draw the subset of the mark’s data in the current facet\n- *exclude* - draw the subset of the mark’s data *not* in the current facet\n- *super* - draw this mark in a single frame that covers all facets\n- null (or false) - repeat this mark’s data across all facets (*i.e.*, no faceting)\n\nWhen a mark uses *super* faceting, it is not allowed to use position scales (*x*, *y*, *fx*, or *fy*); *super* faceting is intended for decorations, such as labels and legends.\n\nWhen top-level faceting is used, the default *auto* setting is equivalent to *include* when the mark data is strictly equal to the top-level facet data; otherwise it is equivalent to null. When the *include* or *exclude* facet mode is chosen, the mark data must be parallel to the top-level facet data: the data must have the same length and order. If the data are not parallel, then the wrong data may be shown in each facet. The default\n*auto* therefore requires strict equality (`===`) for safety, and using the facet data as mark data is recommended when using the *exclude* facet mode. (To construct parallel data safely, consider using [*array*.map][1] on the facet data.)\n\nWhen mark-level faceting is used, the default *auto* setting is equivalent to *include*: the mark will be faceted if either the **fx** or **fy** channel option (or both) is specified. The null or false option will disable faceting, while *exclude* draws the subset of the mark’s data *not* in the current facet.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map" + }, + "facetAnchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "right", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "const": "left", + "type": "string" + }, + { + "const": "top-left", + "type": "string" + }, + { + "const": "top-right", + "type": "string" + }, + { + "const": "bottom-left", + "type": "string" + }, + { + "const": "bottom-right", + "type": "string" + }, + { + "const": "top-empty", + "type": "string" + }, + { + "const": "right-empty", + "type": "string" + }, + { + "const": "bottom-empty", + "type": "string" + }, + { + "const": "left-empty", + "type": "string" + }, + { + "const": "empty", + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to place the mark with respect to facets; one of:\n\n- null (default for most marks) - display the mark in each non-empty facet\n- *top*, *right*, *bottom*, or *left* - display the mark only in facets on the given side\n- *top-empty*, *right-empty*, *bottom-empty*, or *left-empty* (default for axis marks) - display the mark only in facets that have empty space on the given side: either the margin, or an empty facet\n- *empty* - display the mark in empty facets only" + }, + "fill": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The fill, typically bound to the *color* scale. Can be specified as a constant or a channel based on the input data. Use the special value `\"density\"` to map computed density values to pixel colors. Use an aggregate expression to instead visualize an aggregate value per raster bin. If fill is set to a constant color or to a non-aggregate field, opacity will be used to convey densities. If a non-aggregate (group by) field is provided, multiple rasters are created with a unique categorical color per layer." + }, + "fillOpacity": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The opacity, typically bound to the *opacity* scale. Can be specified as a constant or a channel based on the input data. Use the special value `\"density\"` to map computed density values to opacity. Use an aggregate expression to instead visualize an aggregate value per raster bin." + }, + "filter": { + "$ref": "#/definitions/ChannelValue", + "description": "Applies a transform to filter the mark’s index according to the given channel values; only truthy values are retained.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "fx": { + "$ref": "#/definitions/ChannelValue", + "description": "The horizontal facet position channel, for mark-level faceting, bound to the *fx* scale." + }, + "fy": { + "$ref": "#/definitions/ChannelValue", + "description": "The vertical facet position channel, for mark-level faceting, bound to the\n*fy* scale." + }, + "height": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The height (number of rows) of the grid, in actual pixels." + }, + "href": { + "$ref": "#/definitions/ChannelValue", + "description": "The [href][1]; a channel specifying URLs for clickable links. May be used in conjunction with the **target** option to open links in another window.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/href" + }, + "imageFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A CSS [filter][1]; a constant string used to adjust the rendering of images, such as *blur(5px)*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/filter" + }, + "imageRendering": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [image-rendering attribute][1]; defaults to *auto* (bilinear). The option may be set to *pixelated* to disable bilinear interpolation for a sharper image; however, note that this is not supported in WebKit.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/image-rendering" + }, + "interpolate": { + "anyOf": [ + { + "$ref": "#/definitions/GridInterpolate" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The spatial interpolation method; one of:\n\n- *none* - do not perform interpolation (the default), maps samples to single bins\n- *linear* - apply proportional linear interpolation across adjacent bins\n- *nearest* - assign each pixel to the closest sample’s value (Voronoi diagram)\n- *barycentric* - apply barycentric interpolation over the Delaunay triangulation\n- *random-walk* - apply a random walk from each pixel, stopping when near a sample" + }, + "margin": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four mark margins: **marginTop**,\n**marginRight**, **marginBottom**, and **marginLeft**; typically defaults to 0, except for axis marks." + }, + "marginBottom": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s bottom margin; the minimum distance in pixels between the bottom edges of the inner and outer plot area." + }, + "marginLeft": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s left margin; the minimum distance in pixels between the left edges of the inner and outer plot area." + }, + "marginRight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s right margin; the minimum distance in pixels between the right edges of the mark’s inner and outer plot area." + }, + "marginTop": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s top margin; the minimum distance in pixels between the top edges of the inner and outer plot area." + }, + "mark": { + "const": "raster", + "description": "A raster mark which renders a raster image from spatial samples. It represents discrete samples in abstract coordinates **x** and **y**; the **fill** and **fillOpacity** channels specify further abstract values (_e.g._, height in a topographic map) to be spatially interpolated to produce an image.\n\nThe **x** and **y** data domains are binned into the cells (\"pixels\") of a raster grid, typically with an aggregate function evaluated over the binned data. The result can be optionally smoothed (blurred).\n\nTo create a smoothed density heatmap, use the heatmap mark, which is a raster mark with different default options.", + "type": "string" + }, + "mixBlendMode": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [mix-blend-mode][1]; a constant string specifying how to blend content such as *multiply*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode" + }, + "opacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally. For faster rendering, prefer the **strokeOpacity** or **fillOpacity** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/opacity" + }, + "pad": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The bin padding, one of 1 (default) to include extra padding for the final bin, or 0 to make the bins flush with the maximum domain value." + }, + "paintOrder": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [paint-order][1]; a constant string specifying the order in which the\n**fill**, **stroke**, and any markers are drawn; defaults to *normal*, which draws the fill, then stroke, then markers; defaults to *stroke* for the text mark to create a “halo” around text to improve legibility.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/paint-order" + }, + "pixelSize": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The effective screen size of a raster pixel, used to determine the height and width of the raster from the frame’s dimensions; defaults to 1." + }, + "pointerEvents": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [pointer-events][1] property; a constant string such as *none*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/pointer-events" + }, + "reverse": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Applies a transform to reverse the order of the mark’s index, say for reverse input order." + }, + "select": { + "$ref": "#/definitions/SelectFilter", + "description": "Applies a filter transform after data is loaded to highlight selected values only. For example, `first` and `last` select the first or last values of series only (using the *z* channel to separate series). Meanwhile, `nearestX` and `nearestY` select the point nearest to the pointer along the *x* or *y* channel dimension. Unlike Mosaic selections, a mark level *select* is internal to the mark only, and does not populate a param or selection value to be shared across clients.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "shapeRendering": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [shape-rendering][1]; a constant string such as *crispEdges*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/shape-rendering" + }, + "sort": { + "anyOf": [ + { + "$ref": "#/definitions/SortOrder" + }, + { + "$ref": "#/definitions/ChannelDomainSort" + } + ], + "description": "Either applies a transform to sort the mark’s index by the specified channel values, or imputes ordinal scale domains from this mark’s channels.\n\nWhen imputing ordinal scale domains from channel values, the **sort** option is an object whose keys are ordinal scale names such as *x* or *fx*, and whose values are channel names such as *y*, *y1*, or *y2*. For example, to impute the *y* scale’s domain from the associated *x* channel values in ascending order:\n\n```js sort: {y: \"x\"} ```\n\nFor different sort options for different scales, replace the channel name with a *value* object and per-scale options:\n\n```js sort: {y: {value: \"-x\"}} ```\n\nWhen sorting the mark’s index, the **sort** option is instead one of:\n\n- a channel value definition for sorting given values in ascending order\n- a {value, order} object for sorting given values\n- a {channel, order} object for sorting the named channel’s values" + }, + "stroke": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke" + }, + "strokeDasharray": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dasharray][1]; a constant number indicating the length in pixels of alternating dashes and gaps, or a constant string of numbers separated by spaces or commas (_e.g._, *10 2* for dashes of 10 pixels separated by gaps of 2 pixels), or *none* (the default) for no dashing\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dasharray" + }, + "strokeDashoffset": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dashoffset][1]; a constant indicating the offset in pixels of the first dash along the stroke; defaults to zero.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dashoffset" + }, + "strokeLinecap": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linecap][1]; a constant specifying how to cap stroked paths, such as *butt*, *round*, or *square*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linecap" + }, + "strokeLinejoin": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linejoin][1]; a constant specifying how to join stroked paths, such as *bevel*, *miter*, *miter-clip*, or *round*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linejoin" + }, + "strokeMiterlimit": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-miterlimit][1]; a constant number specifying how to limit the length of *miter* joins on stroked paths.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-miterlimit" + }, + "strokeOpacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-opacity" + }, + "strokeWidth": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-width][1]; a constant number in pixels, or a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-width" + }, + "target": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [target][1]; a constant string specifying the target window (_e.g._,\n*_blank*) for clickable links; used in conjunction with the **href** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/target" + }, + "tip": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/TipPointer" + }, + { + "properties": { + "anchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The tip anchor specifies how to orient the tip box relative to its anchor position; it refers to the part of the tip box that is attached to the anchor point. For example, the *top-left* anchor places the top-left corner of tip box near the anchor position, hence placing the tip box below and to the right of the anchor position." + }, + "fontFamily": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font-family][1]; a constant; defaults to the plot’s font family, which is typically [*system-ui*][2].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-family [2]: https://drafts.csswg.org/css-fonts-4/#valdef-font-family-system-ui" + }, + "fontSize": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font size][1] in pixels; either a constant or a channel; defaults to the plot’s font size, which is typically 10. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-size" + }, + "fontStyle": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font style][1]; a constant; defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-style" + }, + "fontVariant": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font variant][1]; a constant; if the **text** channel contains numbers or dates, defaults to *tabular-nums* to facilitate comparing numbers; otherwise defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant" + }, + "fontWeight": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font weight][1]; a constant; defaults to the plot’s font weight, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight" + }, + "format": { + "additionalProperties": false, + "description": "How channel values are formatted for display. If a format is a string, it is interpreted as a (UTC) time format for temporal channels, and otherwise a number format.", + "properties": { + "ariaLabel": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fill": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fillOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fontSize": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fx": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fy": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "geometry": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "height": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "href": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "length": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "opacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "path": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "r": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "rotate": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "src": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "stroke": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeWidth": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "symbol": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "text": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "title": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "weight": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "width": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "z": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + } + }, + "type": "object" + }, + "frameAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The frame anchor specifies defaults for **x** and **y** based on the plot’s frame; it may be one of the four sides (*top*, *right*, *bottom*, *left*), one of the four corners (*top-left*, *top-right*, *bottom-right*,\n*bottom-left*), or the *middle* of the frame. For example, for tips distributed horizontally at the top of the frame:\n\n```js Plot.tip(data, {x: \"date\", frameAnchor: \"top\"}) ```" + }, + "lineHeight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line height in ems; defaults to 1. The line height affects the (typically vertical) separation between adjacent baselines of text, as well as the separation between the text and its anchor point." + }, + "lineWidth": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line width in ems (e.g., 10 for about 20 characters); defaults to infinity, disabling wrapping and clipping.\n\nIf **textOverflow** is null, lines will be wrapped at the specified length. If a line is split at a soft hyphen (\\xad), a hyphen (-) will be displayed at the end of the line. If **textOverflow** is not null, lines will be clipped according to the given strategy." + }, + "monospace": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, changes the default **fontFamily** to *monospace*, and uses simplified monospaced text metrics calculations." + }, + "pathFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The image filter for the tip’s box; defaults to a drop shadow." + }, + "pointer": { + "$ref": "#/definitions/TipPointer" + }, + "pointerSize": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The size of the tip’s pointer in pixels; defaults to 12." + }, + "preferredAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If an explicit tip anchor is not specified, an anchor is chosen automatically such that the tip fits within the plot’s frame; if the preferred anchor fits, it is chosen." + }, + "textAnchor": { + "anyOf": [ + { + "const": "start", + "type": "string" + }, + { + "const": "middle", + "type": "string" + }, + { + "const": "end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [text anchor][1] controls how text is aligned (typically horizontally) relative to its anchor point; it is one of *start*, *end*, or *middle*. If the frame anchor is *left*, *top-left*, or *bottom-left*, the default text anchor is *start*; if the frame anchor is *right*, *top-right*, or\n*bottom-right*, the default is *end*; otherwise it is *middle*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/text-anchor" + }, + "textOverflow": { + "anyOf": [ + { + "type": "null" + }, + { + "const": "clip", + "type": "string" + }, + { + "const": "ellipsis", + "type": "string" + }, + { + "const": "clip-start", + "type": "string" + }, + { + "const": "clip-end", + "type": "string" + }, + { + "const": "ellipsis-start", + "type": "string" + }, + { + "const": "ellipsis-middle", + "type": "string" + }, + { + "const": "ellipsis-end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How truncate (or wrap) lines of text longer than the given **lineWidth**; one of:\n\n- null (default) - preserve overflowing characters (and wrap if needed)\n- *clip* or *clip-end* - remove characters from the end\n- *clip-start* - remove characters from the start\n- *ellipsis* or *ellipsis-end* - replace characters from the end with an ellipsis (…)\n- *ellipsis-start* - replace characters from the start with an ellipsis (…)\n- *ellipsis-middle* - replace characters from the middle with an ellipsis (…)\n\nIf no **title** was specified, if text requires truncation, a title containing the non-truncated text will be implicitly added." + }, + "textPadding": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The padding around the text in pixels; defaults to 8." + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + } + }, + "type": "object" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to generate a tooltip for this mark, and any tip options." + }, + "title": { + "$ref": "#/definitions/ChannelValue", + "description": "The title; a channel specifying accessible, short textual descriptions as strings (possibly with newlines). If the tip option is specified, the title will be displayed with an interactive tooltip instead of using the SVG [title element][1].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/title" + }, + "width": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The width (number of columns) of the grid, in actual pixels." + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel, typically bound to the *x* scale. Domain values are binned into a grid with *width* horizontal bins." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel, typically bound to the *y* scale. Domain values are binned into a grid with *height* vertical bins." + } + }, + "required": [ + "data", + "mark" + ], + "type": "object" + }, + "RasterTile": { + "additionalProperties": false, + "description": "The rasterTile mark.", + "properties": { + "ariaDescription": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-description][1]; a constant textual description.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-description" + }, + "ariaHidden": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-hidden][1] state; a constant indicating whether the element is exposed to an accessibility API.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-hidden" + }, + "ariaLabel": { + "$ref": "#/definitions/ChannelValue", + "description": "The [aria-label][1]; a channel specifying short textual labels representing the value in the accessibility tree.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-label" + }, + "bandwidth": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The kernel density bandwidth for smoothing, in pixels." + }, + "clip": { + "anyOf": [ + { + "const": "frame", + "type": "string" + }, + { + "const": "sphere", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to clip the mark; one of:\n\n- *frame* or true - clip to the plot’s frame (inner area)\n- *sphere* - clip to the projected sphere (*e.g.*, front hemisphere)\n- null or false - do not clip\n\nThe *sphere* clip option requires a geographic projection." + }, + "data": { + "$ref": "#/definitions/PlotMarkData", + "description": "The data source for the mark." + }, + "dx": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The horizontal offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "dy": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The vertical offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "facet": { + "anyOf": [ + { + "const": "auto", + "type": "string" + }, + { + "const": "include", + "type": "string" + }, + { + "const": "exclude", + "type": "string" + }, + { + "const": "super", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to enable or disable faceting; one of:\n\n- *auto* (default) - automatically determine if this mark should be faceted\n- *include* (or true) - draw the subset of the mark’s data in the current facet\n- *exclude* - draw the subset of the mark’s data *not* in the current facet\n- *super* - draw this mark in a single frame that covers all facets\n- null (or false) - repeat this mark’s data across all facets (*i.e.*, no faceting)\n\nWhen a mark uses *super* faceting, it is not allowed to use position scales (*x*, *y*, *fx*, or *fy*); *super* faceting is intended for decorations, such as labels and legends.\n\nWhen top-level faceting is used, the default *auto* setting is equivalent to *include* when the mark data is strictly equal to the top-level facet data; otherwise it is equivalent to null. When the *include* or *exclude* facet mode is chosen, the mark data must be parallel to the top-level facet data: the data must have the same length and order. If the data are not parallel, then the wrong data may be shown in each facet. The default\n*auto* therefore requires strict equality (`===`) for safety, and using the facet data as mark data is recommended when using the *exclude* facet mode. (To construct parallel data safely, consider using [*array*.map][1] on the facet data.)\n\nWhen mark-level faceting is used, the default *auto* setting is equivalent to *include*: the mark will be faceted if either the **fx** or **fy** channel option (or both) is specified. The null or false option will disable faceting, while *exclude* draws the subset of the mark’s data *not* in the current facet.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map" + }, + "facetAnchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "right", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "const": "left", + "type": "string" + }, + { + "const": "top-left", + "type": "string" + }, + { + "const": "top-right", + "type": "string" + }, + { + "const": "bottom-left", + "type": "string" + }, + { + "const": "bottom-right", + "type": "string" + }, + { + "const": "top-empty", + "type": "string" + }, + { + "const": "right-empty", + "type": "string" + }, + { + "const": "bottom-empty", + "type": "string" + }, + { + "const": "left-empty", + "type": "string" + }, + { + "const": "empty", + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to place the mark with respect to facets; one of:\n\n- null (default for most marks) - display the mark in each non-empty facet\n- *top*, *right*, *bottom*, or *left* - display the mark only in facets on the given side\n- *top-empty*, *right-empty*, *bottom-empty*, or *left-empty* (default for axis marks) - display the mark only in facets that have empty space on the given side: either the margin, or an empty facet\n- *empty* - display the mark in empty facets only" + }, + "fill": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The fill, typically bound to the *color* scale. Can be specified as a constant or a channel based on the input data. Use the special value `\"density\"` to map computed density values to pixel colors. Use an aggregate expression to instead visualize an aggregate value per raster bin. If fill is set to a constant color or to a non-aggregate field, opacity will be used to convey densities. If a non-aggregate (group by) field is provided, multiple rasters are created with a unique categorical color per layer." + }, + "fillOpacity": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The opacity, typically bound to the *opacity* scale. Can be specified as a constant or a channel based on the input data. Use the special value `\"density\"` to map computed density values to opacity. Use an aggregate expression to instead visualize an aggregate value per raster bin." + }, + "filter": { + "$ref": "#/definitions/ChannelValue", + "description": "Applies a transform to filter the mark’s index according to the given channel values; only truthy values are retained.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "fx": { + "$ref": "#/definitions/ChannelValue", + "description": "The horizontal facet position channel, for mark-level faceting, bound to the *fx* scale." + }, + "fy": { + "$ref": "#/definitions/ChannelValue", + "description": "The vertical facet position channel, for mark-level faceting, bound to the\n*fy* scale." + }, + "height": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The height (number of rows) of the grid, in actual pixels." + }, + "href": { + "$ref": "#/definitions/ChannelValue", + "description": "The [href][1]; a channel specifying URLs for clickable links. May be used in conjunction with the **target** option to open links in another window.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/href" + }, + "imageFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A CSS [filter][1]; a constant string used to adjust the rendering of images, such as *blur(5px)*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/filter" + }, + "imageRendering": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [image-rendering attribute][1]; defaults to *auto* (bilinear). The option may be set to *pixelated* to disable bilinear interpolation for a sharper image; however, note that this is not supported in WebKit.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/image-rendering" + }, + "interpolate": { + "anyOf": [ + { + "$ref": "#/definitions/GridInterpolate" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The spatial interpolation method; one of:\n\n- *none* - do not perform interpolation (the default), maps samples to single bins\n- *linear* - apply proportional linear interpolation across adjacent bins\n- *nearest* - assign each pixel to the closest sample’s value (Voronoi diagram)\n- *barycentric* - apply barycentric interpolation over the Delaunay triangulation\n- *random-walk* - apply a random walk from each pixel, stopping when near a sample" + }, + "margin": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four mark margins: **marginTop**,\n**marginRight**, **marginBottom**, and **marginLeft**; typically defaults to 0, except for axis marks." + }, + "marginBottom": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s bottom margin; the minimum distance in pixels between the bottom edges of the inner and outer plot area." + }, + "marginLeft": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s left margin; the minimum distance in pixels between the left edges of the inner and outer plot area." + }, + "marginRight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s right margin; the minimum distance in pixels between the right edges of the mark’s inner and outer plot area." + }, + "marginTop": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s top margin; the minimum distance in pixels between the top edges of the inner and outer plot area." + }, + "mark": { + "const": "rasterTile", + "description": "An experimental raster mark which performs tiling and prefetching to support more scalable rasters upon panning the domain. Uses a tile size that matches with current width and height, and prefetches data from neighboring tile segments.", + "type": "string" + }, + "mixBlendMode": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [mix-blend-mode][1]; a constant string specifying how to blend content such as *multiply*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode" + }, + "opacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally. For faster rendering, prefer the **strokeOpacity** or **fillOpacity** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/opacity" + }, + "origin": { + "anyOf": [ + { + "items": { + "type": "number" + }, + "maxItems": 2, + "minItems": 2, + "type": "array" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The coordinates of the tile origin in the **x** and **y** data domains. Defaults to [0, 0]." + }, + "pad": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The bin padding, one of 1 (default) to include extra padding for the final bin, or 0 to make the bins flush with the maximum domain value." + }, + "paintOrder": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [paint-order][1]; a constant string specifying the order in which the\n**fill**, **stroke**, and any markers are drawn; defaults to *normal*, which draws the fill, then stroke, then markers; defaults to *stroke* for the text mark to create a “halo” around text to improve legibility.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/paint-order" + }, + "pixelSize": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The effective screen size of a raster pixel, used to determine the height and width of the raster from the frame’s dimensions; defaults to 1." + }, + "pointerEvents": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [pointer-events][1] property; a constant string such as *none*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/pointer-events" + }, + "reverse": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Applies a transform to reverse the order of the mark’s index, say for reverse input order." + }, + "select": { + "$ref": "#/definitions/SelectFilter", + "description": "Applies a filter transform after data is loaded to highlight selected values only. For example, `first` and `last` select the first or last values of series only (using the *z* channel to separate series). Meanwhile, `nearestX` and `nearestY` select the point nearest to the pointer along the *x* or *y* channel dimension. Unlike Mosaic selections, a mark level *select* is internal to the mark only, and does not populate a param or selection value to be shared across clients.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "shapeRendering": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [shape-rendering][1]; a constant string such as *crispEdges*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/shape-rendering" + }, + "sort": { + "anyOf": [ + { + "$ref": "#/definitions/SortOrder" + }, + { + "$ref": "#/definitions/ChannelDomainSort" + } + ], + "description": "Either applies a transform to sort the mark’s index by the specified channel values, or imputes ordinal scale domains from this mark’s channels.\n\nWhen imputing ordinal scale domains from channel values, the **sort** option is an object whose keys are ordinal scale names such as *x* or *fx*, and whose values are channel names such as *y*, *y1*, or *y2*. For example, to impute the *y* scale’s domain from the associated *x* channel values in ascending order:\n\n```js sort: {y: \"x\"} ```\n\nFor different sort options for different scales, replace the channel name with a *value* object and per-scale options:\n\n```js sort: {y: {value: \"-x\"}} ```\n\nWhen sorting the mark’s index, the **sort** option is instead one of:\n\n- a channel value definition for sorting given values in ascending order\n- a {value, order} object for sorting given values\n- a {channel, order} object for sorting the named channel’s values" + }, + "stroke": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke" + }, + "strokeDasharray": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dasharray][1]; a constant number indicating the length in pixels of alternating dashes and gaps, or a constant string of numbers separated by spaces or commas (_e.g._, *10 2* for dashes of 10 pixels separated by gaps of 2 pixels), or *none* (the default) for no dashing\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dasharray" + }, + "strokeDashoffset": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dashoffset][1]; a constant indicating the offset in pixels of the first dash along the stroke; defaults to zero.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dashoffset" + }, + "strokeLinecap": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linecap][1]; a constant specifying how to cap stroked paths, such as *butt*, *round*, or *square*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linecap" + }, + "strokeLinejoin": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linejoin][1]; a constant specifying how to join stroked paths, such as *bevel*, *miter*, *miter-clip*, or *round*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linejoin" + }, + "strokeMiterlimit": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-miterlimit][1]; a constant number specifying how to limit the length of *miter* joins on stroked paths.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-miterlimit" + }, + "strokeOpacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-opacity" + }, + "strokeWidth": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-width][1]; a constant number in pixels, or a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-width" + }, + "target": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [target][1]; a constant string specifying the target window (_e.g._,\n*_blank*) for clickable links; used in conjunction with the **href** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/target" + }, + "tip": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/TipPointer" + }, + { + "properties": { + "anchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The tip anchor specifies how to orient the tip box relative to its anchor position; it refers to the part of the tip box that is attached to the anchor point. For example, the *top-left* anchor places the top-left corner of tip box near the anchor position, hence placing the tip box below and to the right of the anchor position." + }, + "fontFamily": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font-family][1]; a constant; defaults to the plot’s font family, which is typically [*system-ui*][2].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-family [2]: https://drafts.csswg.org/css-fonts-4/#valdef-font-family-system-ui" + }, + "fontSize": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font size][1] in pixels; either a constant or a channel; defaults to the plot’s font size, which is typically 10. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-size" + }, + "fontStyle": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font style][1]; a constant; defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-style" + }, + "fontVariant": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font variant][1]; a constant; if the **text** channel contains numbers or dates, defaults to *tabular-nums* to facilitate comparing numbers; otherwise defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant" + }, + "fontWeight": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font weight][1]; a constant; defaults to the plot’s font weight, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight" + }, + "format": { + "additionalProperties": false, + "description": "How channel values are formatted for display. If a format is a string, it is interpreted as a (UTC) time format for temporal channels, and otherwise a number format.", + "properties": { + "ariaLabel": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fill": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fillOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fontSize": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fx": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fy": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "geometry": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "height": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "href": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "length": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "opacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "path": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "r": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "rotate": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "src": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "stroke": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeWidth": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "symbol": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "text": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "title": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "weight": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "width": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "z": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + } + }, + "type": "object" + }, + "frameAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The frame anchor specifies defaults for **x** and **y** based on the plot’s frame; it may be one of the four sides (*top*, *right*, *bottom*, *left*), one of the four corners (*top-left*, *top-right*, *bottom-right*,\n*bottom-left*), or the *middle* of the frame. For example, for tips distributed horizontally at the top of the frame:\n\n```js Plot.tip(data, {x: \"date\", frameAnchor: \"top\"}) ```" + }, + "lineHeight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line height in ems; defaults to 1. The line height affects the (typically vertical) separation between adjacent baselines of text, as well as the separation between the text and its anchor point." + }, + "lineWidth": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line width in ems (e.g., 10 for about 20 characters); defaults to infinity, disabling wrapping and clipping.\n\nIf **textOverflow** is null, lines will be wrapped at the specified length. If a line is split at a soft hyphen (\\xad), a hyphen (-) will be displayed at the end of the line. If **textOverflow** is not null, lines will be clipped according to the given strategy." + }, + "monospace": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, changes the default **fontFamily** to *monospace*, and uses simplified monospaced text metrics calculations." + }, + "pathFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The image filter for the tip’s box; defaults to a drop shadow." + }, + "pointer": { + "$ref": "#/definitions/TipPointer" + }, + "pointerSize": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The size of the tip’s pointer in pixels; defaults to 12." + }, + "preferredAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If an explicit tip anchor is not specified, an anchor is chosen automatically such that the tip fits within the plot’s frame; if the preferred anchor fits, it is chosen." + }, + "textAnchor": { + "anyOf": [ + { + "const": "start", + "type": "string" + }, + { + "const": "middle", + "type": "string" + }, + { + "const": "end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [text anchor][1] controls how text is aligned (typically horizontally) relative to its anchor point; it is one of *start*, *end*, or *middle*. If the frame anchor is *left*, *top-left*, or *bottom-left*, the default text anchor is *start*; if the frame anchor is *right*, *top-right*, or\n*bottom-right*, the default is *end*; otherwise it is *middle*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/text-anchor" + }, + "textOverflow": { + "anyOf": [ + { + "type": "null" + }, + { + "const": "clip", + "type": "string" + }, + { + "const": "ellipsis", + "type": "string" + }, + { + "const": "clip-start", + "type": "string" + }, + { + "const": "clip-end", + "type": "string" + }, + { + "const": "ellipsis-start", + "type": "string" + }, + { + "const": "ellipsis-middle", + "type": "string" + }, + { + "const": "ellipsis-end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How truncate (or wrap) lines of text longer than the given **lineWidth**; one of:\n\n- null (default) - preserve overflowing characters (and wrap if needed)\n- *clip* or *clip-end* - remove characters from the end\n- *clip-start* - remove characters from the start\n- *ellipsis* or *ellipsis-end* - replace characters from the end with an ellipsis (…)\n- *ellipsis-start* - replace characters from the start with an ellipsis (…)\n- *ellipsis-middle* - replace characters from the middle with an ellipsis (…)\n\nIf no **title** was specified, if text requires truncation, a title containing the non-truncated text will be implicitly added." + }, + "textPadding": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The padding around the text in pixels; defaults to 8." + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + } + }, + "type": "object" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to generate a tooltip for this mark, and any tip options." + }, + "title": { + "$ref": "#/definitions/ChannelValue", + "description": "The title; a channel specifying accessible, short textual descriptions as strings (possibly with newlines). If the tip option is specified, the title will be displayed with an interactive tooltip instead of using the SVG [title element][1].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/title" + }, + "width": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The width (number of columns) of the grid, in actual pixels." + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel, typically bound to the *x* scale. Domain values are binned into a grid with *width* horizontal bins." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel, typically bound to the *y* scale. Domain values are binned into a grid with *height* vertical bins." + } + }, + "required": [ + "data", + "mark" + ], + "type": "object" + }, + "Rect": { + "additionalProperties": false, + "description": "The rect mark.", + "properties": { + "ariaDescription": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-description][1]; a constant textual description.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-description" + }, + "ariaHidden": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-hidden][1] state; a constant indicating whether the element is exposed to an accessibility API.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-hidden" + }, + "ariaLabel": { + "$ref": "#/definitions/ChannelValue", + "description": "The [aria-label][1]; a channel specifying short textual labels representing the value in the accessibility tree.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-label" + }, + "clip": { + "anyOf": [ + { + "const": "frame", + "type": "string" + }, + { + "const": "sphere", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to clip the mark; one of:\n\n- *frame* or true - clip to the plot’s frame (inner area)\n- *sphere* - clip to the projected sphere (*e.g.*, front hemisphere)\n- null or false - do not clip\n\nThe *sphere* clip option requires a geographic projection." + }, + "data": { + "$ref": "#/definitions/PlotMarkData", + "description": "The data source for the mark." + }, + "dx": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The horizontal offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "dy": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The vertical offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "facet": { + "anyOf": [ + { + "const": "auto", + "type": "string" + }, + { + "const": "include", + "type": "string" + }, + { + "const": "exclude", + "type": "string" + }, + { + "const": "super", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to enable or disable faceting; one of:\n\n- *auto* (default) - automatically determine if this mark should be faceted\n- *include* (or true) - draw the subset of the mark’s data in the current facet\n- *exclude* - draw the subset of the mark’s data *not* in the current facet\n- *super* - draw this mark in a single frame that covers all facets\n- null (or false) - repeat this mark’s data across all facets (*i.e.*, no faceting)\n\nWhen a mark uses *super* faceting, it is not allowed to use position scales (*x*, *y*, *fx*, or *fy*); *super* faceting is intended for decorations, such as labels and legends.\n\nWhen top-level faceting is used, the default *auto* setting is equivalent to *include* when the mark data is strictly equal to the top-level facet data; otherwise it is equivalent to null. When the *include* or *exclude* facet mode is chosen, the mark data must be parallel to the top-level facet data: the data must have the same length and order. If the data are not parallel, then the wrong data may be shown in each facet. The default\n*auto* therefore requires strict equality (`===`) for safety, and using the facet data as mark data is recommended when using the *exclude* facet mode. (To construct parallel data safely, consider using [*array*.map][1] on the facet data.)\n\nWhen mark-level faceting is used, the default *auto* setting is equivalent to *include*: the mark will be faceted if either the **fx** or **fy** channel option (or both) is specified. The null or false option will disable faceting, while *exclude* draws the subset of the mark’s data *not* in the current facet.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map" + }, + "facetAnchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "right", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "const": "left", + "type": "string" + }, + { + "const": "top-left", + "type": "string" + }, + { + "const": "top-right", + "type": "string" + }, + { + "const": "bottom-left", + "type": "string" + }, + { + "const": "bottom-right", + "type": "string" + }, + { + "const": "top-empty", + "type": "string" + }, + { + "const": "right-empty", + "type": "string" + }, + { + "const": "bottom-empty", + "type": "string" + }, + { + "const": "left-empty", + "type": "string" + }, + { + "const": "empty", + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to place the mark with respect to facets; one of:\n\n- null (default for most marks) - display the mark in each non-empty facet\n- *top*, *right*, *bottom*, or *left* - display the mark only in facets on the given side\n- *top-empty*, *right-empty*, *bottom-empty*, or *left-empty* (default for axis marks) - display the mark only in facets that have empty space on the given side: either the margin, or an empty facet\n- *empty* - display the mark in empty facets only" + }, + "fill": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill" + }, + "fillOpacity": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill-opacity][1]; a constant number between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill-opacity" + }, + "filter": { + "$ref": "#/definitions/ChannelValue", + "description": "Applies a transform to filter the mark’s index according to the given channel values; only truthy values are retained.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "fx": { + "$ref": "#/definitions/ChannelValue", + "description": "The horizontal facet position channel, for mark-level faceting, bound to the *fx* scale." + }, + "fy": { + "$ref": "#/definitions/ChannelValue", + "description": "The vertical facet position channel, for mark-level faceting, bound to the\n*fy* scale." + }, + "href": { + "$ref": "#/definitions/ChannelValue", + "description": "The [href][1]; a channel specifying URLs for clickable links. May be used in conjunction with the **target** option to open links in another window.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/href" + }, + "imageFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A CSS [filter][1]; a constant string used to adjust the rendering of images, such as *blur(5px)*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/filter" + }, + "inset": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four insets: **insetTop**,\n**insetRight**, **insetBottom**, and **insetLeft**. All insets typically default to zero, though not always (say when using bin transform). A positive inset reduces effective area, while a negative inset increases it." + }, + "insetBottom": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Insets the bottom edge by the specified number of pixels. A positive value insets towards the top edge (reducing effective area), while a negative value insets away from the top edge (increasing it)." + }, + "insetLeft": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Insets the left edge by the specified number of pixels. A positive value insets towards the right edge (reducing effective area), while a negative value insets away from the right edge (increasing it)." + }, + "insetRight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Insets the right edge by the specified number of pixels. A positive value insets towards the left edge (reducing effective area), while a negative value insets away from the left edge (increasing it)." + }, + "insetTop": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Insets the top edge by the specified number of pixels. A positive value insets towards the bottom edge (reducing effective area), while a negative value insets away from the bottom edge (increasing it)." + }, + "interval": { + "anyOf": [ + { + "$ref": "#/definitions/Interval" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to convert a continuous value (**x** for rectY, **y** for rectX, or both for rect) into an interval (**x1** and **x2** for rectY, or **y1** and\n**y2** for rectX, or both for rect); one of:\n\n- a named time interval such as *day* (for date intervals)\n- a number (for number intervals), defining intervals at integer multiples of *n*\n\nSetting this option disables the implicit stack transform (stackX for rectX, or stackY for rectY)." + }, + "margin": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four mark margins: **marginTop**,\n**marginRight**, **marginBottom**, and **marginLeft**; typically defaults to 0, except for axis marks." + }, + "marginBottom": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s bottom margin; the minimum distance in pixels between the bottom edges of the inner and outer plot area." + }, + "marginLeft": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s left margin; the minimum distance in pixels between the left edges of the inner and outer plot area." + }, + "marginRight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s right margin; the minimum distance in pixels between the right edges of the mark’s inner and outer plot area." + }, + "marginTop": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s top margin; the minimum distance in pixels between the top edges of the inner and outer plot area." + }, + "mark": { + "const": "rect", + "description": "A rect mark. The rectangle extends horizontally from **x1** to **x2**, and vertically from **y1** to **y2**. The position channels are often derived with a transform.\n\nWhen **y** extends from zero, for example for a histogram where the height of each rect reflects a count of values, use the rectY mark for an implicit stackY transform; similarly, if **x** extends from zero, use the rectX mark for an implicit stackX transform.\n\nIf an **interval** is specified, then **x1** and **x2** are derived from\n**x**, and **y1** and **y2** are derived from **y**, each representing the lower and upper bound of the containing interval, respectively.\n\nBoth *x* and *y* should be quantitative or temporal; otherwise, use a bar or cell mark.", + "type": "string" + }, + "mixBlendMode": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [mix-blend-mode][1]; a constant string specifying how to blend content such as *multiply*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode" + }, + "offset": { + "anyOf": [ + { + "$ref": "#/definitions/StackOffset" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "After stacking, an optional **offset** can be applied to translate and scale stacks, say to produce a streamgraph; defaults to null for a zero baseline (**y** = 0 for stackY, and **x** = 0 for stackX). If the *wiggle* offset is used, the default **order** changes to *inside-out*." + }, + "opacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally. For faster rendering, prefer the **strokeOpacity** or **fillOpacity** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/opacity" + }, + "order": { + "anyOf": [ + { + "$ref": "#/definitions/StackOrder" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The order in which stacks are layered; one of:\n\n- null (default) for input order\n- a named stack order method such as *inside-out* or *sum*\n- a field name, for natural order of the corresponding values\n- a function of data, for natural order of the corresponding values\n- an array of explicit **z** values in the desired order\n\nIf the *wiggle* **offset** is used, as for a streamgraph, the default changes to *inside-out*." + }, + "paintOrder": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [paint-order][1]; a constant string specifying the order in which the\n**fill**, **stroke**, and any markers are drawn; defaults to *normal*, which draws the fill, then stroke, then markers; defaults to *stroke* for the text mark to create a “halo” around text to improve legibility.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/paint-order" + }, + "pointerEvents": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [pointer-events][1] property; a constant string such as *none*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/pointer-events" + }, + "reverse": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Applies a transform to reverse the order of the mark’s index, say for reverse input order." + }, + "rx": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The rounded corner [*x*-radius][1], either in pixels or as a percentage of the rect width. If **rx** is not specified, it defaults to **ry** if present, and otherwise draws square corners.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/rx" + }, + "ry": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The rounded corner [*y*-radius][1], either in pixels or as a percentage of the rect height. If **ry** is not specified, it defaults to **rx** if present, and otherwise draws square corners.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/ry" + }, + "select": { + "$ref": "#/definitions/SelectFilter", + "description": "Applies a filter transform after data is loaded to highlight selected values only. For example, `first` and `last` select the first or last values of series only (using the *z* channel to separate series). Meanwhile, `nearestX` and `nearestY` select the point nearest to the pointer along the *x* or *y* channel dimension. Unlike Mosaic selections, a mark level *select* is internal to the mark only, and does not populate a param or selection value to be shared across clients.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "shapeRendering": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [shape-rendering][1]; a constant string such as *crispEdges*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/shape-rendering" + }, + "sort": { + "anyOf": [ + { + "$ref": "#/definitions/SortOrder" + }, + { + "$ref": "#/definitions/ChannelDomainSort" + } + ], + "description": "Either applies a transform to sort the mark’s index by the specified channel values, or imputes ordinal scale domains from this mark’s channels.\n\nWhen imputing ordinal scale domains from channel values, the **sort** option is an object whose keys are ordinal scale names such as *x* or *fx*, and whose values are channel names such as *y*, *y1*, or *y2*. For example, to impute the *y* scale’s domain from the associated *x* channel values in ascending order:\n\n```js sort: {y: \"x\"} ```\n\nFor different sort options for different scales, replace the channel name with a *value* object and per-scale options:\n\n```js sort: {y: {value: \"-x\"}} ```\n\nWhen sorting the mark’s index, the **sort** option is instead one of:\n\n- a channel value definition for sorting given values in ascending order\n- a {value, order} object for sorting given values\n- a {channel, order} object for sorting the named channel’s values" + }, + "stroke": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke" + }, + "strokeDasharray": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dasharray][1]; a constant number indicating the length in pixels of alternating dashes and gaps, or a constant string of numbers separated by spaces or commas (_e.g._, *10 2* for dashes of 10 pixels separated by gaps of 2 pixels), or *none* (the default) for no dashing\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dasharray" + }, + "strokeDashoffset": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dashoffset][1]; a constant indicating the offset in pixels of the first dash along the stroke; defaults to zero.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dashoffset" + }, + "strokeLinecap": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linecap][1]; a constant specifying how to cap stroked paths, such as *butt*, *round*, or *square*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linecap" + }, + "strokeLinejoin": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linejoin][1]; a constant specifying how to join stroked paths, such as *bevel*, *miter*, *miter-clip*, or *round*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linejoin" + }, + "strokeMiterlimit": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-miterlimit][1]; a constant number specifying how to limit the length of *miter* joins on stroked paths.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-miterlimit" + }, + "strokeOpacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-opacity" + }, + "strokeWidth": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-width][1]; a constant number in pixels, or a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-width" + }, + "target": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [target][1]; a constant string specifying the target window (_e.g._,\n*_blank*) for clickable links; used in conjunction with the **href** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/target" + }, + "tip": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/TipPointer" + }, + { + "properties": { + "anchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The tip anchor specifies how to orient the tip box relative to its anchor position; it refers to the part of the tip box that is attached to the anchor point. For example, the *top-left* anchor places the top-left corner of tip box near the anchor position, hence placing the tip box below and to the right of the anchor position." + }, + "fontFamily": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font-family][1]; a constant; defaults to the plot’s font family, which is typically [*system-ui*][2].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-family [2]: https://drafts.csswg.org/css-fonts-4/#valdef-font-family-system-ui" + }, + "fontSize": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font size][1] in pixels; either a constant or a channel; defaults to the plot’s font size, which is typically 10. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-size" + }, + "fontStyle": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font style][1]; a constant; defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-style" + }, + "fontVariant": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font variant][1]; a constant; if the **text** channel contains numbers or dates, defaults to *tabular-nums* to facilitate comparing numbers; otherwise defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant" + }, + "fontWeight": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font weight][1]; a constant; defaults to the plot’s font weight, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight" + }, + "format": { + "additionalProperties": false, + "description": "How channel values are formatted for display. If a format is a string, it is interpreted as a (UTC) time format for temporal channels, and otherwise a number format.", + "properties": { + "ariaLabel": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fill": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fillOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fontSize": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fx": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fy": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "geometry": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "height": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "href": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "length": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "opacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "path": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "r": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "rotate": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "src": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "stroke": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeWidth": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "symbol": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "text": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "title": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "weight": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "width": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "z": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + } + }, + "type": "object" + }, + "frameAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The frame anchor specifies defaults for **x** and **y** based on the plot’s frame; it may be one of the four sides (*top*, *right*, *bottom*, *left*), one of the four corners (*top-left*, *top-right*, *bottom-right*,\n*bottom-left*), or the *middle* of the frame. For example, for tips distributed horizontally at the top of the frame:\n\n```js Plot.tip(data, {x: \"date\", frameAnchor: \"top\"}) ```" + }, + "lineHeight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line height in ems; defaults to 1. The line height affects the (typically vertical) separation between adjacent baselines of text, as well as the separation between the text and its anchor point." + }, + "lineWidth": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line width in ems (e.g., 10 for about 20 characters); defaults to infinity, disabling wrapping and clipping.\n\nIf **textOverflow** is null, lines will be wrapped at the specified length. If a line is split at a soft hyphen (\\xad), a hyphen (-) will be displayed at the end of the line. If **textOverflow** is not null, lines will be clipped according to the given strategy." + }, + "monospace": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, changes the default **fontFamily** to *monospace*, and uses simplified monospaced text metrics calculations." + }, + "pathFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The image filter for the tip’s box; defaults to a drop shadow." + }, + "pointer": { + "$ref": "#/definitions/TipPointer" + }, + "pointerSize": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The size of the tip’s pointer in pixels; defaults to 12." + }, + "preferredAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If an explicit tip anchor is not specified, an anchor is chosen automatically such that the tip fits within the plot’s frame; if the preferred anchor fits, it is chosen." + }, + "textAnchor": { + "anyOf": [ + { + "const": "start", + "type": "string" + }, + { + "const": "middle", + "type": "string" + }, + { + "const": "end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [text anchor][1] controls how text is aligned (typically horizontally) relative to its anchor point; it is one of *start*, *end*, or *middle*. If the frame anchor is *left*, *top-left*, or *bottom-left*, the default text anchor is *start*; if the frame anchor is *right*, *top-right*, or\n*bottom-right*, the default is *end*; otherwise it is *middle*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/text-anchor" + }, + "textOverflow": { + "anyOf": [ + { + "type": "null" + }, + { + "const": "clip", + "type": "string" + }, + { + "const": "ellipsis", + "type": "string" + }, + { + "const": "clip-start", + "type": "string" + }, + { + "const": "clip-end", + "type": "string" + }, + { + "const": "ellipsis-start", + "type": "string" + }, + { + "const": "ellipsis-middle", + "type": "string" + }, + { + "const": "ellipsis-end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How truncate (or wrap) lines of text longer than the given **lineWidth**; one of:\n\n- null (default) - preserve overflowing characters (and wrap if needed)\n- *clip* or *clip-end* - remove characters from the end\n- *clip-start* - remove characters from the start\n- *ellipsis* or *ellipsis-end* - replace characters from the end with an ellipsis (…)\n- *ellipsis-start* - replace characters from the start with an ellipsis (…)\n- *ellipsis-middle* - replace characters from the middle with an ellipsis (…)\n\nIf no **title** was specified, if text requires truncation, a title containing the non-truncated text will be implicitly added." + }, + "textPadding": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The padding around the text in pixels; defaults to 8." + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + } + }, + "type": "object" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to generate a tooltip for this mark, and any tip options." + }, + "title": { + "$ref": "#/definitions/ChannelValue", + "description": "The title; a channel specifying accessible, short textual descriptions as strings (possibly with newlines). If the tip option is specified, the title will be displayed with an interactive tooltip instead of using the SVG [title element][1].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/title" + }, + "x": { + "$ref": "#/definitions/ChannelValueIntervalSpec", + "description": "The horizontal position (or length/width) channel, typically bound to the\n*x* scale.\n\nIf an **interval** is specified, then **x1** and **x2** are derived from\n**x**, representing the lower and upper bound of the containing interval, respectively. For example, for a vertical bar chart of items sold by day:\n\n```js Plot.rectY(sales, {x: \"date\", interval: \"day\", y2: \"items\"}) ```\n\nIf *x* represents ordinal values, use a bar or cell mark instead." + }, + "x1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The required primary (starting, often left) horizontal position channel, typically bound to the *x* scale. Setting this option disables the rectX mark’s implicit stackX transform.\n\nIf *x* represents ordinal values, use a bar or cell mark instead." + }, + "x2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The required secondary (ending, often right) horizontal position channel, typically bound to the *x* scale. Setting this option disables the rectX mark’s implicit stackX transform.\n\nIf *x* represents ordinal values, use a bar or cell mark instead." + }, + "y": { + "$ref": "#/definitions/ChannelValueIntervalSpec", + "description": "The vertical position (or length/height) channel, typically bound to the\n*y* scale.\n\nIf an **interval** is specified, then **y1** and **y2** are derived from\n**y**, representing the lower and upper bound of the containing interval, respectively. For example, for a horizontal bar chart of items sold by day:\n\n```js Plot.rectX(sales, {y: \"date\", interval: \"day\", x2: \"items\"}) ```\n\nIf *y* represents ordinal values, use a bar or cell mark instead." + }, + "y1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The required primary (starting, often bottom) vertical position channel, typically bound to the *y* scale. Setting this option disables the rectY mark’s implicit stackY transform.\n\nIf *y* represents ordinal values, use a bar or cell mark instead." + }, + "y2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The required secondary (ending, often top) vertical position channel, typically bound to the *y* scale. Setting this option disables the rectY mark’s implicit stackY transform.\n\nIf *y* represents ordinal values, use a bar or cell mark instead." + }, + "z": { + "$ref": "#/definitions/ChannelValue", + "description": "The **z** channel defines the series of each value in the stack. Used when the **order** is *sum*, *appearance*, *inside-out*, or an explicit array of\n**z** values." + } + }, + "required": [ + "data", + "mark" + ], + "type": "object" + }, + "RectX": { + "additionalProperties": false, + "description": "The rectX mark.", + "properties": { + "ariaDescription": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-description][1]; a constant textual description.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-description" + }, + "ariaHidden": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-hidden][1] state; a constant indicating whether the element is exposed to an accessibility API.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-hidden" + }, + "ariaLabel": { + "$ref": "#/definitions/ChannelValue", + "description": "The [aria-label][1]; a channel specifying short textual labels representing the value in the accessibility tree.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-label" + }, + "clip": { + "anyOf": [ + { + "const": "frame", + "type": "string" + }, + { + "const": "sphere", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to clip the mark; one of:\n\n- *frame* or true - clip to the plot’s frame (inner area)\n- *sphere* - clip to the projected sphere (*e.g.*, front hemisphere)\n- null or false - do not clip\n\nThe *sphere* clip option requires a geographic projection." + }, + "data": { + "$ref": "#/definitions/PlotMarkData", + "description": "The data source for the mark." + }, + "dx": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The horizontal offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "dy": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The vertical offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "facet": { + "anyOf": [ + { + "const": "auto", + "type": "string" + }, + { + "const": "include", + "type": "string" + }, + { + "const": "exclude", + "type": "string" + }, + { + "const": "super", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to enable or disable faceting; one of:\n\n- *auto* (default) - automatically determine if this mark should be faceted\n- *include* (or true) - draw the subset of the mark’s data in the current facet\n- *exclude* - draw the subset of the mark’s data *not* in the current facet\n- *super* - draw this mark in a single frame that covers all facets\n- null (or false) - repeat this mark’s data across all facets (*i.e.*, no faceting)\n\nWhen a mark uses *super* faceting, it is not allowed to use position scales (*x*, *y*, *fx*, or *fy*); *super* faceting is intended for decorations, such as labels and legends.\n\nWhen top-level faceting is used, the default *auto* setting is equivalent to *include* when the mark data is strictly equal to the top-level facet data; otherwise it is equivalent to null. When the *include* or *exclude* facet mode is chosen, the mark data must be parallel to the top-level facet data: the data must have the same length and order. If the data are not parallel, then the wrong data may be shown in each facet. The default\n*auto* therefore requires strict equality (`===`) for safety, and using the facet data as mark data is recommended when using the *exclude* facet mode. (To construct parallel data safely, consider using [*array*.map][1] on the facet data.)\n\nWhen mark-level faceting is used, the default *auto* setting is equivalent to *include*: the mark will be faceted if either the **fx** or **fy** channel option (or both) is specified. The null or false option will disable faceting, while *exclude* draws the subset of the mark’s data *not* in the current facet.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map" + }, + "facetAnchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "right", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "const": "left", + "type": "string" + }, + { + "const": "top-left", + "type": "string" + }, + { + "const": "top-right", + "type": "string" + }, + { + "const": "bottom-left", + "type": "string" + }, + { + "const": "bottom-right", + "type": "string" + }, + { + "const": "top-empty", + "type": "string" + }, + { + "const": "right-empty", + "type": "string" + }, + { + "const": "bottom-empty", + "type": "string" + }, + { + "const": "left-empty", + "type": "string" + }, + { + "const": "empty", + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to place the mark with respect to facets; one of:\n\n- null (default for most marks) - display the mark in each non-empty facet\n- *top*, *right*, *bottom*, or *left* - display the mark only in facets on the given side\n- *top-empty*, *right-empty*, *bottom-empty*, or *left-empty* (default for axis marks) - display the mark only in facets that have empty space on the given side: either the margin, or an empty facet\n- *empty* - display the mark in empty facets only" + }, + "fill": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill" + }, + "fillOpacity": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill-opacity][1]; a constant number between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill-opacity" + }, + "filter": { + "$ref": "#/definitions/ChannelValue", + "description": "Applies a transform to filter the mark’s index according to the given channel values; only truthy values are retained.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "fx": { + "$ref": "#/definitions/ChannelValue", + "description": "The horizontal facet position channel, for mark-level faceting, bound to the *fx* scale." + }, + "fy": { + "$ref": "#/definitions/ChannelValue", + "description": "The vertical facet position channel, for mark-level faceting, bound to the\n*fy* scale." + }, + "href": { + "$ref": "#/definitions/ChannelValue", + "description": "The [href][1]; a channel specifying URLs for clickable links. May be used in conjunction with the **target** option to open links in another window.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/href" + }, + "imageFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A CSS [filter][1]; a constant string used to adjust the rendering of images, such as *blur(5px)*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/filter" + }, + "inset": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four insets: **insetTop**,\n**insetRight**, **insetBottom**, and **insetLeft**. All insets typically default to zero, though not always (say when using bin transform). A positive inset reduces effective area, while a negative inset increases it." + }, + "insetBottom": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Insets the bottom edge by the specified number of pixels. A positive value insets towards the top edge (reducing effective area), while a negative value insets away from the top edge (increasing it)." + }, + "insetLeft": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Insets the left edge by the specified number of pixels. A positive value insets towards the right edge (reducing effective area), while a negative value insets away from the right edge (increasing it)." + }, + "insetRight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Insets the right edge by the specified number of pixels. A positive value insets towards the left edge (reducing effective area), while a negative value insets away from the left edge (increasing it)." + }, + "insetTop": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Insets the top edge by the specified number of pixels. A positive value insets towards the bottom edge (reducing effective area), while a negative value insets away from the bottom edge (increasing it)." + }, + "interval": { + "anyOf": [ + { + "$ref": "#/definitions/Interval" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to convert a continuous value (**x** for rectY, **y** for rectX, or both for rect) into an interval (**x1** and **x2** for rectY, or **y1** and\n**y2** for rectX, or both for rect); one of:\n\n- a named time interval such as *day* (for date intervals)\n- a number (for number intervals), defining intervals at integer multiples of *n*\n\nSetting this option disables the implicit stack transform (stackX for rectX, or stackY for rectY)." + }, + "margin": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four mark margins: **marginTop**,\n**marginRight**, **marginBottom**, and **marginLeft**; typically defaults to 0, except for axis marks." + }, + "marginBottom": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s bottom margin; the minimum distance in pixels between the bottom edges of the inner and outer plot area." + }, + "marginLeft": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s left margin; the minimum distance in pixels between the left edges of the inner and outer plot area." + }, + "marginRight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s right margin; the minimum distance in pixels between the right edges of the mark’s inner and outer plot area." + }, + "marginTop": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s top margin; the minimum distance in pixels between the top edges of the inner and outer plot area." + }, + "mark": { + "const": "rectX", + "description": "Like rect, but if neither **x1** nor **x2** is specified, an implicit stackX transform is applied to **x**, and if **x** is not specified, it defaults to the identity function, assuming that *data* is an array of numbers [*x₀*, *x₁*, *x₂*, …].", + "type": "string" + }, + "mixBlendMode": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [mix-blend-mode][1]; a constant string specifying how to blend content such as *multiply*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode" + }, + "offset": { + "anyOf": [ + { + "$ref": "#/definitions/StackOffset" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "After stacking, an optional **offset** can be applied to translate and scale stacks, say to produce a streamgraph; defaults to null for a zero baseline (**y** = 0 for stackY, and **x** = 0 for stackX). If the *wiggle* offset is used, the default **order** changes to *inside-out*." + }, + "opacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally. For faster rendering, prefer the **strokeOpacity** or **fillOpacity** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/opacity" + }, + "order": { + "anyOf": [ + { + "$ref": "#/definitions/StackOrder" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The order in which stacks are layered; one of:\n\n- null (default) for input order\n- a named stack order method such as *inside-out* or *sum*\n- a field name, for natural order of the corresponding values\n- a function of data, for natural order of the corresponding values\n- an array of explicit **z** values in the desired order\n\nIf the *wiggle* **offset** is used, as for a streamgraph, the default changes to *inside-out*." + }, + "paintOrder": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [paint-order][1]; a constant string specifying the order in which the\n**fill**, **stroke**, and any markers are drawn; defaults to *normal*, which draws the fill, then stroke, then markers; defaults to *stroke* for the text mark to create a “halo” around text to improve legibility.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/paint-order" + }, + "pointerEvents": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [pointer-events][1] property; a constant string such as *none*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/pointer-events" + }, + "reverse": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Applies a transform to reverse the order of the mark’s index, say for reverse input order." + }, + "rx": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The rounded corner [*x*-radius][1], either in pixels or as a percentage of the rect width. If **rx** is not specified, it defaults to **ry** if present, and otherwise draws square corners.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/rx" + }, + "ry": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The rounded corner [*y*-radius][1], either in pixels or as a percentage of the rect height. If **ry** is not specified, it defaults to **rx** if present, and otherwise draws square corners.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/ry" + }, + "select": { + "$ref": "#/definitions/SelectFilter", + "description": "Applies a filter transform after data is loaded to highlight selected values only. For example, `first` and `last` select the first or last values of series only (using the *z* channel to separate series). Meanwhile, `nearestX` and `nearestY` select the point nearest to the pointer along the *x* or *y* channel dimension. Unlike Mosaic selections, a mark level *select* is internal to the mark only, and does not populate a param or selection value to be shared across clients.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "shapeRendering": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [shape-rendering][1]; a constant string such as *crispEdges*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/shape-rendering" + }, + "sort": { + "anyOf": [ + { + "$ref": "#/definitions/SortOrder" + }, + { + "$ref": "#/definitions/ChannelDomainSort" + } + ], + "description": "Either applies a transform to sort the mark’s index by the specified channel values, or imputes ordinal scale domains from this mark’s channels.\n\nWhen imputing ordinal scale domains from channel values, the **sort** option is an object whose keys are ordinal scale names such as *x* or *fx*, and whose values are channel names such as *y*, *y1*, or *y2*. For example, to impute the *y* scale’s domain from the associated *x* channel values in ascending order:\n\n```js sort: {y: \"x\"} ```\n\nFor different sort options for different scales, replace the channel name with a *value* object and per-scale options:\n\n```js sort: {y: {value: \"-x\"}} ```\n\nWhen sorting the mark’s index, the **sort** option is instead one of:\n\n- a channel value definition for sorting given values in ascending order\n- a {value, order} object for sorting given values\n- a {channel, order} object for sorting the named channel’s values" + }, + "stroke": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke" + }, + "strokeDasharray": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dasharray][1]; a constant number indicating the length in pixels of alternating dashes and gaps, or a constant string of numbers separated by spaces or commas (_e.g._, *10 2* for dashes of 10 pixels separated by gaps of 2 pixels), or *none* (the default) for no dashing\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dasharray" + }, + "strokeDashoffset": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dashoffset][1]; a constant indicating the offset in pixels of the first dash along the stroke; defaults to zero.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dashoffset" + }, + "strokeLinecap": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linecap][1]; a constant specifying how to cap stroked paths, such as *butt*, *round*, or *square*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linecap" + }, + "strokeLinejoin": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linejoin][1]; a constant specifying how to join stroked paths, such as *bevel*, *miter*, *miter-clip*, or *round*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linejoin" + }, + "strokeMiterlimit": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-miterlimit][1]; a constant number specifying how to limit the length of *miter* joins on stroked paths.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-miterlimit" + }, + "strokeOpacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-opacity" + }, + "strokeWidth": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-width][1]; a constant number in pixels, or a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-width" + }, + "target": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [target][1]; a constant string specifying the target window (_e.g._,\n*_blank*) for clickable links; used in conjunction with the **href** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/target" + }, + "tip": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/TipPointer" + }, + { + "properties": { + "anchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The tip anchor specifies how to orient the tip box relative to its anchor position; it refers to the part of the tip box that is attached to the anchor point. For example, the *top-left* anchor places the top-left corner of tip box near the anchor position, hence placing the tip box below and to the right of the anchor position." + }, + "fontFamily": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font-family][1]; a constant; defaults to the plot’s font family, which is typically [*system-ui*][2].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-family [2]: https://drafts.csswg.org/css-fonts-4/#valdef-font-family-system-ui" + }, + "fontSize": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font size][1] in pixels; either a constant or a channel; defaults to the plot’s font size, which is typically 10. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-size" + }, + "fontStyle": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font style][1]; a constant; defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-style" + }, + "fontVariant": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font variant][1]; a constant; if the **text** channel contains numbers or dates, defaults to *tabular-nums* to facilitate comparing numbers; otherwise defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant" + }, + "fontWeight": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font weight][1]; a constant; defaults to the plot’s font weight, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight" + }, + "format": { + "additionalProperties": false, + "description": "How channel values are formatted for display. If a format is a string, it is interpreted as a (UTC) time format for temporal channels, and otherwise a number format.", + "properties": { + "ariaLabel": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fill": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fillOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fontSize": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fx": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fy": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "geometry": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "height": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "href": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "length": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "opacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "path": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "r": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "rotate": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "src": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "stroke": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeWidth": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "symbol": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "text": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "title": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "weight": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "width": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "z": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + } + }, + "type": "object" + }, + "frameAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The frame anchor specifies defaults for **x** and **y** based on the plot’s frame; it may be one of the four sides (*top*, *right*, *bottom*, *left*), one of the four corners (*top-left*, *top-right*, *bottom-right*,\n*bottom-left*), or the *middle* of the frame. For example, for tips distributed horizontally at the top of the frame:\n\n```js Plot.tip(data, {x: \"date\", frameAnchor: \"top\"}) ```" + }, + "lineHeight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line height in ems; defaults to 1. The line height affects the (typically vertical) separation between adjacent baselines of text, as well as the separation between the text and its anchor point." + }, + "lineWidth": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line width in ems (e.g., 10 for about 20 characters); defaults to infinity, disabling wrapping and clipping.\n\nIf **textOverflow** is null, lines will be wrapped at the specified length. If a line is split at a soft hyphen (\\xad), a hyphen (-) will be displayed at the end of the line. If **textOverflow** is not null, lines will be clipped according to the given strategy." + }, + "monospace": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, changes the default **fontFamily** to *monospace*, and uses simplified monospaced text metrics calculations." + }, + "pathFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The image filter for the tip’s box; defaults to a drop shadow." + }, + "pointer": { + "$ref": "#/definitions/TipPointer" + }, + "pointerSize": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The size of the tip’s pointer in pixels; defaults to 12." + }, + "preferredAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If an explicit tip anchor is not specified, an anchor is chosen automatically such that the tip fits within the plot’s frame; if the preferred anchor fits, it is chosen." + }, + "textAnchor": { + "anyOf": [ + { + "const": "start", + "type": "string" + }, + { + "const": "middle", + "type": "string" + }, + { + "const": "end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [text anchor][1] controls how text is aligned (typically horizontally) relative to its anchor point; it is one of *start*, *end*, or *middle*. If the frame anchor is *left*, *top-left*, or *bottom-left*, the default text anchor is *start*; if the frame anchor is *right*, *top-right*, or\n*bottom-right*, the default is *end*; otherwise it is *middle*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/text-anchor" + }, + "textOverflow": { + "anyOf": [ + { + "type": "null" + }, + { + "const": "clip", + "type": "string" + }, + { + "const": "ellipsis", + "type": "string" + }, + { + "const": "clip-start", + "type": "string" + }, + { + "const": "clip-end", + "type": "string" + }, + { + "const": "ellipsis-start", + "type": "string" + }, + { + "const": "ellipsis-middle", + "type": "string" + }, + { + "const": "ellipsis-end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How truncate (or wrap) lines of text longer than the given **lineWidth**; one of:\n\n- null (default) - preserve overflowing characters (and wrap if needed)\n- *clip* or *clip-end* - remove characters from the end\n- *clip-start* - remove characters from the start\n- *ellipsis* or *ellipsis-end* - replace characters from the end with an ellipsis (…)\n- *ellipsis-start* - replace characters from the start with an ellipsis (…)\n- *ellipsis-middle* - replace characters from the middle with an ellipsis (…)\n\nIf no **title** was specified, if text requires truncation, a title containing the non-truncated text will be implicitly added." + }, + "textPadding": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The padding around the text in pixels; defaults to 8." + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + } + }, + "type": "object" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to generate a tooltip for this mark, and any tip options." + }, + "title": { + "$ref": "#/definitions/ChannelValue", + "description": "The title; a channel specifying accessible, short textual descriptions as strings (possibly with newlines). If the tip option is specified, the title will be displayed with an interactive tooltip instead of using the SVG [title element][1].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/title" + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position (or length/width) channel, typically bound to the\n*x* scale.\n\nIf neither **x1** nor **x2** is specified, an implicit stackX transform is applied and **x** defaults to the identity function, assuming that *data* = [*x₀*, *x₁*, *x₂*, …]. Otherwise, if only one of **x1** or **x2** is specified, the other defaults to **x**, which defaults to zero." + }, + "x1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The required primary (starting, often left) horizontal position channel, typically bound to the *x* scale. Setting this option disables the rectX mark’s implicit stackX transform.\n\nIf *x* represents ordinal values, use a bar or cell mark instead." + }, + "x2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The required secondary (ending, often right) horizontal position channel, typically bound to the *x* scale. Setting this option disables the rectX mark’s implicit stackX transform.\n\nIf *x* represents ordinal values, use a bar or cell mark instead." + }, + "y": { + "$ref": "#/definitions/ChannelValueIntervalSpec", + "description": "The vertical position (or length/height) channel, typically bound to the\n*y* scale.\n\nIf an **interval** is specified, then **y1** and **y2** are derived from\n**y**, representing the lower and upper bound of the containing interval, respectively. For example, for a horizontal bar chart of items sold by day:\n\n```js Plot.rectX(sales, {y: \"date\", interval: \"day\", x2: \"items\"}) ```\n\nIf *y* represents ordinal values, use a bar or cell mark instead." + }, + "y1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The required primary (starting, often bottom) vertical position channel, typically bound to the *y* scale. Setting this option disables the rectY mark’s implicit stackY transform.\n\nIf *y* represents ordinal values, use a bar or cell mark instead." + }, + "y2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The required secondary (ending, often top) vertical position channel, typically bound to the *y* scale. Setting this option disables the rectY mark’s implicit stackY transform.\n\nIf *y* represents ordinal values, use a bar or cell mark instead." + }, + "z": { + "$ref": "#/definitions/ChannelValue", + "description": "The **z** channel defines the series of each value in the stack. Used when the **order** is *sum*, *appearance*, *inside-out*, or an explicit array of\n**z** values." + } + }, + "required": [ + "data", + "mark" + ], + "type": "object" + }, + "RectY": { + "additionalProperties": false, + "description": "The rectY mark.", + "properties": { + "ariaDescription": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-description][1]; a constant textual description.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-description" + }, + "ariaHidden": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-hidden][1] state; a constant indicating whether the element is exposed to an accessibility API.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-hidden" + }, + "ariaLabel": { + "$ref": "#/definitions/ChannelValue", + "description": "The [aria-label][1]; a channel specifying short textual labels representing the value in the accessibility tree.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-label" + }, + "clip": { + "anyOf": [ + { + "const": "frame", + "type": "string" + }, + { + "const": "sphere", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to clip the mark; one of:\n\n- *frame* or true - clip to the plot’s frame (inner area)\n- *sphere* - clip to the projected sphere (*e.g.*, front hemisphere)\n- null or false - do not clip\n\nThe *sphere* clip option requires a geographic projection." + }, + "data": { + "$ref": "#/definitions/PlotMarkData", + "description": "The data source for the mark." + }, + "dx": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The horizontal offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "dy": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The vertical offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "facet": { + "anyOf": [ + { + "const": "auto", + "type": "string" + }, + { + "const": "include", + "type": "string" + }, + { + "const": "exclude", + "type": "string" + }, + { + "const": "super", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to enable or disable faceting; one of:\n\n- *auto* (default) - automatically determine if this mark should be faceted\n- *include* (or true) - draw the subset of the mark’s data in the current facet\n- *exclude* - draw the subset of the mark’s data *not* in the current facet\n- *super* - draw this mark in a single frame that covers all facets\n- null (or false) - repeat this mark’s data across all facets (*i.e.*, no faceting)\n\nWhen a mark uses *super* faceting, it is not allowed to use position scales (*x*, *y*, *fx*, or *fy*); *super* faceting is intended for decorations, such as labels and legends.\n\nWhen top-level faceting is used, the default *auto* setting is equivalent to *include* when the mark data is strictly equal to the top-level facet data; otherwise it is equivalent to null. When the *include* or *exclude* facet mode is chosen, the mark data must be parallel to the top-level facet data: the data must have the same length and order. If the data are not parallel, then the wrong data may be shown in each facet. The default\n*auto* therefore requires strict equality (`===`) for safety, and using the facet data as mark data is recommended when using the *exclude* facet mode. (To construct parallel data safely, consider using [*array*.map][1] on the facet data.)\n\nWhen mark-level faceting is used, the default *auto* setting is equivalent to *include*: the mark will be faceted if either the **fx** or **fy** channel option (or both) is specified. The null or false option will disable faceting, while *exclude* draws the subset of the mark’s data *not* in the current facet.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map" + }, + "facetAnchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "right", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "const": "left", + "type": "string" + }, + { + "const": "top-left", + "type": "string" + }, + { + "const": "top-right", + "type": "string" + }, + { + "const": "bottom-left", + "type": "string" + }, + { + "const": "bottom-right", + "type": "string" + }, + { + "const": "top-empty", + "type": "string" + }, + { + "const": "right-empty", + "type": "string" + }, + { + "const": "bottom-empty", + "type": "string" + }, + { + "const": "left-empty", + "type": "string" + }, + { + "const": "empty", + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to place the mark with respect to facets; one of:\n\n- null (default for most marks) - display the mark in each non-empty facet\n- *top*, *right*, *bottom*, or *left* - display the mark only in facets on the given side\n- *top-empty*, *right-empty*, *bottom-empty*, or *left-empty* (default for axis marks) - display the mark only in facets that have empty space on the given side: either the margin, or an empty facet\n- *empty* - display the mark in empty facets only" + }, + "fill": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill" + }, + "fillOpacity": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill-opacity][1]; a constant number between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill-opacity" + }, + "filter": { + "$ref": "#/definitions/ChannelValue", + "description": "Applies a transform to filter the mark’s index according to the given channel values; only truthy values are retained.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "fx": { + "$ref": "#/definitions/ChannelValue", + "description": "The horizontal facet position channel, for mark-level faceting, bound to the *fx* scale." + }, + "fy": { + "$ref": "#/definitions/ChannelValue", + "description": "The vertical facet position channel, for mark-level faceting, bound to the\n*fy* scale." + }, + "href": { + "$ref": "#/definitions/ChannelValue", + "description": "The [href][1]; a channel specifying URLs for clickable links. May be used in conjunction with the **target** option to open links in another window.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/href" + }, + "imageFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A CSS [filter][1]; a constant string used to adjust the rendering of images, such as *blur(5px)*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/filter" + }, + "inset": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four insets: **insetTop**,\n**insetRight**, **insetBottom**, and **insetLeft**. All insets typically default to zero, though not always (say when using bin transform). A positive inset reduces effective area, while a negative inset increases it." + }, + "insetBottom": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Insets the bottom edge by the specified number of pixels. A positive value insets towards the top edge (reducing effective area), while a negative value insets away from the top edge (increasing it)." + }, + "insetLeft": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Insets the left edge by the specified number of pixels. A positive value insets towards the right edge (reducing effective area), while a negative value insets away from the right edge (increasing it)." + }, + "insetRight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Insets the right edge by the specified number of pixels. A positive value insets towards the left edge (reducing effective area), while a negative value insets away from the left edge (increasing it)." + }, + "insetTop": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Insets the top edge by the specified number of pixels. A positive value insets towards the bottom edge (reducing effective area), while a negative value insets away from the bottom edge (increasing it)." + }, + "interval": { + "anyOf": [ + { + "$ref": "#/definitions/Interval" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to convert a continuous value (**x** for rectY, **y** for rectX, or both for rect) into an interval (**x1** and **x2** for rectY, or **y1** and\n**y2** for rectX, or both for rect); one of:\n\n- a named time interval such as *day* (for date intervals)\n- a number (for number intervals), defining intervals at integer multiples of *n*\n\nSetting this option disables the implicit stack transform (stackX for rectX, or stackY for rectY)." + }, + "margin": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four mark margins: **marginTop**,\n**marginRight**, **marginBottom**, and **marginLeft**; typically defaults to 0, except for axis marks." + }, + "marginBottom": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s bottom margin; the minimum distance in pixels between the bottom edges of the inner and outer plot area." + }, + "marginLeft": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s left margin; the minimum distance in pixels between the left edges of the inner and outer plot area." + }, + "marginRight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s right margin; the minimum distance in pixels between the right edges of the mark’s inner and outer plot area." + }, + "marginTop": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s top margin; the minimum distance in pixels between the top edges of the inner and outer plot area." + }, + "mark": { + "const": "rectY", + "description": "Like rect, but if neither **y1** nor **y2** is specified, apply an implicit stackY transform is applied to **y**, and if **y** is not specified, it defaults to the identity function, assuming that *data* is an array of numbers [*y₀*, *y₁*, *y₂*, …].", + "type": "string" + }, + "mixBlendMode": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [mix-blend-mode][1]; a constant string specifying how to blend content such as *multiply*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode" + }, + "offset": { + "anyOf": [ + { + "$ref": "#/definitions/StackOffset" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "After stacking, an optional **offset** can be applied to translate and scale stacks, say to produce a streamgraph; defaults to null for a zero baseline (**y** = 0 for stackY, and **x** = 0 for stackX). If the *wiggle* offset is used, the default **order** changes to *inside-out*." + }, + "opacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally. For faster rendering, prefer the **strokeOpacity** or **fillOpacity** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/opacity" + }, + "order": { + "anyOf": [ + { + "$ref": "#/definitions/StackOrder" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The order in which stacks are layered; one of:\n\n- null (default) for input order\n- a named stack order method such as *inside-out* or *sum*\n- a field name, for natural order of the corresponding values\n- a function of data, for natural order of the corresponding values\n- an array of explicit **z** values in the desired order\n\nIf the *wiggle* **offset** is used, as for a streamgraph, the default changes to *inside-out*." + }, + "paintOrder": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [paint-order][1]; a constant string specifying the order in which the\n**fill**, **stroke**, and any markers are drawn; defaults to *normal*, which draws the fill, then stroke, then markers; defaults to *stroke* for the text mark to create a “halo” around text to improve legibility.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/paint-order" + }, + "pointerEvents": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [pointer-events][1] property; a constant string such as *none*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/pointer-events" + }, + "reverse": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Applies a transform to reverse the order of the mark’s index, say for reverse input order." + }, + "rx": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The rounded corner [*x*-radius][1], either in pixels or as a percentage of the rect width. If **rx** is not specified, it defaults to **ry** if present, and otherwise draws square corners.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/rx" + }, + "ry": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The rounded corner [*y*-radius][1], either in pixels or as a percentage of the rect height. If **ry** is not specified, it defaults to **rx** if present, and otherwise draws square corners.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/ry" + }, + "select": { + "$ref": "#/definitions/SelectFilter", + "description": "Applies a filter transform after data is loaded to highlight selected values only. For example, `first` and `last` select the first or last values of series only (using the *z* channel to separate series). Meanwhile, `nearestX` and `nearestY` select the point nearest to the pointer along the *x* or *y* channel dimension. Unlike Mosaic selections, a mark level *select* is internal to the mark only, and does not populate a param or selection value to be shared across clients.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "shapeRendering": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [shape-rendering][1]; a constant string such as *crispEdges*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/shape-rendering" + }, + "sort": { + "anyOf": [ + { + "$ref": "#/definitions/SortOrder" + }, + { + "$ref": "#/definitions/ChannelDomainSort" + } + ], + "description": "Either applies a transform to sort the mark’s index by the specified channel values, or imputes ordinal scale domains from this mark’s channels.\n\nWhen imputing ordinal scale domains from channel values, the **sort** option is an object whose keys are ordinal scale names such as *x* or *fx*, and whose values are channel names such as *y*, *y1*, or *y2*. For example, to impute the *y* scale’s domain from the associated *x* channel values in ascending order:\n\n```js sort: {y: \"x\"} ```\n\nFor different sort options for different scales, replace the channel name with a *value* object and per-scale options:\n\n```js sort: {y: {value: \"-x\"}} ```\n\nWhen sorting the mark’s index, the **sort** option is instead one of:\n\n- a channel value definition for sorting given values in ascending order\n- a {value, order} object for sorting given values\n- a {channel, order} object for sorting the named channel’s values" + }, + "stroke": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke" + }, + "strokeDasharray": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dasharray][1]; a constant number indicating the length in pixels of alternating dashes and gaps, or a constant string of numbers separated by spaces or commas (_e.g._, *10 2* for dashes of 10 pixels separated by gaps of 2 pixels), or *none* (the default) for no dashing\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dasharray" + }, + "strokeDashoffset": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dashoffset][1]; a constant indicating the offset in pixels of the first dash along the stroke; defaults to zero.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dashoffset" + }, + "strokeLinecap": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linecap][1]; a constant specifying how to cap stroked paths, such as *butt*, *round*, or *square*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linecap" + }, + "strokeLinejoin": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linejoin][1]; a constant specifying how to join stroked paths, such as *bevel*, *miter*, *miter-clip*, or *round*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linejoin" + }, + "strokeMiterlimit": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-miterlimit][1]; a constant number specifying how to limit the length of *miter* joins on stroked paths.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-miterlimit" + }, + "strokeOpacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-opacity" + }, + "strokeWidth": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-width][1]; a constant number in pixels, or a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-width" + }, + "target": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [target][1]; a constant string specifying the target window (_e.g._,\n*_blank*) for clickable links; used in conjunction with the **href** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/target" + }, + "tip": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/TipPointer" + }, + { + "properties": { + "anchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The tip anchor specifies how to orient the tip box relative to its anchor position; it refers to the part of the tip box that is attached to the anchor point. For example, the *top-left* anchor places the top-left corner of tip box near the anchor position, hence placing the tip box below and to the right of the anchor position." + }, + "fontFamily": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font-family][1]; a constant; defaults to the plot’s font family, which is typically [*system-ui*][2].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-family [2]: https://drafts.csswg.org/css-fonts-4/#valdef-font-family-system-ui" + }, + "fontSize": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font size][1] in pixels; either a constant or a channel; defaults to the plot’s font size, which is typically 10. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-size" + }, + "fontStyle": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font style][1]; a constant; defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-style" + }, + "fontVariant": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font variant][1]; a constant; if the **text** channel contains numbers or dates, defaults to *tabular-nums* to facilitate comparing numbers; otherwise defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant" + }, + "fontWeight": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font weight][1]; a constant; defaults to the plot’s font weight, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight" + }, + "format": { + "additionalProperties": false, + "description": "How channel values are formatted for display. If a format is a string, it is interpreted as a (UTC) time format for temporal channels, and otherwise a number format.", + "properties": { + "ariaLabel": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fill": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fillOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fontSize": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fx": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fy": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "geometry": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "height": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "href": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "length": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "opacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "path": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "r": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "rotate": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "src": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "stroke": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeWidth": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "symbol": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "text": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "title": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "weight": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "width": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "z": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + } + }, + "type": "object" + }, + "frameAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The frame anchor specifies defaults for **x** and **y** based on the plot’s frame; it may be one of the four sides (*top*, *right*, *bottom*, *left*), one of the four corners (*top-left*, *top-right*, *bottom-right*,\n*bottom-left*), or the *middle* of the frame. For example, for tips distributed horizontally at the top of the frame:\n\n```js Plot.tip(data, {x: \"date\", frameAnchor: \"top\"}) ```" + }, + "lineHeight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line height in ems; defaults to 1. The line height affects the (typically vertical) separation between adjacent baselines of text, as well as the separation between the text and its anchor point." + }, + "lineWidth": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line width in ems (e.g., 10 for about 20 characters); defaults to infinity, disabling wrapping and clipping.\n\nIf **textOverflow** is null, lines will be wrapped at the specified length. If a line is split at a soft hyphen (\\xad), a hyphen (-) will be displayed at the end of the line. If **textOverflow** is not null, lines will be clipped according to the given strategy." + }, + "monospace": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, changes the default **fontFamily** to *monospace*, and uses simplified monospaced text metrics calculations." + }, + "pathFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The image filter for the tip’s box; defaults to a drop shadow." + }, + "pointer": { + "$ref": "#/definitions/TipPointer" + }, + "pointerSize": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The size of the tip’s pointer in pixels; defaults to 12." + }, + "preferredAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If an explicit tip anchor is not specified, an anchor is chosen automatically such that the tip fits within the plot’s frame; if the preferred anchor fits, it is chosen." + }, + "textAnchor": { + "anyOf": [ + { + "const": "start", + "type": "string" + }, + { + "const": "middle", + "type": "string" + }, + { + "const": "end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [text anchor][1] controls how text is aligned (typically horizontally) relative to its anchor point; it is one of *start*, *end*, or *middle*. If the frame anchor is *left*, *top-left*, or *bottom-left*, the default text anchor is *start*; if the frame anchor is *right*, *top-right*, or\n*bottom-right*, the default is *end*; otherwise it is *middle*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/text-anchor" + }, + "textOverflow": { + "anyOf": [ + { + "type": "null" + }, + { + "const": "clip", + "type": "string" + }, + { + "const": "ellipsis", + "type": "string" + }, + { + "const": "clip-start", + "type": "string" + }, + { + "const": "clip-end", + "type": "string" + }, + { + "const": "ellipsis-start", + "type": "string" + }, + { + "const": "ellipsis-middle", + "type": "string" + }, + { + "const": "ellipsis-end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How truncate (or wrap) lines of text longer than the given **lineWidth**; one of:\n\n- null (default) - preserve overflowing characters (and wrap if needed)\n- *clip* or *clip-end* - remove characters from the end\n- *clip-start* - remove characters from the start\n- *ellipsis* or *ellipsis-end* - replace characters from the end with an ellipsis (…)\n- *ellipsis-start* - replace characters from the start with an ellipsis (…)\n- *ellipsis-middle* - replace characters from the middle with an ellipsis (…)\n\nIf no **title** was specified, if text requires truncation, a title containing the non-truncated text will be implicitly added." + }, + "textPadding": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The padding around the text in pixels; defaults to 8." + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + } + }, + "type": "object" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to generate a tooltip for this mark, and any tip options." + }, + "title": { + "$ref": "#/definitions/ChannelValue", + "description": "The title; a channel specifying accessible, short textual descriptions as strings (possibly with newlines). If the tip option is specified, the title will be displayed with an interactive tooltip instead of using the SVG [title element][1].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/title" + }, + "x": { + "$ref": "#/definitions/ChannelValueIntervalSpec", + "description": "The horizontal position (or length/width) channel, typically bound to the\n*x* scale.\n\nIf an **interval** is specified, then **x1** and **x2** are derived from\n**x**, representing the lower and upper bound of the containing interval, respectively. For example, for a vertical bar chart of items sold by day:\n\n```js Plot.rectY(sales, {x: \"date\", interval: \"day\", y2: \"items\"}) ```\n\nIf *x* represents ordinal values, use a bar or cell mark instead." + }, + "x1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The required primary (starting, often left) horizontal position channel, typically bound to the *x* scale. Setting this option disables the rectX mark’s implicit stackX transform.\n\nIf *x* represents ordinal values, use a bar or cell mark instead." + }, + "x2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The required secondary (ending, often right) horizontal position channel, typically bound to the *x* scale. Setting this option disables the rectX mark’s implicit stackX transform.\n\nIf *x* represents ordinal values, use a bar or cell mark instead." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position (or length/height) channel, typically bound to the\n*y* scale.\n\nIf neither **y1** nor **y2** is specified, an implicit stackY transform is applied and **y** defaults to the identity function, assuming that *data* = [*y₀*, *y₁*, *y₂*, …]. Otherwise, if only one of **y1** or **y2** is specified, the other defaults to **y**, which defaults to zero." + }, + "y1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The required primary (starting, often bottom) vertical position channel, typically bound to the *y* scale. Setting this option disables the rectY mark’s implicit stackY transform.\n\nIf *y* represents ordinal values, use a bar or cell mark instead." + }, + "y2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The required secondary (ending, often top) vertical position channel, typically bound to the *y* scale. Setting this option disables the rectY mark’s implicit stackY transform.\n\nIf *y* represents ordinal values, use a bar or cell mark instead." + }, + "z": { + "$ref": "#/definitions/ChannelValue", + "description": "The **z** channel defines the series of each value in the stack. Used when the **order** is *sum*, *appearance*, *inside-out*, or an explicit array of\n**z** values." + } + }, + "required": [ + "data", + "mark" + ], + "type": "object" + }, + "Reducer": { + "anyOf": [ + { + "const": "first", + "type": "string" + }, + { + "const": "last", + "type": "string" + }, + { + "const": "identity", + "type": "string" + }, + { + "const": "count", + "type": "string" + }, + { + "const": "distinct", + "type": "string" + }, + { + "const": "sum", + "type": "string" + }, + { + "const": "proportion", + "type": "string" + }, + { + "const": "proportion-facet", + "type": "string" + }, + { + "const": "deviation", + "type": "string" + }, + { + "const": "min", + "type": "string" + }, + { + "const": "min-index", + "type": "string" + }, + { + "const": "max", + "type": "string" + }, + { + "const": "max-index", + "type": "string" + }, + { + "const": "mean", + "type": "string" + }, + { + "const": "median", + "type": "string" + }, + { + "const": "variance", + "type": "string" + }, + { + "const": "mode", + "type": "string" + }, + { + "$ref": "#/definitions/ReducerPercentile" + } + ], + "description": "How to reduce aggregated (binned or grouped) values; one of:\n\n- *first* - the first value, in input order\n- *last* - the last value, in input order\n- *count* - the number of elements (frequency)\n- *distinct* - the number of distinct values\n- *sum* - the sum of values\n- *proportion* - the sum proportional to the overall total (weighted frequency)\n- *proportion-facet* - the sum proportional to the facet total\n- *deviation* - the standard deviation\n- *min* - the minimum value\n- *min-index* - the zero-based index of the minimum value\n- *max* - the maximum value\n- *max-index* - the zero-based index of the maximum value\n- *mean* - the mean value (average)\n- *median* - the median value\n- *variance* - the variance per [Welford’s algorithm][1]\n- *mode* - the value with the most occurrences\n- *pXX* - the percentile value, where XX is a number in [00,99]\n- *identity* - the array of values\n\n[1]: https://en.wikipedia.org/wiki/Algorithms_for_calculating_variance#Welford's_online_algorithm" + }, + "ReducerPercentile": { + "enum": [ + "p00", + "p01", + "p02", + "p03", + "p04", + "p05", + "p06", + "p07", + "p08", + "p09", + "p10", + "p11", + "p12", + "p13", + "p14", + "p15", + "p16", + "p17", + "p18", + "p19", + "p20", + "p21", + "p22", + "p23", + "p24", + "p25", + "p26", + "p27", + "p28", + "p29", + "p30", + "p31", + "p32", + "p33", + "p34", + "p35", + "p36", + "p37", + "p38", + "p39", + "p40", + "p41", + "p42", + "p43", + "p44", + "p45", + "p46", + "p47", + "p48", + "p49", + "p50", + "p51", + "p52", + "p53", + "p54", + "p55", + "p56", + "p57", + "p58", + "p59", + "p60", + "p61", + "p62", + "p63", + "p64", + "p65", + "p66", + "p67", + "p68", + "p69", + "p70", + "p71", + "p72", + "p73", + "p74", + "p75", + "p76", + "p77", + "p78", + "p79", + "p80", + "p81", + "p82", + "p83", + "p84", + "p85", + "p86", + "p87", + "p88", + "p89", + "p90", + "p91", + "p92", + "p93", + "p94", + "p95", + "p96", + "p97", + "p98", + "p99" + ], + "type": "string" + }, + "RegressionY": { + "additionalProperties": false, + "description": "The regressionY mark.", + "properties": { + "ariaDescription": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-description][1]; a constant textual description.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-description" + }, + "ariaHidden": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-hidden][1] state; a constant indicating whether the element is exposed to an accessibility API.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-hidden" + }, + "ariaLabel": { + "$ref": "#/definitions/ChannelValue", + "description": "The [aria-label][1]; a channel specifying short textual labels representing the value in the accessibility tree.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-label" + }, + "ci": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The confidence interval in (0, 1), or 0 to hide bands; defaults to 0.95." + }, + "clip": { + "anyOf": [ + { + "const": "frame", + "type": "string" + }, + { + "const": "sphere", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to clip the mark; one of:\n\n- *frame* or true - clip to the plot’s frame (inner area)\n- *sphere* - clip to the projected sphere (*e.g.*, front hemisphere)\n- null or false - do not clip\n\nThe *sphere* clip option requires a geographic projection." + }, + "data": { + "$ref": "#/definitions/PlotMarkData", + "description": "The data source for the mark." + }, + "dx": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The horizontal offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "dy": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The vertical offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "facet": { + "anyOf": [ + { + "const": "auto", + "type": "string" + }, + { + "const": "include", + "type": "string" + }, + { + "const": "exclude", + "type": "string" + }, + { + "const": "super", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to enable or disable faceting; one of:\n\n- *auto* (default) - automatically determine if this mark should be faceted\n- *include* (or true) - draw the subset of the mark’s data in the current facet\n- *exclude* - draw the subset of the mark’s data *not* in the current facet\n- *super* - draw this mark in a single frame that covers all facets\n- null (or false) - repeat this mark’s data across all facets (*i.e.*, no faceting)\n\nWhen a mark uses *super* faceting, it is not allowed to use position scales (*x*, *y*, *fx*, or *fy*); *super* faceting is intended for decorations, such as labels and legends.\n\nWhen top-level faceting is used, the default *auto* setting is equivalent to *include* when the mark data is strictly equal to the top-level facet data; otherwise it is equivalent to null. When the *include* or *exclude* facet mode is chosen, the mark data must be parallel to the top-level facet data: the data must have the same length and order. If the data are not parallel, then the wrong data may be shown in each facet. The default\n*auto* therefore requires strict equality (`===`) for safety, and using the facet data as mark data is recommended when using the *exclude* facet mode. (To construct parallel data safely, consider using [*array*.map][1] on the facet data.)\n\nWhen mark-level faceting is used, the default *auto* setting is equivalent to *include*: the mark will be faceted if either the **fx** or **fy** channel option (or both) is specified. The null or false option will disable faceting, while *exclude* draws the subset of the mark’s data *not* in the current facet.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map" + }, + "facetAnchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "right", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "const": "left", + "type": "string" + }, + { + "const": "top-left", + "type": "string" + }, + { + "const": "top-right", + "type": "string" + }, + { + "const": "bottom-left", + "type": "string" + }, + { + "const": "bottom-right", + "type": "string" + }, + { + "const": "top-empty", + "type": "string" + }, + { + "const": "right-empty", + "type": "string" + }, + { + "const": "bottom-empty", + "type": "string" + }, + { + "const": "left-empty", + "type": "string" + }, + { + "const": "empty", + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to place the mark with respect to facets; one of:\n\n- null (default for most marks) - display the mark in each non-empty facet\n- *top*, *right*, *bottom*, or *left* - display the mark only in facets on the given side\n- *top-empty*, *right-empty*, *bottom-empty*, or *left-empty* (default for axis marks) - display the mark only in facets that have empty space on the given side: either the margin, or an empty facet\n- *empty* - display the mark in empty facets only" + }, + "fill": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill" + }, + "fillOpacity": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill-opacity][1]; a constant number between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill-opacity" + }, + "filter": { + "$ref": "#/definitions/ChannelValue", + "description": "Applies a transform to filter the mark’s index according to the given channel values; only truthy values are retained.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "fx": { + "$ref": "#/definitions/ChannelValue", + "description": "The horizontal facet position channel, for mark-level faceting, bound to the *fx* scale." + }, + "fy": { + "$ref": "#/definitions/ChannelValue", + "description": "The vertical facet position channel, for mark-level faceting, bound to the\n*fy* scale." + }, + "href": { + "$ref": "#/definitions/ChannelValue", + "description": "The [href][1]; a channel specifying URLs for clickable links. May be used in conjunction with the **target** option to open links in another window.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/href" + }, + "imageFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A CSS [filter][1]; a constant string used to adjust the rendering of images, such as *blur(5px)*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/filter" + }, + "margin": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four mark margins: **marginTop**,\n**marginRight**, **marginBottom**, and **marginLeft**; typically defaults to 0, except for axis marks." + }, + "marginBottom": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s bottom margin; the minimum distance in pixels between the bottom edges of the inner and outer plot area." + }, + "marginLeft": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s left margin; the minimum distance in pixels between the left edges of the inner and outer plot area." + }, + "marginRight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s right margin; the minimum distance in pixels between the right edges of the mark’s inner and outer plot area." + }, + "marginTop": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s top margin; the minimum distance in pixels between the top edges of the inner and outer plot area." + }, + "mark": { + "const": "regressionY", + "description": "A mark that draws [linear regression][1] lines with confidence bands, representing the estimated relation of a dependent variable (*y*) on an independent variable (*x*).\n\nThe linear regression line is fit using the [least squares][2] approach. See Torben Jansen’s [“Linear regression with confidence bands”][3] and [this StatExchange question][4] for details on the confidence interval calculation.\n\nMultiple regressions can be produced by specifying a **z**, **fill**, or\n**stroke** channel.\n\n[1]: https://en.wikipedia.org/wiki/Linear_regression [2]: https://en.wikipedia.org/wiki/Least_squares [3]: https://observablehq.com/@toja/linear-regression-with-confidence-bands [4]: https://stats.stackexchange.com/questions/101318/understanding-shape-and-calculation-of-confidence-bands-in-linear-regression", + "type": "string" + }, + "mixBlendMode": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [mix-blend-mode][1]; a constant string specifying how to blend content such as *multiply*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode" + }, + "opacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally. For faster rendering, prefer the **strokeOpacity** or **fillOpacity** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/opacity" + }, + "paintOrder": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [paint-order][1]; a constant string specifying the order in which the\n**fill**, **stroke**, and any markers are drawn; defaults to *normal*, which draws the fill, then stroke, then markers; defaults to *stroke* for the text mark to create a “halo” around text to improve legibility.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/paint-order" + }, + "pointerEvents": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [pointer-events][1] property; a constant string such as *none*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/pointer-events" + }, + "precision": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The distance in pixels between samples of the confidence band; defaults to 4." + }, + "reverse": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Applies a transform to reverse the order of the mark’s index, say for reverse input order." + }, + "select": { + "$ref": "#/definitions/SelectFilter", + "description": "Applies a filter transform after data is loaded to highlight selected values only. For example, `first` and `last` select the first or last values of series only (using the *z* channel to separate series). Meanwhile, `nearestX` and `nearestY` select the point nearest to the pointer along the *x* or *y* channel dimension. Unlike Mosaic selections, a mark level *select* is internal to the mark only, and does not populate a param or selection value to be shared across clients.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "shapeRendering": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [shape-rendering][1]; a constant string such as *crispEdges*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/shape-rendering" + }, + "sort": { + "anyOf": [ + { + "$ref": "#/definitions/SortOrder" + }, + { + "$ref": "#/definitions/ChannelDomainSort" + } + ], + "description": "Either applies a transform to sort the mark’s index by the specified channel values, or imputes ordinal scale domains from this mark’s channels.\n\nWhen imputing ordinal scale domains from channel values, the **sort** option is an object whose keys are ordinal scale names such as *x* or *fx*, and whose values are channel names such as *y*, *y1*, or *y2*. For example, to impute the *y* scale’s domain from the associated *x* channel values in ascending order:\n\n```js sort: {y: \"x\"} ```\n\nFor different sort options for different scales, replace the channel name with a *value* object and per-scale options:\n\n```js sort: {y: {value: \"-x\"}} ```\n\nWhen sorting the mark’s index, the **sort** option is instead one of:\n\n- a channel value definition for sorting given values in ascending order\n- a {value, order} object for sorting given values\n- a {channel, order} object for sorting the named channel’s values" + }, + "stroke": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke" + }, + "strokeDasharray": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dasharray][1]; a constant number indicating the length in pixels of alternating dashes and gaps, or a constant string of numbers separated by spaces or commas (_e.g._, *10 2* for dashes of 10 pixels separated by gaps of 2 pixels), or *none* (the default) for no dashing\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dasharray" + }, + "strokeDashoffset": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dashoffset][1]; a constant indicating the offset in pixels of the first dash along the stroke; defaults to zero.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dashoffset" + }, + "strokeLinecap": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linecap][1]; a constant specifying how to cap stroked paths, such as *butt*, *round*, or *square*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linecap" + }, + "strokeLinejoin": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linejoin][1]; a constant specifying how to join stroked paths, such as *bevel*, *miter*, *miter-clip*, or *round*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linejoin" + }, + "strokeMiterlimit": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-miterlimit][1]; a constant number specifying how to limit the length of *miter* joins on stroked paths.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-miterlimit" + }, + "strokeOpacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-opacity" + }, + "strokeWidth": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-width][1]; a constant number in pixels, or a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-width" + }, + "target": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [target][1]; a constant string specifying the target window (_e.g._,\n*_blank*) for clickable links; used in conjunction with the **href** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/target" + }, + "tip": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/TipPointer" + }, + { + "properties": { + "anchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The tip anchor specifies how to orient the tip box relative to its anchor position; it refers to the part of the tip box that is attached to the anchor point. For example, the *top-left* anchor places the top-left corner of tip box near the anchor position, hence placing the tip box below and to the right of the anchor position." + }, + "fontFamily": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font-family][1]; a constant; defaults to the plot’s font family, which is typically [*system-ui*][2].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-family [2]: https://drafts.csswg.org/css-fonts-4/#valdef-font-family-system-ui" + }, + "fontSize": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font size][1] in pixels; either a constant or a channel; defaults to the plot’s font size, which is typically 10. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-size" + }, + "fontStyle": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font style][1]; a constant; defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-style" + }, + "fontVariant": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font variant][1]; a constant; if the **text** channel contains numbers or dates, defaults to *tabular-nums* to facilitate comparing numbers; otherwise defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant" + }, + "fontWeight": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font weight][1]; a constant; defaults to the plot’s font weight, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight" + }, + "format": { + "additionalProperties": false, + "description": "How channel values are formatted for display. If a format is a string, it is interpreted as a (UTC) time format for temporal channels, and otherwise a number format.", + "properties": { + "ariaLabel": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fill": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fillOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fontSize": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fx": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fy": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "geometry": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "height": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "href": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "length": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "opacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "path": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "r": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "rotate": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "src": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "stroke": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeWidth": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "symbol": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "text": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "title": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "weight": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "width": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "z": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + } + }, + "type": "object" + }, + "frameAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The frame anchor specifies defaults for **x** and **y** based on the plot’s frame; it may be one of the four sides (*top*, *right*, *bottom*, *left*), one of the four corners (*top-left*, *top-right*, *bottom-right*,\n*bottom-left*), or the *middle* of the frame. For example, for tips distributed horizontally at the top of the frame:\n\n```js Plot.tip(data, {x: \"date\", frameAnchor: \"top\"}) ```" + }, + "lineHeight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line height in ems; defaults to 1. The line height affects the (typically vertical) separation between adjacent baselines of text, as well as the separation between the text and its anchor point." + }, + "lineWidth": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line width in ems (e.g., 10 for about 20 characters); defaults to infinity, disabling wrapping and clipping.\n\nIf **textOverflow** is null, lines will be wrapped at the specified length. If a line is split at a soft hyphen (\\xad), a hyphen (-) will be displayed at the end of the line. If **textOverflow** is not null, lines will be clipped according to the given strategy." + }, + "monospace": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, changes the default **fontFamily** to *monospace*, and uses simplified monospaced text metrics calculations." + }, + "pathFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The image filter for the tip’s box; defaults to a drop shadow." + }, + "pointer": { + "$ref": "#/definitions/TipPointer" + }, + "pointerSize": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The size of the tip’s pointer in pixels; defaults to 12." + }, + "preferredAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If an explicit tip anchor is not specified, an anchor is chosen automatically such that the tip fits within the plot’s frame; if the preferred anchor fits, it is chosen." + }, + "textAnchor": { + "anyOf": [ + { + "const": "start", + "type": "string" + }, + { + "const": "middle", + "type": "string" + }, + { + "const": "end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [text anchor][1] controls how text is aligned (typically horizontally) relative to its anchor point; it is one of *start*, *end*, or *middle*. If the frame anchor is *left*, *top-left*, or *bottom-left*, the default text anchor is *start*; if the frame anchor is *right*, *top-right*, or\n*bottom-right*, the default is *end*; otherwise it is *middle*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/text-anchor" + }, + "textOverflow": { + "anyOf": [ + { + "type": "null" + }, + { + "const": "clip", + "type": "string" + }, + { + "const": "ellipsis", + "type": "string" + }, + { + "const": "clip-start", + "type": "string" + }, + { + "const": "clip-end", + "type": "string" + }, + { + "const": "ellipsis-start", + "type": "string" + }, + { + "const": "ellipsis-middle", + "type": "string" + }, + { + "const": "ellipsis-end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How truncate (or wrap) lines of text longer than the given **lineWidth**; one of:\n\n- null (default) - preserve overflowing characters (and wrap if needed)\n- *clip* or *clip-end* - remove characters from the end\n- *clip-start* - remove characters from the start\n- *ellipsis* or *ellipsis-end* - replace characters from the end with an ellipsis (…)\n- *ellipsis-start* - replace characters from the start with an ellipsis (…)\n- *ellipsis-middle* - replace characters from the middle with an ellipsis (…)\n\nIf no **title** was specified, if text requires truncation, a title containing the non-truncated text will be implicitly added." + }, + "textPadding": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The padding around the text in pixels; defaults to 8." + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + } + }, + "type": "object" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to generate a tooltip for this mark, and any tip options." + }, + "title": { + "$ref": "#/definitions/ChannelValue", + "description": "The title; a channel specifying accessible, short textual descriptions as strings (possibly with newlines). If the tip option is specified, the title will be displayed with an interactive tooltip instead of using the SVG [title element][1].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/title" + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The independent variable horizontal position channel, typically bound to the *x* scale; defaults to the zero-based index of the data [0, 1, 2, …]." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The dependent variable vertical position channel, typically bound to the\n*y* scale; defaults to identity, assuming that *data* = [*y₀*, *y₁*, *y₂*, …]." + }, + "z": { + "$ref": "#/definitions/ChannelValue", + "description": "An optional ordinal channel for grouping data into (possibly stacked) series, producing an independent regression for each group. If not specified, it defaults to **fill** if a channel, or **stroke** if a channel." + } + }, + "required": [ + "data", + "mark" + ], + "type": "object" + }, + "RowNumber": { + "additionalProperties": false, + "properties": { + "orderby": { + "anyOf": [ + { + "$ref": "#/definitions/TransformField" + }, + { + "items": { + "$ref": "#/definitions/TransformField" + }, + "type": "array" + } + ] + }, + "partitionby": { + "anyOf": [ + { + "$ref": "#/definitions/TransformField" + }, + { + "items": { + "$ref": "#/definitions/TransformField" + }, + "type": "array" + } + ] + }, + "range": { + "anyOf": [ + { + "items": { + "type": [ + "number", + "null" + ] + }, + "type": "array" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "row_number": { + "anyOf": [ + { + "type": "null" + }, + { + "maxItems": 0, + "minItems": 0, + "type": "array" + } + ], + "description": "Compute the 1-based row number over an ordered window partition." + }, + "rows": { + "anyOf": [ + { + "items": { + "type": [ + "number", + "null" + ] + }, + "type": "array" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + } + }, + "required": [ + "row_number" + ], + "type": "object" + }, + "RuleX": { + "additionalProperties": false, + "description": "The ruleX mark.", + "properties": { + "ariaDescription": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-description][1]; a constant textual description.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-description" + }, + "ariaHidden": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-hidden][1] state; a constant indicating whether the element is exposed to an accessibility API.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-hidden" + }, + "ariaLabel": { + "$ref": "#/definitions/ChannelValue", + "description": "The [aria-label][1]; a channel specifying short textual labels representing the value in the accessibility tree.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-label" + }, + "clip": { + "anyOf": [ + { + "const": "frame", + "type": "string" + }, + { + "const": "sphere", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to clip the mark; one of:\n\n- *frame* or true - clip to the plot’s frame (inner area)\n- *sphere* - clip to the projected sphere (*e.g.*, front hemisphere)\n- null or false - do not clip\n\nThe *sphere* clip option requires a geographic projection." + }, + "data": { + "$ref": "#/definitions/PlotMarkData", + "description": "The data source for the mark." + }, + "dx": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The horizontal offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "dy": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The vertical offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "facet": { + "anyOf": [ + { + "const": "auto", + "type": "string" + }, + { + "const": "include", + "type": "string" + }, + { + "const": "exclude", + "type": "string" + }, + { + "const": "super", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to enable or disable faceting; one of:\n\n- *auto* (default) - automatically determine if this mark should be faceted\n- *include* (or true) - draw the subset of the mark’s data in the current facet\n- *exclude* - draw the subset of the mark’s data *not* in the current facet\n- *super* - draw this mark in a single frame that covers all facets\n- null (or false) - repeat this mark’s data across all facets (*i.e.*, no faceting)\n\nWhen a mark uses *super* faceting, it is not allowed to use position scales (*x*, *y*, *fx*, or *fy*); *super* faceting is intended for decorations, such as labels and legends.\n\nWhen top-level faceting is used, the default *auto* setting is equivalent to *include* when the mark data is strictly equal to the top-level facet data; otherwise it is equivalent to null. When the *include* or *exclude* facet mode is chosen, the mark data must be parallel to the top-level facet data: the data must have the same length and order. If the data are not parallel, then the wrong data may be shown in each facet. The default\n*auto* therefore requires strict equality (`===`) for safety, and using the facet data as mark data is recommended when using the *exclude* facet mode. (To construct parallel data safely, consider using [*array*.map][1] on the facet data.)\n\nWhen mark-level faceting is used, the default *auto* setting is equivalent to *include*: the mark will be faceted if either the **fx** or **fy** channel option (or both) is specified. The null or false option will disable faceting, while *exclude* draws the subset of the mark’s data *not* in the current facet.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map" + }, + "facetAnchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "right", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "const": "left", + "type": "string" + }, + { + "const": "top-left", + "type": "string" + }, + { + "const": "top-right", + "type": "string" + }, + { + "const": "bottom-left", + "type": "string" + }, + { + "const": "bottom-right", + "type": "string" + }, + { + "const": "top-empty", + "type": "string" + }, + { + "const": "right-empty", + "type": "string" + }, + { + "const": "bottom-empty", + "type": "string" + }, + { + "const": "left-empty", + "type": "string" + }, + { + "const": "empty", + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to place the mark with respect to facets; one of:\n\n- null (default for most marks) - display the mark in each non-empty facet\n- *top*, *right*, *bottom*, or *left* - display the mark only in facets on the given side\n- *top-empty*, *right-empty*, *bottom-empty*, or *left-empty* (default for axis marks) - display the mark only in facets that have empty space on the given side: either the margin, or an empty facet\n- *empty* - display the mark in empty facets only" + }, + "fill": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill" + }, + "fillOpacity": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill-opacity][1]; a constant number between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill-opacity" + }, + "filter": { + "$ref": "#/definitions/ChannelValue", + "description": "Applies a transform to filter the mark’s index according to the given channel values; only truthy values are retained.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "fx": { + "$ref": "#/definitions/ChannelValue", + "description": "The horizontal facet position channel, for mark-level faceting, bound to the *fx* scale." + }, + "fy": { + "$ref": "#/definitions/ChannelValue", + "description": "The vertical facet position channel, for mark-level faceting, bound to the\n*fy* scale." + }, + "href": { + "$ref": "#/definitions/ChannelValue", + "description": "The [href][1]; a channel specifying URLs for clickable links. May be used in conjunction with the **target** option to open links in another window.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/href" + }, + "imageFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A CSS [filter][1]; a constant string used to adjust the rendering of images, such as *blur(5px)*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/filter" + }, + "inset": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four insets: **insetTop**,\n**insetRight**, **insetBottom**, and **insetLeft**. All insets typically default to zero, though not always (say when using bin transform). A positive inset reduces effective area, while a negative inset increases it." + }, + "insetBottom": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Insets the bottom edge by the specified number of pixels. A positive value insets towards the top edge (reducing effective area), while a negative value insets away from the top edge (increasing it)." + }, + "insetTop": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Insets the top edge by the specified number of pixels. A positive value insets towards the bottom edge (reducing effective area), while a negative value insets away from the bottom edge (increasing it)." + }, + "interval": { + "anyOf": [ + { + "$ref": "#/definitions/Interval" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to convert a continuous value (**y** for ruleX, or **x** for ruleY) into an interval (**y1** and **y2** for ruleX, or **x1** and **x2** for ruleY); one of:\n\n- a named time interval such as *day* (for date intervals)\n- a number (for number intervals), defining intervals at integer multiples of *n*" + }, + "margin": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four mark margins: **marginTop**,\n**marginRight**, **marginBottom**, and **marginLeft**; typically defaults to 0, except for axis marks." + }, + "marginBottom": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s bottom margin; the minimum distance in pixels between the bottom edges of the inner and outer plot area." + }, + "marginLeft": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s left margin; the minimum distance in pixels between the left edges of the inner and outer plot area." + }, + "marginRight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s right margin; the minimum distance in pixels between the right edges of the mark’s inner and outer plot area." + }, + "marginTop": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s top margin; the minimum distance in pixels between the top edges of the inner and outer plot area." + }, + "mark": { + "const": "ruleX", + "description": "A horizontally-positioned ruleX mark (a vertical line, |). The **x** channel specifies the rule’s horizontal position and defaults to identity, assuming that *data* = [*x₀*, *x₁*, *x₂*, …]; the optional **y1** and\n**y2** channels specify its vertical extent.\n\nThe ruleX mark is often used to highlight specific *x* values. If *y* represents ordinal values, use a tickX mark instead.", + "type": "string" + }, + "marker": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for markerStart, markerMid, and markerEnd; one of:\n\n- a marker name such as *arrow* or *circle*\n- *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*" + }, + "markerEnd": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The marker for the ending point of a line segment; one of:\n\n- a marker name such as *arrow* or *circle*\n* *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*" + }, + "markerMid": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The marker for any middle (interior) points of a line segment. If the line segment only has a start and end point, this option has no effect. One of:\n\n- a marker name such as *arrow* or *circle*\n* *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*\n* a function - a custom marker function; see below" + }, + "markerStart": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The marker for the starting point of a line segment; one of:\n\n- a marker name such as *arrow* or *circle*\n* *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*" + }, + "mixBlendMode": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [mix-blend-mode][1]; a constant string specifying how to blend content such as *multiply*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode" + }, + "opacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally. For faster rendering, prefer the **strokeOpacity** or **fillOpacity** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/opacity" + }, + "paintOrder": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [paint-order][1]; a constant string specifying the order in which the\n**fill**, **stroke**, and any markers are drawn; defaults to *normal*, which draws the fill, then stroke, then markers; defaults to *stroke* for the text mark to create a “halo” around text to improve legibility.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/paint-order" + }, + "pointerEvents": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [pointer-events][1] property; a constant string such as *none*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/pointer-events" + }, + "reverse": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Applies a transform to reverse the order of the mark’s index, say for reverse input order." + }, + "select": { + "$ref": "#/definitions/SelectFilter", + "description": "Applies a filter transform after data is loaded to highlight selected values only. For example, `first` and `last` select the first or last values of series only (using the *z* channel to separate series). Meanwhile, `nearestX` and `nearestY` select the point nearest to the pointer along the *x* or *y* channel dimension. Unlike Mosaic selections, a mark level *select* is internal to the mark only, and does not populate a param or selection value to be shared across clients.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "shapeRendering": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [shape-rendering][1]; a constant string such as *crispEdges*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/shape-rendering" + }, + "sort": { + "anyOf": [ + { + "$ref": "#/definitions/SortOrder" + }, + { + "$ref": "#/definitions/ChannelDomainSort" + } + ], + "description": "Either applies a transform to sort the mark’s index by the specified channel values, or imputes ordinal scale domains from this mark’s channels.\n\nWhen imputing ordinal scale domains from channel values, the **sort** option is an object whose keys are ordinal scale names such as *x* or *fx*, and whose values are channel names such as *y*, *y1*, or *y2*. For example, to impute the *y* scale’s domain from the associated *x* channel values in ascending order:\n\n```js sort: {y: \"x\"} ```\n\nFor different sort options for different scales, replace the channel name with a *value* object and per-scale options:\n\n```js sort: {y: {value: \"-x\"}} ```\n\nWhen sorting the mark’s index, the **sort** option is instead one of:\n\n- a channel value definition for sorting given values in ascending order\n- a {value, order} object for sorting given values\n- a {channel, order} object for sorting the named channel’s values" + }, + "stroke": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke" + }, + "strokeDasharray": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dasharray][1]; a constant number indicating the length in pixels of alternating dashes and gaps, or a constant string of numbers separated by spaces or commas (_e.g._, *10 2* for dashes of 10 pixels separated by gaps of 2 pixels), or *none* (the default) for no dashing\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dasharray" + }, + "strokeDashoffset": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dashoffset][1]; a constant indicating the offset in pixels of the first dash along the stroke; defaults to zero.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dashoffset" + }, + "strokeLinecap": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linecap][1]; a constant specifying how to cap stroked paths, such as *butt*, *round*, or *square*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linecap" + }, + "strokeLinejoin": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linejoin][1]; a constant specifying how to join stroked paths, such as *bevel*, *miter*, *miter-clip*, or *round*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linejoin" + }, + "strokeMiterlimit": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-miterlimit][1]; a constant number specifying how to limit the length of *miter* joins on stroked paths.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-miterlimit" + }, + "strokeOpacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-opacity" + }, + "strokeWidth": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-width][1]; a constant number in pixels, or a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-width" + }, + "target": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [target][1]; a constant string specifying the target window (_e.g._,\n*_blank*) for clickable links; used in conjunction with the **href** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/target" + }, + "tip": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/TipPointer" + }, + { + "properties": { + "anchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The tip anchor specifies how to orient the tip box relative to its anchor position; it refers to the part of the tip box that is attached to the anchor point. For example, the *top-left* anchor places the top-left corner of tip box near the anchor position, hence placing the tip box below and to the right of the anchor position." + }, + "fontFamily": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font-family][1]; a constant; defaults to the plot’s font family, which is typically [*system-ui*][2].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-family [2]: https://drafts.csswg.org/css-fonts-4/#valdef-font-family-system-ui" + }, + "fontSize": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font size][1] in pixels; either a constant or a channel; defaults to the plot’s font size, which is typically 10. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-size" + }, + "fontStyle": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font style][1]; a constant; defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-style" + }, + "fontVariant": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font variant][1]; a constant; if the **text** channel contains numbers or dates, defaults to *tabular-nums* to facilitate comparing numbers; otherwise defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant" + }, + "fontWeight": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font weight][1]; a constant; defaults to the plot’s font weight, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight" + }, + "format": { + "additionalProperties": false, + "description": "How channel values are formatted for display. If a format is a string, it is interpreted as a (UTC) time format for temporal channels, and otherwise a number format.", + "properties": { + "ariaLabel": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fill": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fillOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fontSize": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fx": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fy": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "geometry": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "height": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "href": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "length": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "opacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "path": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "r": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "rotate": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "src": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "stroke": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeWidth": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "symbol": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "text": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "title": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "weight": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "width": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "z": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + } + }, + "type": "object" + }, + "frameAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The frame anchor specifies defaults for **x** and **y** based on the plot’s frame; it may be one of the four sides (*top*, *right*, *bottom*, *left*), one of the four corners (*top-left*, *top-right*, *bottom-right*,\n*bottom-left*), or the *middle* of the frame. For example, for tips distributed horizontally at the top of the frame:\n\n```js Plot.tip(data, {x: \"date\", frameAnchor: \"top\"}) ```" + }, + "lineHeight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line height in ems; defaults to 1. The line height affects the (typically vertical) separation between adjacent baselines of text, as well as the separation between the text and its anchor point." + }, + "lineWidth": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line width in ems (e.g., 10 for about 20 characters); defaults to infinity, disabling wrapping and clipping.\n\nIf **textOverflow** is null, lines will be wrapped at the specified length. If a line is split at a soft hyphen (\\xad), a hyphen (-) will be displayed at the end of the line. If **textOverflow** is not null, lines will be clipped according to the given strategy." + }, + "monospace": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, changes the default **fontFamily** to *monospace*, and uses simplified monospaced text metrics calculations." + }, + "pathFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The image filter for the tip’s box; defaults to a drop shadow." + }, + "pointer": { + "$ref": "#/definitions/TipPointer" + }, + "pointerSize": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The size of the tip’s pointer in pixels; defaults to 12." + }, + "preferredAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If an explicit tip anchor is not specified, an anchor is chosen automatically such that the tip fits within the plot’s frame; if the preferred anchor fits, it is chosen." + }, + "textAnchor": { + "anyOf": [ + { + "const": "start", + "type": "string" + }, + { + "const": "middle", + "type": "string" + }, + { + "const": "end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [text anchor][1] controls how text is aligned (typically horizontally) relative to its anchor point; it is one of *start*, *end*, or *middle*. If the frame anchor is *left*, *top-left*, or *bottom-left*, the default text anchor is *start*; if the frame anchor is *right*, *top-right*, or\n*bottom-right*, the default is *end*; otherwise it is *middle*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/text-anchor" + }, + "textOverflow": { + "anyOf": [ + { + "type": "null" + }, + { + "const": "clip", + "type": "string" + }, + { + "const": "ellipsis", + "type": "string" + }, + { + "const": "clip-start", + "type": "string" + }, + { + "const": "clip-end", + "type": "string" + }, + { + "const": "ellipsis-start", + "type": "string" + }, + { + "const": "ellipsis-middle", + "type": "string" + }, + { + "const": "ellipsis-end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How truncate (or wrap) lines of text longer than the given **lineWidth**; one of:\n\n- null (default) - preserve overflowing characters (and wrap if needed)\n- *clip* or *clip-end* - remove characters from the end\n- *clip-start* - remove characters from the start\n- *ellipsis* or *ellipsis-end* - replace characters from the end with an ellipsis (…)\n- *ellipsis-start* - replace characters from the start with an ellipsis (…)\n- *ellipsis-middle* - replace characters from the middle with an ellipsis (…)\n\nIf no **title** was specified, if text requires truncation, a title containing the non-truncated text will be implicitly added." + }, + "textPadding": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The padding around the text in pixels; defaults to 8." + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + } + }, + "type": "object" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to generate a tooltip for this mark, and any tip options." + }, + "title": { + "$ref": "#/definitions/ChannelValue", + "description": "The title; a channel specifying accessible, short textual descriptions as strings (possibly with newlines). If the tip option is specified, the title will be displayed with an interactive tooltip instead of using the SVG [title element][1].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/title" + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position of the tick; an optional channel bound to the *x* scale. If not specified, the rule will be horizontally centered in the plot’s frame." + }, + "y": { + "$ref": "#/definitions/ChannelValueIntervalSpec", + "description": "Shorthand for specifying both the primary and secondary vertical position of the tick as the bounds of the containing interval; can only be used in conjunction with the **interval** option." + }, + "y1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The primary (starting, often bottom) vertical position of the tick; a channel bound to the *y* scale.\n\nIf *y* represents ordinal values, use a tickX mark instead." + }, + "y2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The secondary (ending, often top) vertical position of the tick; a channel bound to the *y* scale.\n\nIf *y* represents ordinal values, use a tickX mark instead." + } + }, + "required": [ + "mark" + ], + "type": "object" + }, + "RuleY": { + "additionalProperties": false, + "description": "The ruleY mark.", + "properties": { + "ariaDescription": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-description][1]; a constant textual description.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-description" + }, + "ariaHidden": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-hidden][1] state; a constant indicating whether the element is exposed to an accessibility API.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-hidden" + }, + "ariaLabel": { + "$ref": "#/definitions/ChannelValue", + "description": "The [aria-label][1]; a channel specifying short textual labels representing the value in the accessibility tree.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-label" + }, + "clip": { + "anyOf": [ + { + "const": "frame", + "type": "string" + }, + { + "const": "sphere", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to clip the mark; one of:\n\n- *frame* or true - clip to the plot’s frame (inner area)\n- *sphere* - clip to the projected sphere (*e.g.*, front hemisphere)\n- null or false - do not clip\n\nThe *sphere* clip option requires a geographic projection." + }, + "data": { + "$ref": "#/definitions/PlotMarkData", + "description": "The data source for the mark." + }, + "dx": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The horizontal offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "dy": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The vertical offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "facet": { + "anyOf": [ + { + "const": "auto", + "type": "string" + }, + { + "const": "include", + "type": "string" + }, + { + "const": "exclude", + "type": "string" + }, + { + "const": "super", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to enable or disable faceting; one of:\n\n- *auto* (default) - automatically determine if this mark should be faceted\n- *include* (or true) - draw the subset of the mark’s data in the current facet\n- *exclude* - draw the subset of the mark’s data *not* in the current facet\n- *super* - draw this mark in a single frame that covers all facets\n- null (or false) - repeat this mark’s data across all facets (*i.e.*, no faceting)\n\nWhen a mark uses *super* faceting, it is not allowed to use position scales (*x*, *y*, *fx*, or *fy*); *super* faceting is intended for decorations, such as labels and legends.\n\nWhen top-level faceting is used, the default *auto* setting is equivalent to *include* when the mark data is strictly equal to the top-level facet data; otherwise it is equivalent to null. When the *include* or *exclude* facet mode is chosen, the mark data must be parallel to the top-level facet data: the data must have the same length and order. If the data are not parallel, then the wrong data may be shown in each facet. The default\n*auto* therefore requires strict equality (`===`) for safety, and using the facet data as mark data is recommended when using the *exclude* facet mode. (To construct parallel data safely, consider using [*array*.map][1] on the facet data.)\n\nWhen mark-level faceting is used, the default *auto* setting is equivalent to *include*: the mark will be faceted if either the **fx** or **fy** channel option (or both) is specified. The null or false option will disable faceting, while *exclude* draws the subset of the mark’s data *not* in the current facet.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map" + }, + "facetAnchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "right", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "const": "left", + "type": "string" + }, + { + "const": "top-left", + "type": "string" + }, + { + "const": "top-right", + "type": "string" + }, + { + "const": "bottom-left", + "type": "string" + }, + { + "const": "bottom-right", + "type": "string" + }, + { + "const": "top-empty", + "type": "string" + }, + { + "const": "right-empty", + "type": "string" + }, + { + "const": "bottom-empty", + "type": "string" + }, + { + "const": "left-empty", + "type": "string" + }, + { + "const": "empty", + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to place the mark with respect to facets; one of:\n\n- null (default for most marks) - display the mark in each non-empty facet\n- *top*, *right*, *bottom*, or *left* - display the mark only in facets on the given side\n- *top-empty*, *right-empty*, *bottom-empty*, or *left-empty* (default for axis marks) - display the mark only in facets that have empty space on the given side: either the margin, or an empty facet\n- *empty* - display the mark in empty facets only" + }, + "fill": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill" + }, + "fillOpacity": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill-opacity][1]; a constant number between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill-opacity" + }, + "filter": { + "$ref": "#/definitions/ChannelValue", + "description": "Applies a transform to filter the mark’s index according to the given channel values; only truthy values are retained.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "fx": { + "$ref": "#/definitions/ChannelValue", + "description": "The horizontal facet position channel, for mark-level faceting, bound to the *fx* scale." + }, + "fy": { + "$ref": "#/definitions/ChannelValue", + "description": "The vertical facet position channel, for mark-level faceting, bound to the\n*fy* scale." + }, + "href": { + "$ref": "#/definitions/ChannelValue", + "description": "The [href][1]; a channel specifying URLs for clickable links. May be used in conjunction with the **target** option to open links in another window.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/href" + }, + "imageFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A CSS [filter][1]; a constant string used to adjust the rendering of images, such as *blur(5px)*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/filter" + }, + "inset": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four insets: **insetTop**,\n**insetRight**, **insetBottom**, and **insetLeft**. All insets typically default to zero, though not always (say when using bin transform). A positive inset reduces effective area, while a negative inset increases it." + }, + "insetBottom": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Insets the bottom edge by the specified number of pixels. A positive value insets towards the top edge (reducing effective area), while a negative value insets away from the top edge (increasing it)." + }, + "insetTop": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Insets the top edge by the specified number of pixels. A positive value insets towards the bottom edge (reducing effective area), while a negative value insets away from the bottom edge (increasing it)." + }, + "interval": { + "anyOf": [ + { + "$ref": "#/definitions/Interval" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to convert a continuous value (**y** for ruleX, or **x** for ruleY) into an interval (**y1** and **y2** for ruleX, or **x1** and **x2** for ruleY); one of:\n\n- a named time interval such as *day* (for date intervals)\n- a number (for number intervals), defining intervals at integer multiples of *n*" + }, + "margin": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four mark margins: **marginTop**,\n**marginRight**, **marginBottom**, and **marginLeft**; typically defaults to 0, except for axis marks." + }, + "marginBottom": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s bottom margin; the minimum distance in pixels between the bottom edges of the inner and outer plot area." + }, + "marginLeft": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s left margin; the minimum distance in pixels between the left edges of the inner and outer plot area." + }, + "marginRight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s right margin; the minimum distance in pixels between the right edges of the mark’s inner and outer plot area." + }, + "marginTop": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s top margin; the minimum distance in pixels between the top edges of the inner and outer plot area." + }, + "mark": { + "const": "ruleY", + "description": "A vertically-positioned ruleY mark (a horizontal line, —). The **y** channel specifies the rule's vertical position and defaults to identity, assuming that *data* = [*y₀*, *y₁*, *y₂*, …]; the optional **x1** and\n**x2** channels specify its horizontal extent.\n\nThe ruleY mark is often used to highlight specific *y* values. If *x* represents ordinal values, use a tickY mark instead.", + "type": "string" + }, + "marker": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for markerStart, markerMid, and markerEnd; one of:\n\n- a marker name such as *arrow* or *circle*\n- *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*" + }, + "markerEnd": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The marker for the ending point of a line segment; one of:\n\n- a marker name such as *arrow* or *circle*\n* *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*" + }, + "markerMid": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The marker for any middle (interior) points of a line segment. If the line segment only has a start and end point, this option has no effect. One of:\n\n- a marker name such as *arrow* or *circle*\n* *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*\n* a function - a custom marker function; see below" + }, + "markerStart": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The marker for the starting point of a line segment; one of:\n\n- a marker name such as *arrow* or *circle*\n* *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*" + }, + "mixBlendMode": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [mix-blend-mode][1]; a constant string specifying how to blend content such as *multiply*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode" + }, + "opacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally. For faster rendering, prefer the **strokeOpacity** or **fillOpacity** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/opacity" + }, + "paintOrder": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [paint-order][1]; a constant string specifying the order in which the\n**fill**, **stroke**, and any markers are drawn; defaults to *normal*, which draws the fill, then stroke, then markers; defaults to *stroke* for the text mark to create a “halo” around text to improve legibility.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/paint-order" + }, + "pointerEvents": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [pointer-events][1] property; a constant string such as *none*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/pointer-events" + }, + "reverse": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Applies a transform to reverse the order of the mark’s index, say for reverse input order." + }, + "select": { + "$ref": "#/definitions/SelectFilter", + "description": "Applies a filter transform after data is loaded to highlight selected values only. For example, `first` and `last` select the first or last values of series only (using the *z* channel to separate series). Meanwhile, `nearestX` and `nearestY` select the point nearest to the pointer along the *x* or *y* channel dimension. Unlike Mosaic selections, a mark level *select* is internal to the mark only, and does not populate a param or selection value to be shared across clients.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "shapeRendering": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [shape-rendering][1]; a constant string such as *crispEdges*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/shape-rendering" + }, + "sort": { + "anyOf": [ + { + "$ref": "#/definitions/SortOrder" + }, + { + "$ref": "#/definitions/ChannelDomainSort" + } + ], + "description": "Either applies a transform to sort the mark’s index by the specified channel values, or imputes ordinal scale domains from this mark’s channels.\n\nWhen imputing ordinal scale domains from channel values, the **sort** option is an object whose keys are ordinal scale names such as *x* or *fx*, and whose values are channel names such as *y*, *y1*, or *y2*. For example, to impute the *y* scale’s domain from the associated *x* channel values in ascending order:\n\n```js sort: {y: \"x\"} ```\n\nFor different sort options for different scales, replace the channel name with a *value* object and per-scale options:\n\n```js sort: {y: {value: \"-x\"}} ```\n\nWhen sorting the mark’s index, the **sort** option is instead one of:\n\n- a channel value definition for sorting given values in ascending order\n- a {value, order} object for sorting given values\n- a {channel, order} object for sorting the named channel’s values" + }, + "stroke": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke" + }, + "strokeDasharray": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dasharray][1]; a constant number indicating the length in pixels of alternating dashes and gaps, or a constant string of numbers separated by spaces or commas (_e.g._, *10 2* for dashes of 10 pixels separated by gaps of 2 pixels), or *none* (the default) for no dashing\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dasharray" + }, + "strokeDashoffset": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dashoffset][1]; a constant indicating the offset in pixels of the first dash along the stroke; defaults to zero.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dashoffset" + }, + "strokeLinecap": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linecap][1]; a constant specifying how to cap stroked paths, such as *butt*, *round*, or *square*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linecap" + }, + "strokeLinejoin": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linejoin][1]; a constant specifying how to join stroked paths, such as *bevel*, *miter*, *miter-clip*, or *round*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linejoin" + }, + "strokeMiterlimit": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-miterlimit][1]; a constant number specifying how to limit the length of *miter* joins on stroked paths.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-miterlimit" + }, + "strokeOpacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-opacity" + }, + "strokeWidth": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-width][1]; a constant number in pixels, or a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-width" + }, + "target": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [target][1]; a constant string specifying the target window (_e.g._,\n*_blank*) for clickable links; used in conjunction with the **href** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/target" + }, + "tip": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/TipPointer" + }, + { + "properties": { + "anchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The tip anchor specifies how to orient the tip box relative to its anchor position; it refers to the part of the tip box that is attached to the anchor point. For example, the *top-left* anchor places the top-left corner of tip box near the anchor position, hence placing the tip box below and to the right of the anchor position." + }, + "fontFamily": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font-family][1]; a constant; defaults to the plot’s font family, which is typically [*system-ui*][2].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-family [2]: https://drafts.csswg.org/css-fonts-4/#valdef-font-family-system-ui" + }, + "fontSize": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font size][1] in pixels; either a constant or a channel; defaults to the plot’s font size, which is typically 10. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-size" + }, + "fontStyle": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font style][1]; a constant; defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-style" + }, + "fontVariant": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font variant][1]; a constant; if the **text** channel contains numbers or dates, defaults to *tabular-nums* to facilitate comparing numbers; otherwise defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant" + }, + "fontWeight": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font weight][1]; a constant; defaults to the plot’s font weight, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight" + }, + "format": { + "additionalProperties": false, + "description": "How channel values are formatted for display. If a format is a string, it is interpreted as a (UTC) time format for temporal channels, and otherwise a number format.", + "properties": { + "ariaLabel": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fill": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fillOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fontSize": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fx": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fy": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "geometry": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "height": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "href": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "length": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "opacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "path": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "r": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "rotate": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "src": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "stroke": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeWidth": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "symbol": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "text": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "title": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "weight": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "width": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "z": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + } + }, + "type": "object" + }, + "frameAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The frame anchor specifies defaults for **x** and **y** based on the plot’s frame; it may be one of the four sides (*top*, *right*, *bottom*, *left*), one of the four corners (*top-left*, *top-right*, *bottom-right*,\n*bottom-left*), or the *middle* of the frame. For example, for tips distributed horizontally at the top of the frame:\n\n```js Plot.tip(data, {x: \"date\", frameAnchor: \"top\"}) ```" + }, + "lineHeight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line height in ems; defaults to 1. The line height affects the (typically vertical) separation between adjacent baselines of text, as well as the separation between the text and its anchor point." + }, + "lineWidth": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line width in ems (e.g., 10 for about 20 characters); defaults to infinity, disabling wrapping and clipping.\n\nIf **textOverflow** is null, lines will be wrapped at the specified length. If a line is split at a soft hyphen (\\xad), a hyphen (-) will be displayed at the end of the line. If **textOverflow** is not null, lines will be clipped according to the given strategy." + }, + "monospace": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, changes the default **fontFamily** to *monospace*, and uses simplified monospaced text metrics calculations." + }, + "pathFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The image filter for the tip’s box; defaults to a drop shadow." + }, + "pointer": { + "$ref": "#/definitions/TipPointer" + }, + "pointerSize": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The size of the tip’s pointer in pixels; defaults to 12." + }, + "preferredAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If an explicit tip anchor is not specified, an anchor is chosen automatically such that the tip fits within the plot’s frame; if the preferred anchor fits, it is chosen." + }, + "textAnchor": { + "anyOf": [ + { + "const": "start", + "type": "string" + }, + { + "const": "middle", + "type": "string" + }, + { + "const": "end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [text anchor][1] controls how text is aligned (typically horizontally) relative to its anchor point; it is one of *start*, *end*, or *middle*. If the frame anchor is *left*, *top-left*, or *bottom-left*, the default text anchor is *start*; if the frame anchor is *right*, *top-right*, or\n*bottom-right*, the default is *end*; otherwise it is *middle*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/text-anchor" + }, + "textOverflow": { + "anyOf": [ + { + "type": "null" + }, + { + "const": "clip", + "type": "string" + }, + { + "const": "ellipsis", + "type": "string" + }, + { + "const": "clip-start", + "type": "string" + }, + { + "const": "clip-end", + "type": "string" + }, + { + "const": "ellipsis-start", + "type": "string" + }, + { + "const": "ellipsis-middle", + "type": "string" + }, + { + "const": "ellipsis-end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How truncate (or wrap) lines of text longer than the given **lineWidth**; one of:\n\n- null (default) - preserve overflowing characters (and wrap if needed)\n- *clip* or *clip-end* - remove characters from the end\n- *clip-start* - remove characters from the start\n- *ellipsis* or *ellipsis-end* - replace characters from the end with an ellipsis (…)\n- *ellipsis-start* - replace characters from the start with an ellipsis (…)\n- *ellipsis-middle* - replace characters from the middle with an ellipsis (…)\n\nIf no **title** was specified, if text requires truncation, a title containing the non-truncated text will be implicitly added." + }, + "textPadding": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The padding around the text in pixels; defaults to 8." + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + } + }, + "type": "object" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to generate a tooltip for this mark, and any tip options." + }, + "title": { + "$ref": "#/definitions/ChannelValue", + "description": "The title; a channel specifying accessible, short textual descriptions as strings (possibly with newlines). If the tip option is specified, the title will be displayed with an interactive tooltip instead of using the SVG [title element][1].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/title" + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position of the tick; an optional channel bound to the *x* scale. If not specified, the rule will be horizontally centered in the plot’s frame." + }, + "y": { + "$ref": "#/definitions/ChannelValueIntervalSpec", + "description": "Shorthand for specifying both the primary and secondary vertical position of the tick as the bounds of the containing interval; can only be used in conjunction with the **interval** option." + }, + "y1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The primary (starting, often bottom) vertical position of the tick; a channel bound to the *y* scale.\n\nIf *y* represents ordinal values, use a tickX mark instead." + }, + "y2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The secondary (ending, often top) vertical position of the tick; a channel bound to the *y* scale.\n\nIf *y* represents ordinal values, use a tickX mark instead." + } + }, + "required": [ + "mark" + ], + "type": "object" + }, + "SQLExpression": { + "additionalProperties": false, + "description": "A custom SQL expression.", + "properties": { + "label": { + "description": "A label for this expression, for example to label a plot axis.", + "type": "string" + }, + "sql": { + "description": "A SQL expression string to derive a new column value. Embedded Param refrences, such as `$param + 1`, are supported. For expressions with aggregate functions, use *agg* instead.", + "type": "string" + } + }, + "required": [ + "sql" + ], + "type": "object" + }, + "ScaleName": { + "description": "The built-in scale names; one of:\n\n- *x* - horizontal position\n- *y* - vertical position\n- *fx* - horizontal facet position\n- *fy* - vertical facet position\n- *r* - radius (for dots and point geos)\n- *color* - color\n- *opacity* - opacity\n- *symbol* - categorical symbol (for dots)\n- *length* - length (for vectors)\n\nPosition scales may have associated axes. Color, opacity, and symbol scales may have an associated legend.", + "enum": [ + "x", + "y", + "fx", + "fy", + "r", + "color", + "opacity", + "symbol", + "length" + ], + "type": "string" + }, + "Search": { + "additionalProperties": false, + "description": "A search input component.", + "properties": { + "as": { + "$ref": "#/definitions/ParamRef", + "description": "The output selection. A selection clause is added for the current text search query." + }, + "column": { + "description": "The name of a database column from which to pull valid search results. The unique column values are used as search autocomplete values. Used in conjunction with the `from` property.", + "type": "string" + }, + "field": { + "description": "The database column name to use within generated selection clause predicates. Defaults to the `column` property.", + "type": "string" + }, + "filterBy": { + "$ref": "#/definitions/ParamRef", + "description": "A selection to filter the database table indicated by the `from` property." + }, + "from": { + "description": "The name of a database table to use as an autocomplete data source for this widget. Used in conjunction with the `column` property.", + "type": "string" + }, + "input": { + "const": "search", + "description": "A text search input widget.", + "type": "string" + }, + "label": { + "description": "A text label for this input.", + "type": "string" + }, + "type": { + "description": "The type of text search query to perform. One of:\n- `\"contains\"` (default): the query string may appear anywhere in the text\n- `\"prefix\"`: the query string must appear at the start of the text\n- `\"suffix\"`: the query string must appear at the end of the text\n- `\"regexp\"`: the query string is a regular expression the text must match", + "enum": [ + "contains", + "prefix", + "suffix", + "regexp" + ], + "type": "string" + } + }, + "required": [ + "input" + ], + "type": "object" + }, + "SelectFilter": { + "description": "Selection filters to apply internally to mark data.", + "enum": [ + "first", + "last", + "maxX", + "maxY", + "minX", + "minY", + "nearest", + "nearestX", + "nearestY" + ], + "type": "string" + }, + "Selection": { + "additionalProperties": false, + "description": "A Selection definition.", + "properties": { + "cross": { + "description": "A flag for cross-filtering, where selections made in a plot filter others but not oneself (default `false`, except for `crossfilter` selections).", + "type": "boolean" + }, + "empty": { + "description": "A flag for setting an initial empty selection state. If true, a selection with no clauses corresponds to an empty selection with no records. If false, a selection with no clauses selects all values.", + "type": "boolean" + }, + "select": { + "description": "The type of reactive parameter. One of:\n- `\"value\"` (default) for a standard `Param`\n- `\"intersect\"` for a `Selection` that intersects clauses (logical \"and\")\n- `\"union\"` for a `Selection` that unions clauses (logical \"or\")\n- `\"single\"` for a `Selection` that retains a single clause only\n- `\"crossfilter\"` for a cross-filtered intersection `Selection`", + "enum": [ + "crossfilter", + "intersect", + "single", + "union" + ], + "type": "string" + } + }, + "required": [ + "select" + ], + "type": "object" + }, + "Slider": { + "additionalProperties": false, + "description": "A slider input component.", + "properties": { + "as": { + "$ref": "#/definitions/ParamRef", + "description": "The output selection. A selection clause is added for the currently selected slider option." + }, + "column": { + "description": "The name of a database column whose values determine the slider range. Used in conjunction with the `from` property. The minimum and maximum values of the column determine the slider range.", + "type": "string" + }, + "field": { + "description": "The database column name to use within generated selection clause predicates. Defaults to the `column` property.", + "type": "string" + }, + "filterBy": { + "$ref": "#/definitions/ParamRef", + "description": "A selection to filter the database table indicated by the `from` property." + }, + "from": { + "description": "The name of a database table to use as a data source for this widget. Used in conjunction with the `column` property. The minimum and maximum values of the column determine the slider range.", + "type": "string" + }, + "input": { + "const": "slider", + "description": "A slider input widget.", + "type": "string" + }, + "label": { + "description": "A text label for this input.", + "type": "string" + }, + "max": { + "description": "The maximum slider value.", + "type": "number" + }, + "min": { + "description": "The minumum slider value.", + "type": "number" + }, + "select": { + "description": "The type of selection clause predicate to generate if the **as** option is a Selection. If `'point'` (the default), the selection predicate is an equality check for the slider value. If `'interval'`, the predicate checks an interval from the minimum to the current slider value.", + "enum": [ + "point", + "interval" + ], + "type": "string" + }, + "step": { + "description": "The slider step, the amount to increment between consecutive values.", + "type": "number" + }, + "value": { + "description": "The initial slider value.", + "type": "number" + }, + "width": { + "description": "The width of the slider in screen pixels.", + "type": "number" + } + }, + "required": [ + "input" + ], + "type": "object" + }, + "SortOrder": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "additionalProperties": false, + "properties": { + "order": { + "enum": [ + "ascending", + "descending" + ], + "type": "string" + }, + "value": { + "$ref": "#/definitions/ChannelValue" + } + }, + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "channel": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelName" + }, + { + "const": "-ariaLabel", + "type": "string" + }, + { + "const": "-fill", + "type": "string" + }, + { + "const": "-fillOpacity", + "type": "string" + }, + { + "const": "-fontSize", + "type": "string" + }, + { + "const": "-fx", + "type": "string" + }, + { + "const": "-fy", + "type": "string" + }, + { + "const": "-geometry", + "type": "string" + }, + { + "const": "-height", + "type": "string" + }, + { + "const": "-href", + "type": "string" + }, + { + "const": "-length", + "type": "string" + }, + { + "const": "-opacity", + "type": "string" + }, + { + "const": "-path", + "type": "string" + }, + { + "const": "-r", + "type": "string" + }, + { + "const": "-rotate", + "type": "string" + }, + { + "const": "-src", + "type": "string" + }, + { + "const": "-stroke", + "type": "string" + }, + { + "const": "-strokeOpacity", + "type": "string" + }, + { + "const": "-strokeWidth", + "type": "string" + }, + { + "const": "-symbol", + "type": "string" + }, + { + "const": "-text", + "type": "string" + }, + { + "const": "-title", + "type": "string" + }, + { + "const": "-weight", + "type": "string" + }, + { + "const": "-width", + "type": "string" + }, + { + "const": "-x", + "type": "string" + }, + { + "const": "-x1", + "type": "string" + }, + { + "const": "-x2", + "type": "string" + }, + { + "const": "-y", + "type": "string" + }, + { + "const": "-y1", + "type": "string" + }, + { + "const": "-y2", + "type": "string" + }, + { + "const": "-z", + "type": "string" + } + ] + }, + "order": { + "enum": [ + "ascending", + "descending" + ], + "type": "string" + } + }, + "type": "object" + } + ], + "description": "How to order values; one of:\n\n- a function for comparing data, returning a signed number\n- a channel value definition for sorting given values in ascending order\n- a {value, order} object for sorting given values\n- a {channel, order} object for sorting the named channel’s values" + }, + "Spec": { + "anyOf": [ + { + "additionalProperties": false, + "properties": { + "$schema": { + "description": "A [JSON schema](http://json-schema.org/) URL for this specification, such as https://uwdata.github.io/mosaic/schema/latest.json. This property enables validation and autocomplete in editors with JSON schema support.", + "format": "uri", + "type": "string" + }, + "config": { + "$ref": "#/definitions/Config", + "description": "Configuration options." + }, + "data": { + "$ref": "#/definitions/Data", + "description": "Dataset definitions." + }, + "hconcat": { + "description": "Horizontally concatenate components in a row layout.", + "items": { + "$ref": "#/definitions/Component" + }, + "type": "array" + }, + "meta": { + "$ref": "#/definitions/Meta", + "description": "Specification metadata." + }, + "params": { + "$ref": "#/definitions/Params", + "description": "Param and Selection definitions." + }, + "plotDefaults": { + "$ref": "#/definitions/PlotAttributes", + "description": "A default set of attributes to apply to all plot components." + } + }, + "required": [ + "hconcat" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "$schema": { + "description": "A [JSON schema](http://json-schema.org/) URL for this specification, such as https://uwdata.github.io/mosaic/schema/latest.json. This property enables validation and autocomplete in editors with JSON schema support.", + "format": "uri", + "type": "string" + }, + "config": { + "$ref": "#/definitions/Config", + "description": "Configuration options." + }, + "data": { + "$ref": "#/definitions/Data", + "description": "Dataset definitions." + }, + "meta": { + "$ref": "#/definitions/Meta", + "description": "Specification metadata." + }, + "params": { + "$ref": "#/definitions/Params", + "description": "Param and Selection definitions." + }, + "plotDefaults": { + "$ref": "#/definitions/PlotAttributes", + "description": "A default set of attributes to apply to all plot components." + }, + "vconcat": { + "description": "Vertically concatenate components in a column layout.", + "items": { + "$ref": "#/definitions/Component" + }, + "type": "array" + } + }, + "required": [ + "vconcat" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "$schema": { + "description": "A [JSON schema](http://json-schema.org/) URL for this specification, such as https://uwdata.github.io/mosaic/schema/latest.json. This property enables validation and autocomplete in editors with JSON schema support.", + "format": "uri", + "type": "string" + }, + "config": { + "$ref": "#/definitions/Config", + "description": "Configuration options." + }, + "data": { + "$ref": "#/definitions/Data", + "description": "Dataset definitions." + }, + "hspace": { + "description": "Horizontal space to place between components. Number values indicate screen pixels. String values may use CSS units (em, pt, px, etc).", + "type": [ + "number", + "string" + ] + }, + "meta": { + "$ref": "#/definitions/Meta", + "description": "Specification metadata." + }, + "params": { + "$ref": "#/definitions/Params", + "description": "Param and Selection definitions." + }, + "plotDefaults": { + "$ref": "#/definitions/PlotAttributes", + "description": "A default set of attributes to apply to all plot components." + } + }, + "required": [ + "hspace" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "$schema": { + "description": "A [JSON schema](http://json-schema.org/) URL for this specification, such as https://uwdata.github.io/mosaic/schema/latest.json. This property enables validation and autocomplete in editors with JSON schema support.", + "format": "uri", + "type": "string" + }, + "config": { + "$ref": "#/definitions/Config", + "description": "Configuration options." + }, + "data": { + "$ref": "#/definitions/Data", + "description": "Dataset definitions." + }, + "meta": { + "$ref": "#/definitions/Meta", + "description": "Specification metadata." + }, + "params": { + "$ref": "#/definitions/Params", + "description": "Param and Selection definitions." + }, + "plotDefaults": { + "$ref": "#/definitions/PlotAttributes", + "description": "A default set of attributes to apply to all plot components." + }, + "vspace": { + "description": "Vertical space to place between components. Number values indicate screen pixels. String values may use CSS units (em, pt, px, etc).", + "type": [ + "number", + "string" + ] + } + }, + "required": [ + "vspace" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "$schema": { + "description": "A [JSON schema](http://json-schema.org/) URL for this specification, such as https://uwdata.github.io/mosaic/schema/latest.json. This property enables validation and autocomplete in editors with JSON schema support.", + "format": "uri", + "type": "string" + }, + "as": { + "$ref": "#/definitions/ParamRef", + "description": "The output selection. A selection clause is added for the currently selected menu option." + }, + "column": { + "description": "The name of a database column from which to pull menu options. The unique column values are used as menu options. Used in conjunction with the `from` property.", + "type": "string" + }, + "config": { + "$ref": "#/definitions/Config", + "description": "Configuration options." + }, + "data": { + "$ref": "#/definitions/Data", + "description": "Dataset definitions." + }, + "field": { + "description": "The database column name to use within generated selection clause predicates. Defaults to the `column` property.", + "type": "string" + }, + "filterBy": { + "$ref": "#/definitions/ParamRef", + "description": "A selection to filter the database table indicated by the `from` property." + }, + "from": { + "description": "The name of a database table to use as a data source for this widget. Used in conjunction with the `column` property.", + "type": "string" + }, + "input": { + "const": "menu", + "description": "A menu input widget.", + "type": "string" + }, + "label": { + "description": "A text label for this input.", + "type": "string" + }, + "meta": { + "$ref": "#/definitions/Meta", + "description": "Specification metadata." + }, + "options": { + "description": "An array of menu options, as literal values or option objects. Option objects have a `value` property and an optional `label` property. If no label is provided, the string-coerced value is used.", + "items": { + "anyOf": [ + {}, + { + "additionalProperties": false, + "properties": { + "label": { + "type": "string" + }, + "value": {} + }, + "required": [ + "value" + ], + "type": "object" + } + ] + }, + "type": "array" + }, + "params": { + "$ref": "#/definitions/Params", + "description": "Param and Selection definitions." + }, + "plotDefaults": { + "$ref": "#/definitions/PlotAttributes", + "description": "A default set of attributes to apply to all plot components." + }, + "value": { + "description": "The initial selected menu value." + } + }, + "required": [ + "input" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "$schema": { + "description": "A [JSON schema](http://json-schema.org/) URL for this specification, such as https://uwdata.github.io/mosaic/schema/latest.json. This property enables validation and autocomplete in editors with JSON schema support.", + "format": "uri", + "type": "string" + }, + "as": { + "$ref": "#/definitions/ParamRef", + "description": "The output selection. A selection clause is added for the current text search query." + }, + "column": { + "description": "The name of a database column from which to pull valid search results. The unique column values are used as search autocomplete values. Used in conjunction with the `from` property.", + "type": "string" + }, + "config": { + "$ref": "#/definitions/Config", + "description": "Configuration options." + }, + "data": { + "$ref": "#/definitions/Data", + "description": "Dataset definitions." + }, + "field": { + "description": "The database column name to use within generated selection clause predicates. Defaults to the `column` property.", + "type": "string" + }, + "filterBy": { + "$ref": "#/definitions/ParamRef", + "description": "A selection to filter the database table indicated by the `from` property." + }, + "from": { + "description": "The name of a database table to use as an autocomplete data source for this widget. Used in conjunction with the `column` property.", + "type": "string" + }, + "input": { + "const": "search", + "description": "A text search input widget.", + "type": "string" + }, + "label": { + "description": "A text label for this input.", + "type": "string" + }, + "meta": { + "$ref": "#/definitions/Meta", + "description": "Specification metadata." + }, + "params": { + "$ref": "#/definitions/Params", + "description": "Param and Selection definitions." + }, + "plotDefaults": { + "$ref": "#/definitions/PlotAttributes", + "description": "A default set of attributes to apply to all plot components." + }, + "type": { + "description": "The type of text search query to perform. One of:\n- `\"contains\"` (default): the query string may appear anywhere in the text\n- `\"prefix\"`: the query string must appear at the start of the text\n- `\"suffix\"`: the query string must appear at the end of the text\n- `\"regexp\"`: the query string is a regular expression the text must match", + "enum": [ + "contains", + "prefix", + "suffix", + "regexp" + ], + "type": "string" + } + }, + "required": [ + "input" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "$schema": { + "description": "A [JSON schema](http://json-schema.org/) URL for this specification, such as https://uwdata.github.io/mosaic/schema/latest.json. This property enables validation and autocomplete in editors with JSON schema support.", + "format": "uri", + "type": "string" + }, + "as": { + "$ref": "#/definitions/ParamRef", + "description": "The output selection. A selection clause is added for the currently selected slider option." + }, + "column": { + "description": "The name of a database column whose values determine the slider range. Used in conjunction with the `from` property. The minimum and maximum values of the column determine the slider range.", + "type": "string" + }, + "config": { + "$ref": "#/definitions/Config", + "description": "Configuration options." + }, + "data": { + "$ref": "#/definitions/Data", + "description": "Dataset definitions." + }, + "field": { + "description": "The database column name to use within generated selection clause predicates. Defaults to the `column` property.", + "type": "string" + }, + "filterBy": { + "$ref": "#/definitions/ParamRef", + "description": "A selection to filter the database table indicated by the `from` property." + }, + "from": { + "description": "The name of a database table to use as a data source for this widget. Used in conjunction with the `column` property. The minimum and maximum values of the column determine the slider range.", + "type": "string" + }, + "input": { + "const": "slider", + "description": "A slider input widget.", + "type": "string" + }, + "label": { + "description": "A text label for this input.", + "type": "string" + }, + "max": { + "description": "The maximum slider value.", + "type": "number" + }, + "meta": { + "$ref": "#/definitions/Meta", + "description": "Specification metadata." + }, + "min": { + "description": "The minumum slider value.", + "type": "number" + }, + "params": { + "$ref": "#/definitions/Params", + "description": "Param and Selection definitions." + }, + "plotDefaults": { + "$ref": "#/definitions/PlotAttributes", + "description": "A default set of attributes to apply to all plot components." + }, + "select": { + "description": "The type of selection clause predicate to generate if the **as** option is a Selection. If `'point'` (the default), the selection predicate is an equality check for the slider value. If `'interval'`, the predicate checks an interval from the minimum to the current slider value.", + "enum": [ + "point", + "interval" + ], + "type": "string" + }, + "step": { + "description": "The slider step, the amount to increment between consecutive values.", + "type": "number" + }, + "value": { + "description": "The initial slider value.", + "type": "number" + }, + "width": { + "description": "The width of the slider in screen pixels.", + "type": "number" + } + }, + "required": [ + "input" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "$schema": { + "description": "A [JSON schema](http://json-schema.org/) URL for this specification, such as https://uwdata.github.io/mosaic/schema/latest.json. This property enables validation and autocomplete in editors with JSON schema support.", + "format": "uri", + "type": "string" + }, + "align": { + "additionalProperties": { + "enum": [ + "left", + "right", + "center", + "justify" + ], + "type": "string" + }, + "description": "An object of per-column alignment values. Column names should be object keys, which map to alignment values. Valid alignment values are: `\"left\"`, `\"right\"`, `\"center\"`, and `\"justify\"`. By default, numbers are right-aligned and other values are left-aligned.", + "type": "object" + }, + "as": { + "$ref": "#/definitions/ParamRef", + "description": "The output selection. A selection clause is added for each currently selected table row." + }, + "columns": { + "description": "A list of column names to include in the table grid. If unspecified, all table columns are included.", + "items": { + "type": "string" + }, + "type": "array" + }, + "config": { + "$ref": "#/definitions/Config", + "description": "Configuration options." + }, + "data": { + "$ref": "#/definitions/Data", + "description": "Dataset definitions." + }, + "filterBy": { + "$ref": "#/definitions/ParamRef", + "description": "A selection to filter the database table indicated by the `from` property." + }, + "from": { + "description": "The name of a database table to use as a data source for this widget.", + "type": "string" + }, + "height": { + "description": "The height of the table widget, in pixels.", + "type": "number" + }, + "input": { + "const": "table", + "description": "A table grid widget.", + "type": "string" + }, + "maxWidth": { + "description": "The maximum width of the table widget, in pixels.", + "type": "number" + }, + "meta": { + "$ref": "#/definitions/Meta", + "description": "Specification metadata." + }, + "params": { + "$ref": "#/definitions/Params", + "description": "Param and Selection definitions." + }, + "plotDefaults": { + "$ref": "#/definitions/PlotAttributes", + "description": "A default set of attributes to apply to all plot components." + }, + "rowBatch": { + "description": "The number of rows load in a new batch upon table scroll.", + "type": "number" + }, + "width": { + "anyOf": [ + { + "type": "number" + }, + { + "additionalProperties": { + "type": "number" + }, + "type": "object" + } + ], + "description": "If a number, sets the total width of the table widget, in pixels. If an object, provides per-column pixel width values. Column names should be object keys, mapped to numeric width values." + } + }, + "required": [ + "from", + "input" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "$schema": { + "description": "A [JSON schema](http://json-schema.org/) URL for this specification, such as https://uwdata.github.io/mosaic/schema/latest.json. This property enables validation and autocomplete in editors with JSON schema support.", + "format": "uri", + "type": "string" + }, + "align": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to distribute unused space in the **range** for *point* and *band* scales. A number in [0, 1], such as:\n\n- 0 - use the start of the range, putting unused space at the end\n- 0.5 (default) - use the middle, distributing unused space evenly\n- 1 use the end, putting unused space at the start\n\nFor ordinal position scales only." + }, + "aspectRatio": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The desired aspect ratio of the *x* and *y* scales, affecting the default height. Given an aspect ratio of *dx* / *dy*, and assuming that the *x* and\n*y* scales represent equivalent units (say, degrees Celsius or meters), computes a default height such that *dx* pixels along *x* represents the same variation as *dy* pixels along *y*. Note: when faceting, set the *fx* and *fy* scales’ **round** option to false for an exact aspect ratio." + }, + "axis": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "right", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "const": "left", + "type": "string" + }, + { + "const": "both", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The side of the frame on which to place the implicit axis: *top* or\n*bottom* for *x* or *fx*, or *left* or *right* for *y* or *fy*. The default depends on the scale:\n\n- *x* - *bottom*\n- *y* - *left*\n- *fx* - *top* if there is a *bottom* *x* axis, and otherwise *bottom*\n- *fy* - *right* if there is a *left* *y* axis, and otherwise *right*\n\nIf *both*, an implicit axis will be rendered on both sides of the plot (*top* and *bottom* for *x* or *fx*, or *left* and *right* for *y* or\n*fy*). If null, the implicit axis is suppressed.\n\nFor position axes only." + }, + "colorBase": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A log scale’s base; defaults to 10. Does not affect the scale’s encoding, but rather the default ticks. For *log* and *diverging-log* scales only." + }, + "colorClamp": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, values below the domain minimum are treated as the domain minimum, and values above the domain maximum are treated as the domain maximum.\n\nClamping is useful for focusing on a subset of the data while ensuring that extreme values remain visible, but use caution: clamped values may need an annotation to avoid misinterpretation. Clamping typically requires setting an explicit **domain** since if the domain is inferred, no values will be outside the domain.\n\nFor continuous scales only." + }, + "colorConstant": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A symlog scale’s constant, expressing the magnitude of the linear region around the origin; defaults to 1. For *symlog* and *diverging-symlog* scales only." + }, + "colorDomain": { + "anyOf": [ + { + "items": {}, + "type": "array" + }, + { + "$ref": "#/definitions/Fixed" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The extent of the scale’s inputs (abstract values). By default inferred from channel values. For continuous data (numbers and dates), it is typically [*min*, *max*]; it can be [*max*, *min*] to reverse the scale. For ordinal data (strings or booleans), it is an array (or iterable) of values is the desired order, defaulting to natural ascending order." + }, + "colorExponent": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A power scale’s exponent (*e.g.*, 0.5 for sqrt); defaults to 1 for a linear scale. For *pow* and *diverging-pow* scales only." + }, + "colorInterpolate": { + "anyOf": [ + { + "$ref": "#/definitions/Interpolate" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to interpolate color range values. For quantitative scales only. This attribute can be used to specify a color space for interpolating colors specified in the **colorRange**." + }, + "colorLabel": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A textual label to show on the axis or legend; if null, show no label. By default the scale label is inferred from channel definitions, possibly with an arrow (↑, →, ↓, or ←) to indicate the direction of increasing value.\n\nFor axes and legends only." + }, + "colorN": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "For a *quantile* scale, the number of quantiles (creates *n* - 1 thresholds); for a *quantize* scale, the approximate number of thresholds; defaults to 5." + }, + "colorNice": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/Interval" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, or a tick count or interval, extend the domain to nice round values. Defaults to 1, 2 or 5 times a power of 10 for *linear* scales, and nice time intervals for *utc* and *time* scales. Pass an interval such as\n*minute*, *wednesday* or *month* to specify what constitutes a nice interval.\n\nFor continuous scales only." + }, + "colorPercent": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, shorthand for a transform suitable for percentages, mapping proportions in [0, 1] to [0, 100]." + }, + "colorPivot": { + "anyOf": [ + {}, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "For a diverging color scale, the input value (abstract value) that divides the domain into two parts; defaults to 0 for *diverging* scales, dividing the domain into negative and positive parts; defaults to 1 for\n*diverging-log* scales. By default, diverging scales are symmetric around the pivot; see the **symmetric** option." + }, + "colorRange": { + "anyOf": [ + { + "items": {}, + "type": "array" + }, + { + "$ref": "#/definitions/Fixed" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The extent of the scale’s outputs (visual values). By default inferred from the scale’s **type** and **domain**. For other ordinal data, it is an array (or iterable) of output values in the same order as the **domain**." + }, + "colorReverse": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to reverse the scale’s encoding; equivalent to reversing either the\n**domain** or **range**." + }, + "colorScale": { + "anyOf": [ + { + "$ref": "#/definitions/ColorScaleType" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The *color* scale type, affecting how the scale encodes abstract data, say by applying a mathematical transformation. If null, the scale is disabled.\n\nFor quantitative data (numbers), defaults to *linear*; for temporal data (dates), defaults to *utc*; for ordinal data (strings or booleans), defaults to *point* for position scales, *categorical* for color scales, and otherwise *ordinal*." + }, + "colorScheme": { + "anyOf": [ + { + "$ref": "#/definitions/ColorScheme" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If specified, shorthand for setting the **colorRange** or **colorInterpolate** option of a *color* scale." + }, + "colorSymmetric": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "For a diverging color scale, if true (the default), extend the domain to ensure that the lower part of the domain (below the **pivot**) is commensurate with the upper part of the domain (above the **pivot**).\n\nA symmetric diverging color scale may not use all of its output **range**; this reduces contrast but ensures that deviations both below and above the\n**pivot** are represented proportionally. Otherwise if false, the full output **range** will be used; this increases contrast but values on opposite sides of the **pivot** may not be meaningfully compared." + }, + "colorTickFormat": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to format inputs (abstract values) for axis tick labels; one of:\n\n- a [d3-format][1] string for numeric scales\n- a [d3-time-format][2] string for temporal scales\n\n[1]: https://d3js.org/d3-time [2]: https://d3js.org/d3-time-format" + }, + "colorZero": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether the **domain** must include zero. If the domain minimum is positive, it will be set to zero; otherwise if the domain maximum is negative, it will be set to zero.\n\nFor quantitative scales only." + }, + "config": { + "$ref": "#/definitions/Config", + "description": "Configuration options." + }, + "data": { + "$ref": "#/definitions/Data", + "description": "Dataset definitions." + }, + "facetGrid": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/Interval" + }, + { + "items": {}, + "type": "array" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Default axis grid for fx and fy scales; typically set to true to enable." + }, + "facetLabel": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Default axis label for fx and fy scales; typically set to null to disable." + }, + "facetMargin": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four facet margins: marginTop, marginRight, marginBottom, and marginLeft." + }, + "facetMarginBottom": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The right facet margin; the (minimum) distance in pixels between the right edges of the inner and outer plot area." + }, + "facetMarginLeft": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The bottom facet margin; the (minimum) distance in pixels between the bottom edges of the inner and outer plot area." + }, + "facetMarginRight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The left facet margin; the (minimum) distance in pixels between the left edges of the inner and outer plot area." + }, + "facetMarginTop": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The top facet margin; the (minimum) distance in pixels between the top edges of the inner and outer plot area." + }, + "fxAlign": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to distribute unused space in the **range** for *point* and *band* scales. A number in [0, 1], such as:\n\n- 0 - use the start of the range, putting unused space at the end\n- 0.5 (default) - use the middle, distributing unused space evenly\n- 1 use the end, putting unused space at the start\n\nFor ordinal position scales only." + }, + "fxAriaDescription": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A textual description for the axis in the accessibility tree." + }, + "fxAriaLabel": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A short label representing the axis in the accessibility tree." + }, + "fxAxis": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "const": "both", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The side of the frame on which to place the implicit axis: *top* or\n*bottom* for *fx*. Defaults to *top* if there is a *bottom* *x* axis, and otherwise *bottom*.\n\nIf *both*, an implicit axis will be rendered on both sides of the plot (*top* and *bottom* for *fx*). If null, the implicit axis is suppressed." + }, + "fxDomain": { + "anyOf": [ + { + "items": {}, + "type": "array" + }, + { + "$ref": "#/definitions/Fixed" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The extent of the scale’s inputs (abstract values). By default inferred from channel values. For ordinal data (strings or booleans), it is an array (or iterable) of values is the desired order, defaulting to natural ascending order." + }, + "fxFontVariant": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The font-variant attribute for axis ticks; defaults to *tabular-nums* for quantitative axes." + }, + "fxGrid": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/Interval" + }, + { + "items": {}, + "type": "array" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to show a grid aligned with the scale’s ticks. If true, show a grid with the currentColor stroke; if a string, show a grid with the specified stroke color; if an approximate number of ticks, an interval, or an array of tick values, show corresponding grid lines. See also the grid mark.\n\nFor axes only." + }, + "fxInset": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four insets: **insetTop**,\n**insetRight**, **insetBottom**, and **insetLeft**. All insets typically default to zero, though not always (say when using bin transform). A positive inset reduces effective area, while a negative inset increases it." + }, + "fxInsetLeft": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Insets the left edge by the specified number of pixels. A positive value insets towards the right edge (reducing effective area), while a negative value insets away from the right edge (increasing it)." + }, + "fxInsetRight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Insets the right edge by the specified number of pixels. A positive value insets towards the left edge (reducing effective area), while a negative value insets away from the left edge (increasing it)." + }, + "fxLabel": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A textual label to show on the axis or legend; if null, show no label. By default the scale label is inferred from channel definitions, possibly with an arrow (↑, →, ↓, or ←) to indicate the direction of increasing value.\n\nFor axes and legends only." + }, + "fxLabelAnchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "right", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "const": "left", + "type": "string" + }, + { + "const": "center", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Where to place the axis **label** relative to the plot’s frame. For vertical position scales (*y* and *fy*), may be *top*, *bottom*, or\n*center*; for horizontal position scales (*x* and *fx*), may be *left*,\n*right*, or *center*. Defaults to *center* for ordinal scales (including\n*fx* and *fy*), and otherwise *top* for *y*, and *right* for *x*." + }, + "fxLabelOffset": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The axis **label** position offset (in pixels); default depends on margins and orientation." + }, + "fxLine": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, draw a line along the axis; if false (default), do not." + }, + "fxPadding": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "For *band* scales, how much of the **range** to reserve to separate adjacent bands; defaults to 0.1 (10%). For *point* scales, the amount of inset for the first and last value as a proportion of the bandwidth; defaults to 0.5 (50%).\n\nFor ordinal position scales only." + }, + "fxPaddingInner": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "For a *band* scale, how much of the range to reserve to separate adjacent bands." + }, + "fxPaddingOuter": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "For a *band* scale, how much of the range to reserve to inset first and last bands." + }, + "fxRange": { + "anyOf": [ + { + "items": {}, + "type": "array" + }, + { + "$ref": "#/definitions/Fixed" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The extent of the scale’s outputs (visual values). By default inferred from the scale’s **type** and **domain**, and the plot’s dimensions. For ordinal position scales (*point* and *band*), it is typically [*min*, *max*]; it can be [*max*, *min*] to reverse the scale." + }, + "fxReverse": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to reverse the scale’s encoding; equivalent to reversing either the\n**domain** or **range**." + }, + "fxRound": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, round the output value to the nearest integer (pixel); useful for crisp edges when rendering.\n\nFor position scales only." + }, + "fxTickFormat": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to format inputs (abstract values) for axis tick labels; one of:\n\n- a [d3-format][1] string for numeric scales\n- a [d3-time-format][2] string for temporal scales\n\n[1]: https://d3js.org/d3-time [2]: https://d3js.org/d3-time-format" + }, + "fxTickPadding": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The distance between an axis tick mark and its associated text label (in pixels); often defaults to 3, but may be affected by **fxTickSize** and\n**fxTickRotate**." + }, + "fxTickRotate": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The rotation angle of axis tick labels in degrees clocksize; defaults to 0." + }, + "fxTickSize": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The length of axis tick marks in pixels; negative values extend in the opposite direction. Defaults to 6 for *x* and *y* axes and *color* and\n*opacity* *ramp* legends, and 0 for *fx* and *fy* axes." + }, + "fxTickSpacing": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The desired approximate spacing between adjacent axis ticks, affecting the default **ticks**; defaults to 80 pixels for *x* and *fx*, and 35 pixels for *y* and *fy*." + }, + "fxTicks": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/Interval" + }, + { + "items": {}, + "type": "array" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The desired approximate number of axis ticks, or an explicit array of tick values, or an interval such as *day* or *month*." + }, + "fyAlign": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to distribute unused space in the **range** for *point* and *band* scales. A number in [0, 1], such as:\n\n- 0 - use the start of the range, putting unused space at the end\n- 0.5 (default) - use the middle, distributing unused space evenly\n- 1 use the end, putting unused space at the start\n\nFor ordinal position scales only." + }, + "fyAriaDescription": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A textual description for the axis in the accessibility tree." + }, + "fyAriaLabel": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A short label representing the axis in the accessibility tree." + }, + "fyAxis": { + "anyOf": [ + { + "const": "left", + "type": "string" + }, + { + "const": "right", + "type": "string" + }, + { + "const": "both", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The side of the frame on which to place the implicit axis: *left* or\n*right* for *fy*. Defaults to *left* for an *fy* scale.\n\nIf *both*, an implicit axis will be rendered on both sides of the plot (*left* and *right* for *fy*). If null, the implicit axis is suppressed." + }, + "fyDomain": { + "anyOf": [ + { + "items": {}, + "type": "array" + }, + { + "$ref": "#/definitions/Fixed" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The extent of the scale’s inputs (abstract values). By default inferred from channel values. For ordinal data (strings or booleans), it is an array (or iterable) of values is the desired order, defaulting to natural ascending order." + }, + "fyFontVariant": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The font-variant attribute for axis ticks; defaults to *tabular-nums* for quantitative axes." + }, + "fyGrid": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/Interval" + }, + { + "items": {}, + "type": "array" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to show a grid aligned with the scale’s ticks. If true, show a grid with the currentColor stroke; if a string, show a grid with the specified stroke color; if an approximate number of ticks, an interval, or an array of tick values, show corresponding grid lines. See also the grid mark.\n\nFor axes only." + }, + "fyInset": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four insets: **insetTop**,\n**insetRight**, **insetBottom**, and **insetLeft**. All insets typically default to zero, though not always (say when using bin transform). A positive inset reduces effective area, while a negative inset increases it." + }, + "fyInsetBottom": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Insets the bottom edge by the specified number of pixels. A positive value insets towards the top edge (reducing effective area), while a negative value insets away from the top edge (increasing it)." + }, + "fyInsetTop": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Insets the top edge by the specified number of pixels. A positive value insets towards the bottom edge (reducing effective area), while a negative value insets away from the bottom edge (increasing it)." + }, + "fyLabel": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A textual label to show on the axis or legend; if null, show no label. By default the scale label is inferred from channel definitions, possibly with an arrow (↑, →, ↓, or ←) to indicate the direction of increasing value.\n\nFor axes and legends only." + }, + "fyLabelAnchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "right", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "const": "left", + "type": "string" + }, + { + "const": "center", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Where to place the axis **label** relative to the plot’s frame. For vertical position scales (*y* and *fy*), may be *top*, *bottom*, or\n*center*; for horizontal position scales (*x* and *fx*), may be *left*,\n*right*, or *center*. Defaults to *center* for ordinal scales (including\n*fx* and *fy*), and otherwise *top* for *y*, and *right* for *x*." + }, + "fyLabelOffset": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The axis **label** position offset (in pixels); default depends on margins and orientation." + }, + "fyLine": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, draw a line along the axis; if false (default), do not." + }, + "fyPadding": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "For *band* scales, how much of the **range** to reserve to separate adjacent bands; defaults to 0.1 (10%). For *point* scales, the amount of inset for the first and last value as a proportion of the bandwidth; defaults to 0.5 (50%).\n\nFor ordinal position scales only." + }, + "fyPaddingInner": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "For a *band* scale, how much of the range to reserve to separate adjacent bands." + }, + "fyPaddingOuter": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "For a *band* scale, how much of the range to reserve to inset first and last bands." + }, + "fyRange": { + "anyOf": [ + { + "items": {}, + "type": "array" + }, + { + "$ref": "#/definitions/Fixed" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The extent of the scale’s outputs (visual values). By default inferred from the scale’s **type** and **domain**, and the plot’s dimensions. For ordinal position scales (*point* and *band*), it is typically [*min*, *max*]; it can be [*max*, *min*] to reverse the scale." + }, + "fyReverse": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to reverse the scale’s encoding; equivalent to reversing either the\n**domain** or **range**." + }, + "fyRound": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, round the output value to the nearest integer (pixel); useful for crisp edges when rendering.\n\nFor position scales only." + }, + "fyTickFormat": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to format inputs (abstract values) for axis tick labels; one of:\n\n- a [d3-format][1] string for numeric scales\n- a [d3-time-format][2] string for temporal scales\n\n[1]: https://d3js.org/d3-time [2]: https://d3js.org/d3-time-format" + }, + "fyTickPadding": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The distance between an axis tick mark and its associated text label (in pixels); often defaults to 3, but may be affected by **fyTickSize** and\n**fyTickRotate**." + }, + "fyTickRotate": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The rotation angle of axis tick labels in degrees clocksize; defaults to 0." + }, + "fyTickSize": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The length of axis tick marks in pixels; negative values extend in the opposite direction. Defaults to 6 for *x* and *y* axes and *color* and\n*opacity* *ramp* legends, and 0 for *fx* and *fy* axes." + }, + "fyTickSpacing": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The desired approximate spacing between adjacent axis ticks, affecting the default **ticks**; defaults to 80 pixels for *x* and *fx*, and 35 pixels for *y* and *fy*." + }, + "fyTicks": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/Interval" + }, + { + "items": {}, + "type": "array" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The desired approximate number of axis ticks, or an explicit array of tick values, or an interval such as *day* or *month*." + }, + "grid": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to show a grid aligned with the scale’s ticks. If true, show a grid with the currentColor stroke; if a string, show a grid with the specified stroke color; if an approximate number of ticks, an interval, or an array of tick values, show corresponding grid lines. See also the grid mark.\n\nFor axes only." + }, + "height": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The outer height of the plot in pixels, including margins. The default depends on the plot’s scales, and the plot’s width if an aspectRatio is specified. For example, if the *y* scale is linear and there is no *fy* scale, it might be 396." + }, + "inset": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four insets: **insetTop**,\n**insetRight**, **insetBottom**, and **insetLeft**. All insets typically default to zero, though not always (say when using bin transform). A positive inset reduces effective area, while a negative inset increases it." + }, + "label": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A textual label to show on the axis or legend; if null, show no label. By default the scale label is inferred from channel definitions, possibly with an arrow (↑, →, ↓, or ←) to indicate the direction of increasing value.\n\nFor axes and legends only." + }, + "lengthBase": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A log scale’s base; defaults to 10. Does not affect the scale’s encoding, but rather the default ticks. For *log* scales only." + }, + "lengthClamp": { + "description": "If true, values below the domain minimum are treated as the domain minimum, and values above the domain maximum are treated as the domain maximum.\n\nClamping is useful for focusing on a subset of the data while ensuring that extreme values remain visible, but use caution: clamped values may need an annotation to avoid misinterpretation. Clamping typically requires setting an explicit **domain** since if the domain is inferred, no values will be outside the domain.\n\nFor continuous scales only." + }, + "lengthConstant": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A symlog scale’s constant, expressing the magnitude of the linear region around the origin; defaults to 1. For *symlog* scales only." + }, + "lengthDomain": { + "anyOf": [ + { + "items": {}, + "type": "array" + }, + { + "$ref": "#/definitions/Fixed" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The extent of the scale’s inputs (abstract values). By default inferred from channel values. For continuous data (numbers and dates), it is typically [*min*, *max*]; it can be [*max*, *min*] to reverse the scale. For ordinal data (strings or booleans), it is an array (or iterable) of values is the desired order, defaulting to natural ascending order.\n\nLinear scales have a default domain of [0, 1]. Log scales have a default domain of [1, 10] and cannot include zero. Radius scales have a default domain from 0 to the median first quartile of associated channels. Length have a default domain from 0 to the median median of associated channels. Opacity scales have a default domain from 0 to the maximum value of associated channels." + }, + "lengthExponent": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A power scale’s exponent (*e.g.*, 0.5 for sqrt); defaults to 1 for a linear scale. For *pow* scales only." + }, + "lengthNice": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/Interval" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, or a tick count or interval, extend the domain to nice round values. Defaults to 1, 2 or 5 times a power of 10 for *linear* scales, and nice time intervals for *utc* and *time* scales. Pass an interval such as\n*minute*, *wednesday* or *month* to specify what constitutes a nice interval.\n\nFor continuous scales only." + }, + "lengthPercent": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, shorthand for a transform suitable for percentages, mapping proportions in [0, 1] to [0, 100]." + }, + "lengthRange": { + "anyOf": [ + { + "items": {}, + "type": "array" + }, + { + "$ref": "#/definitions/Fixed" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The extent of the scale’s outputs (visual values). By default inferred from the scale’s **type** and **domain**, and for position scales, the plot’s dimensions. For continuous data (numbers and dates), and for ordinal position scales (*point* and *band*), it is typically [*min*, *max*]; it can be [*max*, *min*] to reverse the scale. For other ordinal data, such as for a *color* scale, it is an array (or iterable) of output values in the same order as the **domain**.\n\nLength scales have a default range of [0, 12]." + }, + "lengthScale": { + "anyOf": [ + { + "$ref": "#/definitions/ContinuousScaleType" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The *length* scale type, affecting how the scale encodes abstract data, say by applying a mathematical transformation. If null, the scale is disabled. The length scale defaults to *linear*, as this scale is intended for quantitative data." + }, + "lengthZero": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether the **domain** must include zero. If the domain minimum is positive, it will be set to zero; otherwise if the domain maximum is negative, it will be set to zero.\n\nFor quantitative scales only." + }, + "margin": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four margins: **marginTop**,\n**marginRight**, **marginBottom**, and **marginLeft**. Otherwise, the default margins depend on the maximum margins of the plot’s marks. While most marks default to zero margins (because they are drawn inside the chart area), Plot’s axis marks have non-zero default margins." + }, + "marginBottom": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The bottom margin; the distance in pixels between the bottom edges of the inner and outer plot area. Defaults to the maximum bottom margin of the plot’s marks." + }, + "marginLeft": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The left margin; the distance in pixels between the left edges of the inner and outer plot area. Defaults to the maximum left margin of the plot’s marks." + }, + "marginRight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The right margin; the distance in pixels between the right edges of the inner and outer plot area. Defaults to the maximum right margin of the plot’s marks." + }, + "marginTop": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The top margin; the distance in pixels between the top edges of the inner and outer plot area. Defaults to the maximum top margin of the plot’s marks." + }, + "margins": { + "additionalProperties": false, + "description": "A shorthand object notation for setting multiple margin values. The object keys are margin names (top, right, etc).", + "properties": { + "bottom": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "left": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "right": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "top": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + } + }, + "type": "object" + }, + "meta": { + "$ref": "#/definitions/Meta", + "description": "Specification metadata." + }, + "name": { + "description": "A unique name for the plot. The name is used by standalone legend components to to lookup the plot and access scale mappings.", + "type": "string" + }, + "opacityBase": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A log scale’s base; defaults to 10. Does not affect the scale’s encoding, but rather the default ticks. For *log* scales only." + }, + "opacityClamp": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, values below the domain minimum are treated as the domain minimum, and values above the domain maximum are treated as the domain maximum.\n\nClamping is useful for focusing on a subset of the data while ensuring that extreme values remain visible, but use caution: clamped values may need an annotation to avoid misinterpretation. Clamping typically requires setting an explicit **domain** since if the domain is inferred, no values will be outside the domain.\n\nFor continuous scales only." + }, + "opacityConstant": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A symlog scale’s constant, expressing the magnitude of the linear region around the origin; defaults to 1. For *symlog* scales only." + }, + "opacityDomain": { + "anyOf": [ + { + "items": {}, + "type": "array" + }, + { + "$ref": "#/definitions/Fixed" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The extent of the scale’s inputs (abstract values). By default inferred from channel values. For continuous data (numbers and dates), it is typically [*min*, *max*]; it can be [*max*, *min*] to reverse the scale. For ordinal data (strings or booleans), it is an array (or iterable) of values is the desired order, defaulting to natural ascending order.\n\nOpacity scales have a default domain from 0 to the maximum value of associated channels." + }, + "opacityExponent": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A power scale’s exponent (*e.g.*, 0.5 for sqrt); defaults to 1 for a linear scale. For *pow* scales only." + }, + "opacityLabel": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A textual label to show on the axis or legend; if null, show no label. By default the scale label is inferred from channel definitions, possibly with an arrow (↑, →, ↓, or ←) to indicate the direction of increasing value.\n\nFor axes and legends only." + }, + "opacityNice": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/Interval" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, or a tick count or interval, extend the domain to nice round values. Defaults to 1, 2 or 5 times a power of 10 for *linear* scales, and nice time intervals for *utc* and *time* scales. Pass an interval such as\n*minute*, *wednesday* or *month* to specify what constitutes a nice interval.\n\nFor continuous scales only." + }, + "opacityPercent": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, shorthand for a transform suitable for percentages, mapping proportions in [0, 1] to [0, 100]." + }, + "opacityRange": { + "anyOf": [ + { + "items": {}, + "type": "array" + }, + { + "$ref": "#/definitions/Fixed" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The extent of the scale’s outputs (visual values).\n\nOpacity scales have a default range of [0, 1]." + }, + "opacityReverse": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to reverse the scale’s encoding; equivalent to reversing either the\n**domain** or **range**." + }, + "opacityScale": { + "anyOf": [ + { + "$ref": "#/definitions/ContinuousScaleType" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The *opacity* scale type, affecting how the scale encodes abstract data, say by applying a mathematical transformation. If null, the scale is disabled. The opacity scale defaults to *linear*; this scales is intended for quantitative data." + }, + "opacityTickFormat": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to format inputs (abstract values) for axis tick labels; one of:\n\n- a [d3-format][1] string for numeric scales\n- a [d3-time-format][2] string for temporal scales\n\n[1]: https://d3js.org/d3-time [2]: https://d3js.org/d3-time-format" + }, + "opacityZero": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether the **domain** must include zero. If the domain minimum is positive, it will be set to zero; otherwise if the domain maximum is negative, it will be set to zero.\n\nFor quantitative scales only." + }, + "padding": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "For *band* scales, how much of the **range** to reserve to separate adjacent bands; defaults to 0.1 (10%). For *point* scales, the amount of inset for the first and last value as a proportion of the bandwidth; defaults to 0.5 (50%).\n\nFor ordinal position scales only." + }, + "params": { + "$ref": "#/definitions/Params", + "description": "Param and Selection definitions." + }, + "plot": { + "description": "An array of plot marks, interactors, or legends. Marks are graphical elements that make up plot layers. Unless otherwise configured, interactors will use the nearest previous mark as a basis for which data fields to select.", + "items": { + "anyOf": [ + { + "$ref": "#/definitions/PlotMark" + }, + { + "$ref": "#/definitions/PlotInteractor" + }, + { + "$ref": "#/definitions/PlotLegend" + } + ] + }, + "type": "array" + }, + "plotDefaults": { + "$ref": "#/definitions/PlotAttributes", + "description": "A default set of attributes to apply to all plot components." + }, + "projectionClip": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "number" + }, + { + "const": "frame", + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The projection’s clipping method; one of:\n\n- *frame* or true (default) - clip to the plot’s frame (including margins but not insets)\n- a number - clip to a circle of the given radius in degrees centered around the origin\n- null or false - do not clip\n\nSome projections (such as [*armadillo*][1] and [*berghaus*][2]) require spherical clipping: in that case set the marks’ **clip** option to\n*sphere*.\n\n[1]: https://observablehq.com/@d3/armadillo [2]: https://observablehq.com/@d3/berghaus-star" + }, + "projectionDomain": { + "anyOf": [ + { + "type": "object" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A GeoJSON object to fit to the plot’s frame (minus insets); defaults to a Sphere for spherical projections (outline of the the whole globe)." + }, + "projectionInset": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four projection insets. All insets typically default to zero, though not always. A positive inset reduces effective area, while a negative inset increases it." + }, + "projectionInsetBottom": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Insets the bottom edge of the projection by the specified number of pixels. A positive value insets towards the top edge (reducing effective area), while a negative value insets away from the top edge (increasing it)." + }, + "projectionInsetLeft": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Insets the left edge of the projection by the specified number of pixels. A positive value insets towards the right edge (reducing effective area), while a negative value insets away from the right edge (increasing it)." + }, + "projectionInsetRight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Insets the right edge of the projection by the specified number of pixels. A positive value insets towards the left edge (reducing effective area), while a negative value insets away from the left edge (increasing it)." + }, + "projectionInsetTop": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Insets the top edge of the projection by the specified number of pixels. A positive value insets towards the bottom edge (reducing effective area), while a negative value insets away from the bottom edge (increasing it)." + }, + "projectionParallels": { + "anyOf": [ + { + "items": [ + { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "title": "y1" + }, + { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "title": "y2" + } + ], + "maxItems": 2, + "minItems": 2, + "type": "array" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [standard parallels][1]. For conic projections only.\n\n[1]: https://d3js.org/d3-geo/conic#conic_parallels" + }, + "projectionPrecision": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The projection’s [sampling threshold][1].\n\n[1]: https://d3js.org/d3-geo/projection#projection_precision" + }, + "projectionRotate": { + "anyOf": [ + { + "items": [ + { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "title": "x" + }, + { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "title": "y" + }, + { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "title": "z" + } + ], + "maxItems": 3, + "minItems": 3, + "type": "array" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A rotation of the sphere before projection; defaults to [0, 0, 0]. Specified as Euler angles λ (yaw, or reference longitude), φ (pitch, or reference latitude), and optionally γ (roll), in degrees." + }, + "projectionType": { + "anyOf": [ + { + "$ref": "#/definitions/ProjectionName" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The desired projection; one of:\n\n- a named built-in projection such as *albers-usa*\n- null, for no projection\n\nNamed projections are scaled and translated to fit the **domain** to the plot’s frame (minus insets)." + }, + "rBase": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A log scale’s base; defaults to 10. Does not affect the scale’s encoding, but rather the default ticks. For *log* scales only." + }, + "rClamp": { + "description": "If true, values below the domain minimum are treated as the domain minimum, and values above the domain maximum are treated as the domain maximum.\n\nClamping is useful for focusing on a subset of the data while ensuring that extreme values remain visible, but use caution: clamped values may need an annotation to avoid misinterpretation. Clamping typically requires setting an explicit **domain** since if the domain is inferred, no values will be outside the domain.\n\nFor continuous scales only." + }, + "rConstant": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A symlog scale’s constant, expressing the magnitude of the linear region around the origin; defaults to 1. For *symlog* scales only." + }, + "rDomain": { + "anyOf": [ + { + "items": {}, + "type": "array" + }, + { + "$ref": "#/definitions/Fixed" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The extent of the scale’s inputs (abstract values). By default inferred from channel values. For continuous data (numbers and dates), it is typically [*min*, *max*]; it can be [*max*, *min*] to reverse the scale. For ordinal data (strings or booleans), it is an array (or iterable) of values is the desired order, defaulting to natural ascending order.\n\nRadius scales have a default domain from 0 to the median first quartile of associated channels." + }, + "rExponent": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A power scale’s exponent (*e.g.*, 0.5 for sqrt); defaults to 1 for a linear scale. For *pow* scales only." + }, + "rLabel": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A textual label to show on the axis or legend; if null, show no label. By default the scale label is inferred from channel definitions, possibly with an arrow (↑, →, ↓, or ←) to indicate the direction of increasing value." + }, + "rNice": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/Interval" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, or a tick count or interval, extend the domain to nice round values. Defaults to 1, 2 or 5 times a power of 10 for *linear* scales, and nice time intervals for *utc* and *time* scales. Pass an interval such as\n*minute*, *wednesday* or *month* to specify what constitutes a nice interval.\n\nFor continuous scales only." + }, + "rPercent": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, shorthand for a transform suitable for percentages, mapping proportions in [0, 1] to [0, 100]." + }, + "rRange": { + "anyOf": [ + { + "items": {}, + "type": "array" + }, + { + "$ref": "#/definitions/Fixed" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The extent of the scale’s outputs (visual values). By default inferred from the scale’s **type** and **domain**, and for position scales, the plot’s dimensions. For continuous data (numbers and dates), and for ordinal position scales (*point* and *band*), it is typically [*min*, *max*]; it can be [*max*, *min*] to reverse the scale. For other ordinal data, such as for a *color* scale, it is an array (or iterable) of output values in the same order as the **domain**.\n\nRadius scales have a default range of [0, 3]." + }, + "rScale": { + "anyOf": [ + { + "$ref": "#/definitions/ContinuousScaleType" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The *r* (radius) scale type, affecting how the scale encodes abstract data, say by applying a mathematical transformation. If null, the scale is disabled. The radius scale defaults to *sqrt*; this scale is intended for quantitative data." + }, + "rZero": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether the **domain** must include zero. If the domain minimum is positive, it will be set to zero; otherwise if the domain maximum is negative, it will be set to zero.\n\nFor quantitative scales only." + }, + "style": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/CSSStyles" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Custom styles to override Plot’s defaults. Styles may be specified either as a string of inline styles (*e.g.*, `\"color: red;\"`, in the same fashion as assigning [*element*.style][1]) or an object of properties (*e.g.*, `{color: \"red\"}`, in the same fashion as assigning [*element*.style properties][2]). Note that unitless numbers ([quirky lengths][3]) such as `{padding: 20}` may not supported by some browsers; you should instead specify a string with units such as `{padding: \"20px\"}`. By default, the returned plot has a max-width of 100%, and the system-ui font. Plot’s marks and axes default to [currentColor][4], meaning that they will inherit the surrounding content’s color.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/style [2]: https://developer.mozilla.org/en-US/docs/Web/API/CSSStyleDeclaration [3]: https://www.w3.org/TR/css-values-4/#deprecated-quirky-length [4]: https://developer.mozilla.org/en-US/docs/Web/CSS/color_value#currentcolor_keyword" + }, + "symbolDomain": { + "anyOf": [ + { + "items": {}, + "type": "array" + }, + { + "$ref": "#/definitions/Fixed" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The extent of the scale’s inputs (abstract values). By default inferred from channel values. As symbol scales are discrete, the domain is an array (or iterable) of values is the desired order, defaulting to natural ascending order." + }, + "symbolRange": { + "anyOf": [ + { + "items": {}, + "type": "array" + }, + { + "$ref": "#/definitions/Fixed" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The extent of the scale’s outputs (visual values). By default inferred from the scale’s **type** and **domain**, and for position scales, the plot’s dimensions. For continuous data (numbers and dates), and for ordinal position scales (*point* and *band*), it is typically [*min*, *max*]; it can be [*max*, *min*] to reverse the scale. For other ordinal data, such as for a *color* scale, it is an array (or iterable) of output values in the same order as the **domain**.\n\nSymbol scales have a default range of categorical symbols; the choice of symbols depends on whether the associated dot mark is filled or stroked." + }, + "symbolScale": { + "anyOf": [ + { + "$ref": "#/definitions/DiscreteScaleType" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The *symbol* scale type, affecting how the scale encodes abstract data, say by applying a mathematical transformation. If null, the scale is disabled. Defaults to an *ordinal* scale type." + }, + "width": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The outer width of the plot in pixels, including margins. Defaults to 640. On Observable, this can be set to the built-in [width][1] for full-width responsive plots. Note: the default style has a max-width of 100%; the plot will automatically shrink to fit even when a fixed width is specified.\n\n[1]: https://github.com/observablehq/stdlib/blob/main/README.md#width" + }, + "xAlign": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to distribute unused space in the **range** for *point* and *band* scales. A number in [0, 1], such as:\n\n- 0 - use the start of the range, putting unused space at the end\n- 0.5 (default) - use the middle, distributing unused space evenly\n- 1 use the end, putting unused space at the start\n\nFor ordinal position scales only." + }, + "xAriaDescription": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A textual description for the axis in the accessibility tree." + }, + "xAriaLabel": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A short label representing the axis in the accessibility tree." + }, + "xAxis": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "const": "both", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The side of the frame on which to place the implicit axis: *top* or\n*bottom* for *x*. Defaults to *bottom* for an *x* scale.\n\nIf *both*, an implicit axis will be rendered on both sides of the plot (*top* and *bottom* for *x*). If null, the implicit axis is suppressed." + }, + "xBase": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A log scale’s base; defaults to 10. Does not affect the scale’s encoding, but rather the default ticks. For *log* scales only." + }, + "xClamp": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, values below the domain minimum are treated as the domain minimum, and values above the domain maximum are treated as the domain maximum.\n\nClamping is useful for focusing on a subset of the data while ensuring that extreme values remain visible, but use caution: clamped values may need an annotation to avoid misinterpretation. Clamping typically requires setting an explicit **domain** since if the domain is inferred, no values will be outside the domain.\n\nFor continuous scales only." + }, + "xConstant": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A symlog scale’s constant, expressing the magnitude of the linear region around the origin; defaults to 1. For *symlog* scales only." + }, + "xDomain": { + "anyOf": [ + { + "items": {}, + "type": "array" + }, + { + "$ref": "#/definitions/Fixed" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The extent of the scale’s inputs (abstract values). By default inferred from channel values. For continuous data (numbers and dates), it is typically [*min*, *max*]; it can be [*max*, *min*] to reverse the scale. For ordinal data (strings or booleans), it is an array (or iterable) of values is the desired order, defaulting to natural ascending order.\n\nLinear scales have a default domain of [0, 1]. Log scales have a default domain of [1, 10] and cannot include zero. Radius scales have a default domain from 0 to the median first quartile of associated channels. Length have a default domain from 0 to the median median of associated channels. Opacity scales have a default domain from 0 to the maximum value of associated channels." + }, + "xExponent": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A power scale’s exponent (*e.g.*, 0.5 for sqrt); defaults to 1 for a linear scale. For *pow* scales only." + }, + "xFontVariant": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The font-variant attribute for axis ticks; defaults to *tabular-nums* for quantitative axes." + }, + "xGrid": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/Interval" + }, + { + "items": {}, + "type": "array" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to show a grid aligned with the scale’s ticks. If true, show a grid with the currentColor stroke; if a string, show a grid with the specified stroke color; if an approximate number of ticks, an interval, or an array of tick values, show corresponding grid lines. See also the grid mark.\n\nFor axes only." + }, + "xInset": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four insets: **insetTop**,\n**insetRight**, **insetBottom**, and **insetLeft**. All insets typically default to zero, though not always (say when using bin transform). A positive inset reduces effective area, while a negative inset increases it." + }, + "xInsetLeft": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Insets the left edge by the specified number of pixels. A positive value insets towards the right edge (reducing effective area), while a negative value insets away from the right edge (increasing it)." + }, + "xInsetRight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Insets the right edge by the specified number of pixels. A positive value insets towards the left edge (reducing effective area), while a negative value insets away from the left edge (increasing it)." + }, + "xLabel": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A textual label to show on the axis or legend; if null, show no label. By default the scale label is inferred from channel definitions, possibly with an arrow (↑, →, ↓, or ←) to indicate the direction of increasing value.\n\nFor axes and legends only." + }, + "xLabelAnchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "right", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "const": "left", + "type": "string" + }, + { + "const": "center", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Where to place the axis **label** relative to the plot’s frame. For vertical position scales (*y* and *fy*), may be *top*, *bottom*, or\n*center*; for horizontal position scales (*x* and *fx*), may be *left*,\n*right*, or *center*. Defaults to *center* for ordinal scales (including\n*fx* and *fy*), and otherwise *top* for *y*, and *right* for *x*." + }, + "xLabelArrow": { + "anyOf": [ + { + "$ref": "#/definitions/LabelArrow" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to apply a directional arrow such as → or ↑ to the x-axis scale label. If *auto* (the default), the presence of the arrow depends on whether the scale is ordinal." + }, + "xLabelOffset": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The axis **label** position offset (in pixels); default depends on margins and orientation." + }, + "xLine": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, draw a line along the axis; if false (default), do not." + }, + "xNice": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/Interval" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, or a tick count or interval, extend the domain to nice round values. Defaults to 1, 2 or 5 times a power of 10 for *linear* scales, and nice time intervals for *utc* and *time* scales. Pass an interval such as\n*minute*, *wednesday* or *month* to specify what constitutes a nice interval.\n\nFor continuous scales only." + }, + "xPadding": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "For *band* scales, how much of the **range** to reserve to separate adjacent bands; defaults to 0.1 (10%). For *point* scales, the amount of inset for the first and last value as a proportion of the bandwidth; defaults to 0.5 (50%).\n\nFor ordinal position scales only." + }, + "xPaddingInner": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "For a *band* scale, how much of the range to reserve to separate adjacent bands." + }, + "xPaddingOuter": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "For a *band* scale, how much of the range to reserve to inset first and last bands." + }, + "xPercent": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, shorthand for a transform suitable for percentages, mapping proportions in [0, 1] to [0, 100]." + }, + "xRange": { + "anyOf": [ + { + "items": {}, + "type": "array" + }, + { + "$ref": "#/definitions/Fixed" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The extent of the scale’s outputs (visual values). By default inferred from the scale’s **type** and **domain**, and for position scales, the plot’s dimensions. For continuous data (numbers and dates), and for ordinal position scales (*point* and *band*), it is typically [*min*, *max*]; it can be [*max*, *min*] to reverse the scale." + }, + "xReverse": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to reverse the scale’s encoding; equivalent to reversing either the\n**domain** or **range**." + }, + "xRound": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, round the output value to the nearest integer (pixel); useful for crisp edges when rendering.\n\nFor position scales only." + }, + "xScale": { + "anyOf": [ + { + "$ref": "#/definitions/PositionScaleType" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The *x* scale type, affecting how the scale encodes abstract data, say by applying a mathematical transformation. If null, the scale is disabled.\n\nFor quantitative data (numbers), defaults to *linear*; for temporal data (dates), defaults to *utc*; for ordinal data (strings or booleans), defaults to *point* for position scales, *categorical* for color scales, and otherwise *ordinal*. However, the radius scale defaults to *sqrt*, and the length and opacity scales default to *linear*; these scales are intended for quantitative data. The plot’s marks may also impose a scale type; for example, the barY mark requires that *x* is a *band* scale." + }, + "xTickFormat": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to format inputs (abstract values) for axis tick labels; one of:\n\n- a [d3-format][1] string for numeric scales\n- a [d3-time-format][2] string for temporal scales\n\n[1]: https://d3js.org/d3-time [2]: https://d3js.org/d3-time-format" + }, + "xTickPadding": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The distance between an axis tick mark and its associated text label (in pixels); often defaults to 3, but may be affected by **xTickSize** and\n**xTickRotate**." + }, + "xTickRotate": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The rotation angle of axis tick labels in degrees clocksize; defaults to 0." + }, + "xTickSize": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The length of axis tick marks in pixels; negative values extend in the opposite direction. Defaults to 6 for *x* and *y* axes and *color* and\n*opacity* *ramp* legends, and 0 for *fx* and *fy* axes." + }, + "xTickSpacing": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The desired approximate spacing between adjacent axis ticks, affecting the default **ticks**; defaults to 80 pixels for *x* and *fx*, and 35 pixels for *y* and *fy*." + }, + "xTicks": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/Interval" + }, + { + "items": {}, + "type": "array" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The desired approximate number of axis ticks, or an explicit array of tick values, or an interval such as *day* or *month*." + }, + "xZero": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether the **domain** must include zero. If the domain minimum is positive, it will be set to zero; otherwise if the domain maximum is negative, it will be set to zero.\n\nFor quantitative scales only." + }, + "xyDomain": { + "anyOf": [ + { + "items": {}, + "type": "array" + }, + { + "$ref": "#/definitions/Fixed" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Set the *x* and *y* scale domains." + }, + "yAlign": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to distribute unused space in the **range** for *point* and *band* scales. A number in [0, 1], such as:\n\n- 0 - use the start of the range, putting unused space at the end\n- 0.5 (default) - use the middle, distributing unused space evenly\n- 1 use the end, putting unused space at the start\n\nFor ordinal position scales only." + }, + "yAriaDescription": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A textual description for the axis in the accessibility tree." + }, + "yAriaLabel": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A short label representing the axis in the accessibility tree." + }, + "yAxis": { + "anyOf": [ + { + "const": "left", + "type": "string" + }, + { + "const": "right", + "type": "string" + }, + { + "const": "both", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The side of the frame on which to place the implicit axis: *left* or\n*right* for *y*. Defaults to *left* for a *y* scale.\n\nIf *both*, an implicit axis will be rendered on both sides of the plot (*left* and *right* for *y*). If null, the implicit axis is suppressed." + }, + "yBase": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A log scale’s base; defaults to 10. Does not affect the scale’s encoding, but rather the default ticks. For *log* scales only." + }, + "yClamp": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, values below the domain minimum are treated as the domain minimum, and values above the domain maximum are treated as the domain maximum.\n\nClamping is useful for focusing on a subset of the data while ensuring that extreme values remain visible, but use caution: clamped values may need an annotation to avoid misinterpretation. Clamping typically requires setting an explicit **domain** since if the domain is inferred, no values will be outside the domain.\n\nFor continuous scales only." + }, + "yConstant": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A symlog scale’s constant, expressing the magnitude of the linear region around the origin; defaults to 1. For *symlog* scales only." + }, + "yDomain": { + "anyOf": [ + { + "items": {}, + "type": "array" + }, + { + "$ref": "#/definitions/Fixed" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The extent of the scale’s inputs (abstract values). By default inferred from channel values. For continuous data (numbers and dates), it is typically [*min*, *max*]; it can be [*max*, *min*] to reverse the scale. For ordinal data (strings or booleans), it is an array (or iterable) of values is the desired order, defaulting to natural ascending order.\n\nLinear scales have a default domain of [0, 1]. Log scales have a default domain of [1, 10] and cannot include zero." + }, + "yExponent": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A power scale’s exponent (*e.g.*, 0.5 for sqrt); defaults to 1 for a linear scale. For *pow* scales only." + }, + "yFontVariant": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The font-variant attribute for axis ticks; defaults to *tabular-nums* for quantitative axes." + }, + "yGrid": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/Interval" + }, + { + "items": {}, + "type": "array" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to show a grid aligned with the scale’s ticks. If true, show a grid with the currentColor stroke; if a string, show a grid with the specified stroke color; if an approximate number of ticks, an interval, or an array of tick values, show corresponding grid lines. See also the grid mark.\n\nFor axes only." + }, + "yInset": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four insets: **insetTop**,\n**insetRight**, **insetBottom**, and **insetLeft**. All insets typically default to zero, though not always (say when using bin transform). A positive inset reduces effective area, while a negative inset increases it." + }, + "yInsetBottom": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Insets the bottom edge by the specified number of pixels. A positive value insets towards the top edge (reducing effective area), while a negative value insets away from the top edge (increasing it)." + }, + "yInsetTop": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Insets the top edge by the specified number of pixels. A positive value insets towards the bottom edge (reducing effective area), while a negative value insets away from the bottom edge (increasing it)." + }, + "yLabel": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A textual label to show on the axis or legend; if null, show no label. By default the scale label is inferred from channel definitions, possibly with an arrow (↑, →, ↓, or ←) to indicate the direction of increasing value.\n\nFor axes and legends only." + }, + "yLabelAnchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "right", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "const": "left", + "type": "string" + }, + { + "const": "center", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Where to place the axis **label** relative to the plot’s frame. For vertical position scales (*y* and *fy*), may be *top*, *bottom*, or\n*center*; for horizontal position scales (*x* and *fx*), may be *left*,\n*right*, or *center*. Defaults to *center* for ordinal scales (including\n*fx* and *fy*), and otherwise *top* for *y*, and *right* for *x*." + }, + "yLabelArrow": { + "anyOf": [ + { + "$ref": "#/definitions/LabelArrow" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to apply a directional arrow such as → or ↑ to the x-axis scale label. If *auto* (the default), the presence of the arrow depends on whether the scale is ordinal." + }, + "yLabelOffset": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The axis **label** position offset (in pixels); default depends on margins and orientation." + }, + "yLine": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, draw a line along the axis; if false (default), do not." + }, + "yNice": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/Interval" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, or a tick count or interval, extend the domain to nice round values. Defaults to 1, 2 or 5 times a power of 10 for *linear* scales, and nice time intervals for *utc* and *time* scales. Pass an interval such as\n*minute*, *wednesday* or *month* to specify what constitutes a nice interval.\n\nFor continuous scales only." + }, + "yPadding": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "For *band* scales, how much of the **range** to reserve to separate adjacent bands; defaults to 0.1 (10%). For *point* scales, the amount of inset for the first and last value as a proportion of the bandwidth; defaults to 0.5 (50%).\n\nFor ordinal position scales only." + }, + "yPaddingInner": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "For a *band* scale, how much of the range to reserve to separate adjacent bands." + }, + "yPaddingOuter": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "For a *band* scale, how much of the range to reserve to inset first and last bands." + }, + "yPercent": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, shorthand for a transform suitable for percentages, mapping proportions in [0, 1] to [0, 100]." + }, + "yRange": { + "anyOf": [ + { + "items": {}, + "type": "array" + }, + { + "$ref": "#/definitions/Fixed" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The extent of the scale’s outputs (visual values). By default inferred from the scale’s **type** and **domain**, and for position scales, the plot’s dimensions. For continuous data (numbers and dates), and for ordinal position scales (*point* and *band*), it is typically [*min*,\n*max*]; it can be [*max*, *min*] to reverse the scale." + }, + "yReverse": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to reverse the scale’s encoding; equivalent to reversing either the\n**domain** or **range**. Note that by default, when the *y* scale is continuous, the *max* value points to the top of the screen, whereas ordinal values are ranked from top to bottom." + }, + "yRound": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, round the output value to the nearest integer (pixel); useful for crisp edges when rendering.\n\nFor position scales only." + }, + "yScale": { + "anyOf": [ + { + "$ref": "#/definitions/PositionScaleType" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The *y* scale type, affecting how the scale encodes abstract data, say by applying a mathematical transformation. If null, the scale is disabled.\n\nFor quantitative data (numbers), defaults to *linear*; for temporal data (dates), defaults to *utc*; for ordinal data (strings or booleans), defaults to *point* for position scales, The plot’s marks may also impose a scale type; for example, the barY mark requires that *x* is a *band* scale." + }, + "yTickFormat": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to format inputs (abstract values) for axis tick labels; one of:\n\n- a [d3-format][1] string for numeric scales\n- a [d3-time-format][2] string for temporal scales\n\n[1]: https://d3js.org/d3-time [2]: https://d3js.org/d3-time-format" + }, + "yTickPadding": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The distance between an axis tick mark and its associated text label (in pixels); often defaults to 3, but may be affected by **yTickSize** and\n**yTickRotate**." + }, + "yTickRotate": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The rotation angle of axis tick labels in degrees clocksize; defaults to 0." + }, + "yTickSize": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The length of axis tick marks in pixels; negative values extend in the opposite direction. Defaults to 6 for *x* and *y* axes and *color* and\n*opacity* *ramp* legends, and 0 for *fx* and *fy* axes." + }, + "yTickSpacing": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The desired approximate spacing between adjacent axis ticks, affecting the default **ticks**; defaults to 80 pixels for *x* and *fx*, and 35 pixels for *y* and *fy*." + }, + "yTicks": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/Interval" + }, + { + "items": {}, + "type": "array" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The desired approximate number of axis ticks, or an explicit array of tick values, or an interval such as *day* or *month*." + }, + "yZero": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether the **domain** must include zero. If the domain minimum is positive, it will be set to zero; otherwise if the domain maximum is negative, it will be set to zero.\n\nFor quantitative scales only." + } + }, + "required": [ + "plot" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "$schema": { + "description": "A [JSON schema](http://json-schema.org/) URL for this specification, such as https://uwdata.github.io/mosaic/schema/latest.json. This property enables validation and autocomplete in editors with JSON schema support.", + "format": "uri", + "type": "string" + }, + "ariaDescription": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-description][1]; a constant textual description.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-description" + }, + "ariaHidden": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-hidden][1] state; a constant indicating whether the element is exposed to an accessibility API.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-hidden" + }, + "ariaLabel": { + "$ref": "#/definitions/ChannelValue", + "description": "The [aria-label][1]; a channel specifying short textual labels representing the value in the accessibility tree.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-label" + }, + "clip": { + "anyOf": [ + { + "const": "frame", + "type": "string" + }, + { + "const": "sphere", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to clip the mark; one of:\n\n- *frame* or true - clip to the plot’s frame (inner area)\n- *sphere* - clip to the projected sphere (*e.g.*, front hemisphere)\n- null or false - do not clip\n\nThe *sphere* clip option requires a geographic projection." + }, + "config": { + "$ref": "#/definitions/Config", + "description": "Configuration options." + }, + "curve": { + "anyOf": [ + { + "$ref": "#/definitions/Curve" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The curve (interpolation) method for connecting adjacent points. One of:\n\n- *basis* - a cubic basis spline (repeating the end points)\n- *basis-open* - an open cubic basis spline\n- *basis-closed* - a closed cubic basis spline\n- *bump-x* - a Bézier curve with horizontal tangents\n- *bump-y* - a Bézier curve with vertical tangents\n- *bundle* - a straightened cubic basis spline (suitable for lines only, not areas)\n- *cardinal* - a cubic cardinal spline (with one-sided differences at the ends)\n- *cardinal-open* - an open cubic cardinal spline\n- *cardinal-closed* - an closed cubic cardinal spline\n- *catmull-rom* - a cubic Catmull–Rom spline (with one-sided differences at the ends)\n- *catmull-rom-open* - an open cubic Catmull–Rom spline\n- *catmull-rom-closed* - a closed cubic Catmull–Rom spline\n- *linear* - a piecewise linear curve (*i.e.*, straight line segments)\n- *linear-closed* - a closed piecewise linear curve (*i.e.*, straight line segments)\n- *monotone-x* - a cubic spline that preserves monotonicity in *x*\n- *monotone-y* - a cubic spline that preserves monotonicity in *y*\n- *natural* - a natural cubic spline\n- *step* - a piecewise constant function where *y* changes at the midpoint of *x*\n- *step-after* - a piecewise constant function where *y* changes after *x*\n- *step-before* - a piecewise constant function where *x* changes after *y*" + }, + "data": { + "$ref": "#/definitions/Data", + "description": "Dataset definitions." + }, + "dx": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The horizontal offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "dy": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The vertical offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "facet": { + "anyOf": [ + { + "const": "auto", + "type": "string" + }, + { + "const": "include", + "type": "string" + }, + { + "const": "exclude", + "type": "string" + }, + { + "const": "super", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to enable or disable faceting; one of:\n\n- *auto* (default) - automatically determine if this mark should be faceted\n- *include* (or true) - draw the subset of the mark’s data in the current facet\n- *exclude* - draw the subset of the mark’s data *not* in the current facet\n- *super* - draw this mark in a single frame that covers all facets\n- null (or false) - repeat this mark’s data across all facets (*i.e.*, no faceting)\n\nWhen a mark uses *super* faceting, it is not allowed to use position scales (*x*, *y*, *fx*, or *fy*); *super* faceting is intended for decorations, such as labels and legends.\n\nWhen top-level faceting is used, the default *auto* setting is equivalent to *include* when the mark data is strictly equal to the top-level facet data; otherwise it is equivalent to null. When the *include* or *exclude* facet mode is chosen, the mark data must be parallel to the top-level facet data: the data must have the same length and order. If the data are not parallel, then the wrong data may be shown in each facet. The default\n*auto* therefore requires strict equality (`===`) for safety, and using the facet data as mark data is recommended when using the *exclude* facet mode. (To construct parallel data safely, consider using [*array*.map][1] on the facet data.)\n\nWhen mark-level faceting is used, the default *auto* setting is equivalent to *include*: the mark will be faceted if either the **fx** or **fy** channel option (or both) is specified. The null or false option will disable faceting, while *exclude* draws the subset of the mark’s data *not* in the current facet.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map" + }, + "facetAnchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "right", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "const": "left", + "type": "string" + }, + { + "const": "top-left", + "type": "string" + }, + { + "const": "top-right", + "type": "string" + }, + { + "const": "bottom-left", + "type": "string" + }, + { + "const": "bottom-right", + "type": "string" + }, + { + "const": "top-empty", + "type": "string" + }, + { + "const": "right-empty", + "type": "string" + }, + { + "const": "bottom-empty", + "type": "string" + }, + { + "const": "left-empty", + "type": "string" + }, + { + "const": "empty", + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to place the mark with respect to facets; one of:\n\n- null (default for most marks) - display the mark in each non-empty facet\n- *top*, *right*, *bottom*, or *left* - display the mark only in facets on the given side\n- *top-empty*, *right-empty*, *bottom-empty*, or *left-empty* (default for axis marks) - display the mark only in facets that have empty space on the given side: either the margin, or an empty facet\n- *empty* - display the mark in empty facets only" + }, + "fill": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill" + }, + "fillOpacity": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill-opacity][1]; a constant number between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill-opacity" + }, + "filter": { + "$ref": "#/definitions/ChannelValue", + "description": "Applies a transform to filter the mark’s index according to the given channel values; only truthy values are retained.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "fx": { + "$ref": "#/definitions/ChannelValue", + "description": "The horizontal facet position channel, for mark-level faceting, bound to the *fx* scale." + }, + "fy": { + "$ref": "#/definitions/ChannelValue", + "description": "The vertical facet position channel, for mark-level faceting, bound to the\n*fy* scale." + }, + "href": { + "$ref": "#/definitions/ChannelValue", + "description": "The [href][1]; a channel specifying URLs for clickable links. May be used in conjunction with the **target** option to open links in another window.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/href" + }, + "imageFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A CSS [filter][1]; a constant string used to adjust the rendering of images, such as *blur(5px)*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/filter" + }, + "margin": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four mark margins: **marginTop**,\n**marginRight**, **marginBottom**, and **marginLeft**; typically defaults to 0, except for axis marks." + }, + "marginBottom": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s bottom margin; the minimum distance in pixels between the bottom edges of the inner and outer plot area." + }, + "marginLeft": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s left margin; the minimum distance in pixels between the left edges of the inner and outer plot area." + }, + "marginRight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s right margin; the minimum distance in pixels between the right edges of the mark’s inner and outer plot area." + }, + "marginTop": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s top margin; the minimum distance in pixels between the top edges of the inner and outer plot area." + }, + "mark": { + "const": "area", + "description": "An area mark. The area mark is rarely used directly; it is only needed when the baseline and topline have neither *x* nor *y* values in common. Use areaY for a horizontal orientation where the baseline and topline share *x* values, or areaX for a vertical orientation where the baseline and topline share *y* values.", + "type": "string" + }, + "meta": { + "$ref": "#/definitions/Meta", + "description": "Specification metadata." + }, + "mixBlendMode": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [mix-blend-mode][1]; a constant string specifying how to blend content such as *multiply*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode" + }, + "offset": { + "anyOf": [ + { + "$ref": "#/definitions/StackOffset" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "After stacking, an optional **offset** can be applied to translate and scale stacks, say to produce a streamgraph; defaults to null for a zero baseline (**y** = 0 for stackY, and **x** = 0 for stackX). If the *wiggle* offset is used, the default **order** changes to *inside-out*." + }, + "opacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally. For faster rendering, prefer the **strokeOpacity** or **fillOpacity** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/opacity" + }, + "order": { + "anyOf": [ + { + "$ref": "#/definitions/StackOrder" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The order in which stacks are layered; one of:\n\n- null (default) for input order\n- a named stack order method such as *inside-out* or *sum*\n- a field name, for natural order of the corresponding values\n- a function of data, for natural order of the corresponding values\n- an array of explicit **z** values in the desired order\n\nIf the *wiggle* **offset** is used, as for a streamgraph, the default changes to *inside-out*." + }, + "paintOrder": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [paint-order][1]; a constant string specifying the order in which the\n**fill**, **stroke**, and any markers are drawn; defaults to *normal*, which draws the fill, then stroke, then markers; defaults to *stroke* for the text mark to create a “halo” around text to improve legibility.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/paint-order" + }, + "params": { + "$ref": "#/definitions/Params", + "description": "Param and Selection definitions." + }, + "plotDefaults": { + "$ref": "#/definitions/PlotAttributes", + "description": "A default set of attributes to apply to all plot components." + }, + "pointerEvents": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [pointer-events][1] property; a constant string such as *none*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/pointer-events" + }, + "reverse": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Applies a transform to reverse the order of the mark’s index, say for reverse input order." + }, + "select": { + "$ref": "#/definitions/SelectFilter", + "description": "Applies a filter transform after data is loaded to highlight selected values only. For example, `first` and `last` select the first or last values of series only (using the *z* channel to separate series). Meanwhile, `nearestX` and `nearestY` select the point nearest to the pointer along the *x* or *y* channel dimension. Unlike Mosaic selections, a mark level *select* is internal to the mark only, and does not populate a param or selection value to be shared across clients.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "shapeRendering": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [shape-rendering][1]; a constant string such as *crispEdges*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/shape-rendering" + }, + "sort": { + "anyOf": [ + { + "$ref": "#/definitions/SortOrder" + }, + { + "$ref": "#/definitions/ChannelDomainSort" + } + ], + "description": "Either applies a transform to sort the mark’s index by the specified channel values, or imputes ordinal scale domains from this mark’s channels.\n\nWhen imputing ordinal scale domains from channel values, the **sort** option is an object whose keys are ordinal scale names such as *x* or *fx*, and whose values are channel names such as *y*, *y1*, or *y2*. For example, to impute the *y* scale’s domain from the associated *x* channel values in ascending order:\n\n```js sort: {y: \"x\"} ```\n\nFor different sort options for different scales, replace the channel name with a *value* object and per-scale options:\n\n```js sort: {y: {value: \"-x\"}} ```\n\nWhen sorting the mark’s index, the **sort** option is instead one of:\n\n- a channel value definition for sorting given values in ascending order\n- a {value, order} object for sorting given values\n- a {channel, order} object for sorting the named channel’s values" + }, + "stroke": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke" + }, + "strokeDasharray": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dasharray][1]; a constant number indicating the length in pixels of alternating dashes and gaps, or a constant string of numbers separated by spaces or commas (_e.g._, *10 2* for dashes of 10 pixels separated by gaps of 2 pixels), or *none* (the default) for no dashing\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dasharray" + }, + "strokeDashoffset": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dashoffset][1]; a constant indicating the offset in pixels of the first dash along the stroke; defaults to zero.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dashoffset" + }, + "strokeLinecap": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linecap][1]; a constant specifying how to cap stroked paths, such as *butt*, *round*, or *square*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linecap" + }, + "strokeLinejoin": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linejoin][1]; a constant specifying how to join stroked paths, such as *bevel*, *miter*, *miter-clip*, or *round*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linejoin" + }, + "strokeMiterlimit": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-miterlimit][1]; a constant number specifying how to limit the length of *miter* joins on stroked paths.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-miterlimit" + }, + "strokeOpacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-opacity" + }, + "strokeWidth": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-width][1]; a constant number in pixels, or a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-width" + }, + "target": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [target][1]; a constant string specifying the target window (_e.g._,\n*_blank*) for clickable links; used in conjunction with the **href** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/target" + }, + "tension": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The tension option only has an effect on bundle, cardinal and Catmull–Rom splines (*bundle*, *cardinal*, *cardinal-open*, *cardinal-closed*,\n*catmull-rom*, *catmull-rom-open*, and *catmull-rom-closed*). For bundle splines, it corresponds to [beta][1]; for cardinal splines, [tension][2]; for Catmull–Rom splines, [alpha][3].\n\n[1]: https://d3js.org/d3-shape/curve#curveBundle_beta [2]: https://d3js.org/d3-shape/curve#curveCardinal_tension [3]: https://d3js.org/d3-shape/curve#curveCatmullRom_alpha" + }, + "tip": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/TipPointer" + }, + { + "properties": { + "anchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The tip anchor specifies how to orient the tip box relative to its anchor position; it refers to the part of the tip box that is attached to the anchor point. For example, the *top-left* anchor places the top-left corner of tip box near the anchor position, hence placing the tip box below and to the right of the anchor position." + }, + "fontFamily": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font-family][1]; a constant; defaults to the plot’s font family, which is typically [*system-ui*][2].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-family [2]: https://drafts.csswg.org/css-fonts-4/#valdef-font-family-system-ui" + }, + "fontSize": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font size][1] in pixels; either a constant or a channel; defaults to the plot’s font size, which is typically 10. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-size" + }, + "fontStyle": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font style][1]; a constant; defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-style" + }, + "fontVariant": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font variant][1]; a constant; if the **text** channel contains numbers or dates, defaults to *tabular-nums* to facilitate comparing numbers; otherwise defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant" + }, + "fontWeight": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font weight][1]; a constant; defaults to the plot’s font weight, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight" + }, + "format": { + "additionalProperties": false, + "description": "How channel values are formatted for display. If a format is a string, it is interpreted as a (UTC) time format for temporal channels, and otherwise a number format.", + "properties": { + "ariaLabel": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fill": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fillOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fontSize": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fx": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fy": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "geometry": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "height": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "href": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "length": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "opacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "path": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "r": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "rotate": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "src": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "stroke": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeWidth": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "symbol": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "text": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "title": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "weight": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "width": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "z": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + } + }, + "type": "object" + }, + "frameAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The frame anchor specifies defaults for **x** and **y** based on the plot’s frame; it may be one of the four sides (*top*, *right*, *bottom*, *left*), one of the four corners (*top-left*, *top-right*, *bottom-right*,\n*bottom-left*), or the *middle* of the frame. For example, for tips distributed horizontally at the top of the frame:\n\n```js Plot.tip(data, {x: \"date\", frameAnchor: \"top\"}) ```" + }, + "lineHeight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line height in ems; defaults to 1. The line height affects the (typically vertical) separation between adjacent baselines of text, as well as the separation between the text and its anchor point." + }, + "lineWidth": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line width in ems (e.g., 10 for about 20 characters); defaults to infinity, disabling wrapping and clipping.\n\nIf **textOverflow** is null, lines will be wrapped at the specified length. If a line is split at a soft hyphen (\\xad), a hyphen (-) will be displayed at the end of the line. If **textOverflow** is not null, lines will be clipped according to the given strategy." + }, + "monospace": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, changes the default **fontFamily** to *monospace*, and uses simplified monospaced text metrics calculations." + }, + "pathFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The image filter for the tip’s box; defaults to a drop shadow." + }, + "pointer": { + "$ref": "#/definitions/TipPointer" + }, + "pointerSize": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The size of the tip’s pointer in pixels; defaults to 12." + }, + "preferredAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If an explicit tip anchor is not specified, an anchor is chosen automatically such that the tip fits within the plot’s frame; if the preferred anchor fits, it is chosen." + }, + "textAnchor": { + "anyOf": [ + { + "const": "start", + "type": "string" + }, + { + "const": "middle", + "type": "string" + }, + { + "const": "end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [text anchor][1] controls how text is aligned (typically horizontally) relative to its anchor point; it is one of *start*, *end*, or *middle*. If the frame anchor is *left*, *top-left*, or *bottom-left*, the default text anchor is *start*; if the frame anchor is *right*, *top-right*, or\n*bottom-right*, the default is *end*; otherwise it is *middle*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/text-anchor" + }, + "textOverflow": { + "anyOf": [ + { + "type": "null" + }, + { + "const": "clip", + "type": "string" + }, + { + "const": "ellipsis", + "type": "string" + }, + { + "const": "clip-start", + "type": "string" + }, + { + "const": "clip-end", + "type": "string" + }, + { + "const": "ellipsis-start", + "type": "string" + }, + { + "const": "ellipsis-middle", + "type": "string" + }, + { + "const": "ellipsis-end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How truncate (or wrap) lines of text longer than the given **lineWidth**; one of:\n\n- null (default) - preserve overflowing characters (and wrap if needed)\n- *clip* or *clip-end* - remove characters from the end\n- *clip-start* - remove characters from the start\n- *ellipsis* or *ellipsis-end* - replace characters from the end with an ellipsis (…)\n- *ellipsis-start* - replace characters from the start with an ellipsis (…)\n- *ellipsis-middle* - replace characters from the middle with an ellipsis (…)\n\nIf no **title** was specified, if text requires truncation, a title containing the non-truncated text will be implicitly added." + }, + "textPadding": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The padding around the text in pixels; defaults to 8." + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + } + }, + "type": "object" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to generate a tooltip for this mark, and any tip options." + }, + "title": { + "$ref": "#/definitions/ChannelValue", + "description": "The title; a channel specifying accessible, short textual descriptions as strings (possibly with newlines). If the tip option is specified, the title will be displayed with an interactive tooltip instead of using the SVG [title element][1].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/title" + }, + "x1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The required primary (starting, often left) horizontal position channel, representing the area’s baseline, typically bound to the *x* scale. For areaX, setting this option disables the implicit stackX transform." + }, + "x2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The optional secondary (ending, often right) horizontal position channel, representing the area’s topline, typically bound to the *x* scale; if not specified, **x1** is used. For areaX, setting this option disables the implicit stackX transform." + }, + "y1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The required primary (starting, often bottom) vertical position channel, representing the area’s baseline, typically bound to the *y* scale. For areaY, setting this option disables the implicit stackY transform." + }, + "y2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The optional secondary (ending, often top) vertical position channel, representing the area’s topline, typically bound to the *y* scale; if not specified, **y1** is used. For areaY, setting this option disables the implicit stackY transform." + }, + "z": { + "$ref": "#/definitions/ChannelValue", + "description": "An optional ordinal channel for grouping data into (possibly stacked) series to be drawn as separate areas; defaults to **fill** if a channel, or\n**stroke** if a channel." + } + }, + "required": [ + "data", + "mark" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "$schema": { + "description": "A [JSON schema](http://json-schema.org/) URL for this specification, such as https://uwdata.github.io/mosaic/schema/latest.json. This property enables validation and autocomplete in editors with JSON schema support.", + "format": "uri", + "type": "string" + }, + "ariaDescription": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-description][1]; a constant textual description.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-description" + }, + "ariaHidden": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-hidden][1] state; a constant indicating whether the element is exposed to an accessibility API.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-hidden" + }, + "ariaLabel": { + "$ref": "#/definitions/ChannelValue", + "description": "The [aria-label][1]; a channel specifying short textual labels representing the value in the accessibility tree.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-label" + }, + "clip": { + "anyOf": [ + { + "const": "frame", + "type": "string" + }, + { + "const": "sphere", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to clip the mark; one of:\n\n- *frame* or true - clip to the plot’s frame (inner area)\n- *sphere* - clip to the projected sphere (*e.g.*, front hemisphere)\n- null or false - do not clip\n\nThe *sphere* clip option requires a geographic projection." + }, + "config": { + "$ref": "#/definitions/Config", + "description": "Configuration options." + }, + "curve": { + "anyOf": [ + { + "$ref": "#/definitions/Curve" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The curve (interpolation) method for connecting adjacent points. One of:\n\n- *basis* - a cubic basis spline (repeating the end points)\n- *basis-open* - an open cubic basis spline\n- *basis-closed* - a closed cubic basis spline\n- *bump-x* - a Bézier curve with horizontal tangents\n- *bump-y* - a Bézier curve with vertical tangents\n- *bundle* - a straightened cubic basis spline (suitable for lines only, not areas)\n- *cardinal* - a cubic cardinal spline (with one-sided differences at the ends)\n- *cardinal-open* - an open cubic cardinal spline\n- *cardinal-closed* - an closed cubic cardinal spline\n- *catmull-rom* - a cubic Catmull–Rom spline (with one-sided differences at the ends)\n- *catmull-rom-open* - an open cubic Catmull–Rom spline\n- *catmull-rom-closed* - a closed cubic Catmull–Rom spline\n- *linear* - a piecewise linear curve (*i.e.*, straight line segments)\n- *linear-closed* - a closed piecewise linear curve (*i.e.*, straight line segments)\n- *monotone-x* - a cubic spline that preserves monotonicity in *x*\n- *monotone-y* - a cubic spline that preserves monotonicity in *y*\n- *natural* - a natural cubic spline\n- *step* - a piecewise constant function where *y* changes at the midpoint of *x*\n- *step-after* - a piecewise constant function where *y* changes after *x*\n- *step-before* - a piecewise constant function where *x* changes after *y*" + }, + "data": { + "$ref": "#/definitions/Data", + "description": "Dataset definitions." + }, + "dx": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The horizontal offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "dy": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The vertical offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "facet": { + "anyOf": [ + { + "const": "auto", + "type": "string" + }, + { + "const": "include", + "type": "string" + }, + { + "const": "exclude", + "type": "string" + }, + { + "const": "super", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to enable or disable faceting; one of:\n\n- *auto* (default) - automatically determine if this mark should be faceted\n- *include* (or true) - draw the subset of the mark’s data in the current facet\n- *exclude* - draw the subset of the mark’s data *not* in the current facet\n- *super* - draw this mark in a single frame that covers all facets\n- null (or false) - repeat this mark’s data across all facets (*i.e.*, no faceting)\n\nWhen a mark uses *super* faceting, it is not allowed to use position scales (*x*, *y*, *fx*, or *fy*); *super* faceting is intended for decorations, such as labels and legends.\n\nWhen top-level faceting is used, the default *auto* setting is equivalent to *include* when the mark data is strictly equal to the top-level facet data; otherwise it is equivalent to null. When the *include* or *exclude* facet mode is chosen, the mark data must be parallel to the top-level facet data: the data must have the same length and order. If the data are not parallel, then the wrong data may be shown in each facet. The default\n*auto* therefore requires strict equality (`===`) for safety, and using the facet data as mark data is recommended when using the *exclude* facet mode. (To construct parallel data safely, consider using [*array*.map][1] on the facet data.)\n\nWhen mark-level faceting is used, the default *auto* setting is equivalent to *include*: the mark will be faceted if either the **fx** or **fy** channel option (or both) is specified. The null or false option will disable faceting, while *exclude* draws the subset of the mark’s data *not* in the current facet.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map" + }, + "facetAnchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "right", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "const": "left", + "type": "string" + }, + { + "const": "top-left", + "type": "string" + }, + { + "const": "top-right", + "type": "string" + }, + { + "const": "bottom-left", + "type": "string" + }, + { + "const": "bottom-right", + "type": "string" + }, + { + "const": "top-empty", + "type": "string" + }, + { + "const": "right-empty", + "type": "string" + }, + { + "const": "bottom-empty", + "type": "string" + }, + { + "const": "left-empty", + "type": "string" + }, + { + "const": "empty", + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to place the mark with respect to facets; one of:\n\n- null (default for most marks) - display the mark in each non-empty facet\n- *top*, *right*, *bottom*, or *left* - display the mark only in facets on the given side\n- *top-empty*, *right-empty*, *bottom-empty*, or *left-empty* (default for axis marks) - display the mark only in facets that have empty space on the given side: either the margin, or an empty facet\n- *empty* - display the mark in empty facets only" + }, + "fill": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill" + }, + "fillOpacity": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill-opacity][1]; a constant number between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill-opacity" + }, + "filter": { + "$ref": "#/definitions/ChannelValue", + "description": "Applies a transform to filter the mark’s index according to the given channel values; only truthy values are retained.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "fx": { + "$ref": "#/definitions/ChannelValue", + "description": "The horizontal facet position channel, for mark-level faceting, bound to the *fx* scale." + }, + "fy": { + "$ref": "#/definitions/ChannelValue", + "description": "The vertical facet position channel, for mark-level faceting, bound to the\n*fy* scale." + }, + "href": { + "$ref": "#/definitions/ChannelValue", + "description": "The [href][1]; a channel specifying URLs for clickable links. May be used in conjunction with the **target** option to open links in another window.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/href" + }, + "imageFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A CSS [filter][1]; a constant string used to adjust the rendering of images, such as *blur(5px)*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/filter" + }, + "margin": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four mark margins: **marginTop**,\n**marginRight**, **marginBottom**, and **marginLeft**; typically defaults to 0, except for axis marks." + }, + "marginBottom": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s bottom margin; the minimum distance in pixels between the bottom edges of the inner and outer plot area." + }, + "marginLeft": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s left margin; the minimum distance in pixels between the left edges of the inner and outer plot area." + }, + "marginRight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s right margin; the minimum distance in pixels between the right edges of the mark’s inner and outer plot area." + }, + "marginTop": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s top margin; the minimum distance in pixels between the top edges of the inner and outer plot area." + }, + "mark": { + "const": "areaX", + "description": "A vertically-oriented area mark, where the baseline and topline share\n**y** values, as in a time-series area chart where time goes up↑.\n\nIf neither **x1** nor **x2** is specified, an implicit stackX transform is applied and **x** defaults to the identity function, assuming that *data* = [*x₀*, *x₁*, *x₂*, …]. Otherwise, if only one of **x1** or **x2** is specified, the other defaults to **x**, which defaults to zero.\n\nIf an **interval** is specified, **y** values are binned accordingly, allowing zeroes for empty bins instead of interpolating across gaps. This is recommended to “regularize” sampled data; for example, if your data represents timestamped observations and you expect one observation per day, use *day* as the **interval**.\n\nVariable aesthetic channels are supported: if the **fill** is defined as a channel, the area will be broken into contiguous overlapping sections when the fill color changes; the fill color will apply to the interval spanning the current data point and the following data point. This behavior also applies to the **fillOpacity**, **stroke**, **strokeOpacity**,\n**strokeWidth**, **opacity**, **href**, **title**, and **ariaLabel** channels. When any of these channels are used, setting an explicit **z** channel (possibly to null) is strongly recommended.", + "type": "string" + }, + "meta": { + "$ref": "#/definitions/Meta", + "description": "Specification metadata." + }, + "mixBlendMode": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [mix-blend-mode][1]; a constant string specifying how to blend content such as *multiply*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode" + }, + "offset": { + "anyOf": [ + { + "$ref": "#/definitions/StackOffset" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "After stacking, an optional **offset** can be applied to translate and scale stacks, say to produce a streamgraph; defaults to null for a zero baseline (**y** = 0 for stackY, and **x** = 0 for stackX). If the *wiggle* offset is used, the default **order** changes to *inside-out*." + }, + "opacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally. For faster rendering, prefer the **strokeOpacity** or **fillOpacity** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/opacity" + }, + "order": { + "anyOf": [ + { + "$ref": "#/definitions/StackOrder" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The order in which stacks are layered; one of:\n\n- null (default) for input order\n- a named stack order method such as *inside-out* or *sum*\n- a field name, for natural order of the corresponding values\n- a function of data, for natural order of the corresponding values\n- an array of explicit **z** values in the desired order\n\nIf the *wiggle* **offset** is used, as for a streamgraph, the default changes to *inside-out*." + }, + "paintOrder": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [paint-order][1]; a constant string specifying the order in which the\n**fill**, **stroke**, and any markers are drawn; defaults to *normal*, which draws the fill, then stroke, then markers; defaults to *stroke* for the text mark to create a “halo” around text to improve legibility.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/paint-order" + }, + "params": { + "$ref": "#/definitions/Params", + "description": "Param and Selection definitions." + }, + "plotDefaults": { + "$ref": "#/definitions/PlotAttributes", + "description": "A default set of attributes to apply to all plot components." + }, + "pointerEvents": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [pointer-events][1] property; a constant string such as *none*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/pointer-events" + }, + "reverse": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Applies a transform to reverse the order of the mark’s index, say for reverse input order." + }, + "select": { + "$ref": "#/definitions/SelectFilter", + "description": "Applies a filter transform after data is loaded to highlight selected values only. For example, `first` and `last` select the first or last values of series only (using the *z* channel to separate series). Meanwhile, `nearestX` and `nearestY` select the point nearest to the pointer along the *x* or *y* channel dimension. Unlike Mosaic selections, a mark level *select* is internal to the mark only, and does not populate a param or selection value to be shared across clients.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "shapeRendering": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [shape-rendering][1]; a constant string such as *crispEdges*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/shape-rendering" + }, + "sort": { + "anyOf": [ + { + "$ref": "#/definitions/SortOrder" + }, + { + "$ref": "#/definitions/ChannelDomainSort" + } + ], + "description": "Either applies a transform to sort the mark’s index by the specified channel values, or imputes ordinal scale domains from this mark’s channels.\n\nWhen imputing ordinal scale domains from channel values, the **sort** option is an object whose keys are ordinal scale names such as *x* or *fx*, and whose values are channel names such as *y*, *y1*, or *y2*. For example, to impute the *y* scale’s domain from the associated *x* channel values in ascending order:\n\n```js sort: {y: \"x\"} ```\n\nFor different sort options for different scales, replace the channel name with a *value* object and per-scale options:\n\n```js sort: {y: {value: \"-x\"}} ```\n\nWhen sorting the mark’s index, the **sort** option is instead one of:\n\n- a channel value definition for sorting given values in ascending order\n- a {value, order} object for sorting given values\n- a {channel, order} object for sorting the named channel’s values" + }, + "stroke": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke" + }, + "strokeDasharray": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dasharray][1]; a constant number indicating the length in pixels of alternating dashes and gaps, or a constant string of numbers separated by spaces or commas (_e.g._, *10 2* for dashes of 10 pixels separated by gaps of 2 pixels), or *none* (the default) for no dashing\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dasharray" + }, + "strokeDashoffset": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dashoffset][1]; a constant indicating the offset in pixels of the first dash along the stroke; defaults to zero.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dashoffset" + }, + "strokeLinecap": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linecap][1]; a constant specifying how to cap stroked paths, such as *butt*, *round*, or *square*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linecap" + }, + "strokeLinejoin": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linejoin][1]; a constant specifying how to join stroked paths, such as *bevel*, *miter*, *miter-clip*, or *round*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linejoin" + }, + "strokeMiterlimit": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-miterlimit][1]; a constant number specifying how to limit the length of *miter* joins on stroked paths.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-miterlimit" + }, + "strokeOpacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-opacity" + }, + "strokeWidth": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-width][1]; a constant number in pixels, or a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-width" + }, + "target": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [target][1]; a constant string specifying the target window (_e.g._,\n*_blank*) for clickable links; used in conjunction with the **href** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/target" + }, + "tension": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The tension option only has an effect on bundle, cardinal and Catmull–Rom splines (*bundle*, *cardinal*, *cardinal-open*, *cardinal-closed*,\n*catmull-rom*, *catmull-rom-open*, and *catmull-rom-closed*). For bundle splines, it corresponds to [beta][1]; for cardinal splines, [tension][2]; for Catmull–Rom splines, [alpha][3].\n\n[1]: https://d3js.org/d3-shape/curve#curveBundle_beta [2]: https://d3js.org/d3-shape/curve#curveCardinal_tension [3]: https://d3js.org/d3-shape/curve#curveCatmullRom_alpha" + }, + "tip": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/TipPointer" + }, + { + "properties": { + "anchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The tip anchor specifies how to orient the tip box relative to its anchor position; it refers to the part of the tip box that is attached to the anchor point. For example, the *top-left* anchor places the top-left corner of tip box near the anchor position, hence placing the tip box below and to the right of the anchor position." + }, + "fontFamily": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font-family][1]; a constant; defaults to the plot’s font family, which is typically [*system-ui*][2].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-family [2]: https://drafts.csswg.org/css-fonts-4/#valdef-font-family-system-ui" + }, + "fontSize": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font size][1] in pixels; either a constant or a channel; defaults to the plot’s font size, which is typically 10. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-size" + }, + "fontStyle": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font style][1]; a constant; defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-style" + }, + "fontVariant": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font variant][1]; a constant; if the **text** channel contains numbers or dates, defaults to *tabular-nums* to facilitate comparing numbers; otherwise defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant" + }, + "fontWeight": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font weight][1]; a constant; defaults to the plot’s font weight, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight" + }, + "format": { + "additionalProperties": false, + "description": "How channel values are formatted for display. If a format is a string, it is interpreted as a (UTC) time format for temporal channels, and otherwise a number format.", + "properties": { + "ariaLabel": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fill": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fillOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fontSize": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fx": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fy": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "geometry": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "height": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "href": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "length": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "opacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "path": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "r": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "rotate": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "src": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "stroke": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeWidth": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "symbol": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "text": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "title": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "weight": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "width": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "z": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + } + }, + "type": "object" + }, + "frameAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The frame anchor specifies defaults for **x** and **y** based on the plot’s frame; it may be one of the four sides (*top*, *right*, *bottom*, *left*), one of the four corners (*top-left*, *top-right*, *bottom-right*,\n*bottom-left*), or the *middle* of the frame. For example, for tips distributed horizontally at the top of the frame:\n\n```js Plot.tip(data, {x: \"date\", frameAnchor: \"top\"}) ```" + }, + "lineHeight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line height in ems; defaults to 1. The line height affects the (typically vertical) separation between adjacent baselines of text, as well as the separation between the text and its anchor point." + }, + "lineWidth": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line width in ems (e.g., 10 for about 20 characters); defaults to infinity, disabling wrapping and clipping.\n\nIf **textOverflow** is null, lines will be wrapped at the specified length. If a line is split at a soft hyphen (\\xad), a hyphen (-) will be displayed at the end of the line. If **textOverflow** is not null, lines will be clipped according to the given strategy." + }, + "monospace": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, changes the default **fontFamily** to *monospace*, and uses simplified monospaced text metrics calculations." + }, + "pathFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The image filter for the tip’s box; defaults to a drop shadow." + }, + "pointer": { + "$ref": "#/definitions/TipPointer" + }, + "pointerSize": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The size of the tip’s pointer in pixels; defaults to 12." + }, + "preferredAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If an explicit tip anchor is not specified, an anchor is chosen automatically such that the tip fits within the plot’s frame; if the preferred anchor fits, it is chosen." + }, + "textAnchor": { + "anyOf": [ + { + "const": "start", + "type": "string" + }, + { + "const": "middle", + "type": "string" + }, + { + "const": "end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [text anchor][1] controls how text is aligned (typically horizontally) relative to its anchor point; it is one of *start*, *end*, or *middle*. If the frame anchor is *left*, *top-left*, or *bottom-left*, the default text anchor is *start*; if the frame anchor is *right*, *top-right*, or\n*bottom-right*, the default is *end*; otherwise it is *middle*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/text-anchor" + }, + "textOverflow": { + "anyOf": [ + { + "type": "null" + }, + { + "const": "clip", + "type": "string" + }, + { + "const": "ellipsis", + "type": "string" + }, + { + "const": "clip-start", + "type": "string" + }, + { + "const": "clip-end", + "type": "string" + }, + { + "const": "ellipsis-start", + "type": "string" + }, + { + "const": "ellipsis-middle", + "type": "string" + }, + { + "const": "ellipsis-end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How truncate (or wrap) lines of text longer than the given **lineWidth**; one of:\n\n- null (default) - preserve overflowing characters (and wrap if needed)\n- *clip* or *clip-end* - remove characters from the end\n- *clip-start* - remove characters from the start\n- *ellipsis* or *ellipsis-end* - replace characters from the end with an ellipsis (…)\n- *ellipsis-start* - replace characters from the start with an ellipsis (…)\n- *ellipsis-middle* - replace characters from the middle with an ellipsis (…)\n\nIf no **title** was specified, if text requires truncation, a title containing the non-truncated text will be implicitly added." + }, + "textPadding": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The padding around the text in pixels; defaults to 8." + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + } + }, + "type": "object" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to generate a tooltip for this mark, and any tip options." + }, + "title": { + "$ref": "#/definitions/ChannelValue", + "description": "The title; a channel specifying accessible, short textual descriptions as strings (possibly with newlines). If the tip option is specified, the title will be displayed with an interactive tooltip instead of using the SVG [title element][1].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/title" + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position (or length) channel, typically bound to the *x* scale.\n\nIf neither **x1** nor **x2** is specified, an implicit stackX transform is applied and **x** defaults to the identity function, assuming that *data* = [*x₀*, *x₁*, *x₂*, …]. Otherwise, if only one of **x1** or **x2** is specified, the other defaults to **x**, which defaults to zero." + }, + "x1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The required primary (starting, often left) horizontal position channel, representing the area’s baseline, typically bound to the *x* scale. For areaX, setting this option disables the implicit stackX transform." + }, + "x2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The optional secondary (ending, often right) horizontal position channel, representing the area’s topline, typically bound to the *x* scale; if not specified, **x1** is used. For areaX, setting this option disables the implicit stackX transform." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel, typically bound to the *y* scale; defaults to the zero-based index of the data [0, 1, 2, …]." + }, + "z": { + "$ref": "#/definitions/ChannelValue", + "description": "An optional ordinal channel for grouping data into (possibly stacked) series to be drawn as separate areas; defaults to **fill** if a channel, or\n**stroke** if a channel." + } + }, + "required": [ + "data", + "mark" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "$schema": { + "description": "A [JSON schema](http://json-schema.org/) URL for this specification, such as https://uwdata.github.io/mosaic/schema/latest.json. This property enables validation and autocomplete in editors with JSON schema support.", + "format": "uri", + "type": "string" + }, + "ariaDescription": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-description][1]; a constant textual description.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-description" + }, + "ariaHidden": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-hidden][1] state; a constant indicating whether the element is exposed to an accessibility API.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-hidden" + }, + "ariaLabel": { + "$ref": "#/definitions/ChannelValue", + "description": "The [aria-label][1]; a channel specifying short textual labels representing the value in the accessibility tree.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-label" + }, + "clip": { + "anyOf": [ + { + "const": "frame", + "type": "string" + }, + { + "const": "sphere", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to clip the mark; one of:\n\n- *frame* or true - clip to the plot’s frame (inner area)\n- *sphere* - clip to the projected sphere (*e.g.*, front hemisphere)\n- null or false - do not clip\n\nThe *sphere* clip option requires a geographic projection." + }, + "config": { + "$ref": "#/definitions/Config", + "description": "Configuration options." + }, + "curve": { + "anyOf": [ + { + "$ref": "#/definitions/Curve" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The curve (interpolation) method for connecting adjacent points. One of:\n\n- *basis* - a cubic basis spline (repeating the end points)\n- *basis-open* - an open cubic basis spline\n- *basis-closed* - a closed cubic basis spline\n- *bump-x* - a Bézier curve with horizontal tangents\n- *bump-y* - a Bézier curve with vertical tangents\n- *bundle* - a straightened cubic basis spline (suitable for lines only, not areas)\n- *cardinal* - a cubic cardinal spline (with one-sided differences at the ends)\n- *cardinal-open* - an open cubic cardinal spline\n- *cardinal-closed* - an closed cubic cardinal spline\n- *catmull-rom* - a cubic Catmull–Rom spline (with one-sided differences at the ends)\n- *catmull-rom-open* - an open cubic Catmull–Rom spline\n- *catmull-rom-closed* - a closed cubic Catmull–Rom spline\n- *linear* - a piecewise linear curve (*i.e.*, straight line segments)\n- *linear-closed* - a closed piecewise linear curve (*i.e.*, straight line segments)\n- *monotone-x* - a cubic spline that preserves monotonicity in *x*\n- *monotone-y* - a cubic spline that preserves monotonicity in *y*\n- *natural* - a natural cubic spline\n- *step* - a piecewise constant function where *y* changes at the midpoint of *x*\n- *step-after* - a piecewise constant function where *y* changes after *x*\n- *step-before* - a piecewise constant function where *x* changes after *y*" + }, + "data": { + "$ref": "#/definitions/Data", + "description": "Dataset definitions." + }, + "dx": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The horizontal offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "dy": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The vertical offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "facet": { + "anyOf": [ + { + "const": "auto", + "type": "string" + }, + { + "const": "include", + "type": "string" + }, + { + "const": "exclude", + "type": "string" + }, + { + "const": "super", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to enable or disable faceting; one of:\n\n- *auto* (default) - automatically determine if this mark should be faceted\n- *include* (or true) - draw the subset of the mark’s data in the current facet\n- *exclude* - draw the subset of the mark’s data *not* in the current facet\n- *super* - draw this mark in a single frame that covers all facets\n- null (or false) - repeat this mark’s data across all facets (*i.e.*, no faceting)\n\nWhen a mark uses *super* faceting, it is not allowed to use position scales (*x*, *y*, *fx*, or *fy*); *super* faceting is intended for decorations, such as labels and legends.\n\nWhen top-level faceting is used, the default *auto* setting is equivalent to *include* when the mark data is strictly equal to the top-level facet data; otherwise it is equivalent to null. When the *include* or *exclude* facet mode is chosen, the mark data must be parallel to the top-level facet data: the data must have the same length and order. If the data are not parallel, then the wrong data may be shown in each facet. The default\n*auto* therefore requires strict equality (`===`) for safety, and using the facet data as mark data is recommended when using the *exclude* facet mode. (To construct parallel data safely, consider using [*array*.map][1] on the facet data.)\n\nWhen mark-level faceting is used, the default *auto* setting is equivalent to *include*: the mark will be faceted if either the **fx** or **fy** channel option (or both) is specified. The null or false option will disable faceting, while *exclude* draws the subset of the mark’s data *not* in the current facet.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map" + }, + "facetAnchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "right", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "const": "left", + "type": "string" + }, + { + "const": "top-left", + "type": "string" + }, + { + "const": "top-right", + "type": "string" + }, + { + "const": "bottom-left", + "type": "string" + }, + { + "const": "bottom-right", + "type": "string" + }, + { + "const": "top-empty", + "type": "string" + }, + { + "const": "right-empty", + "type": "string" + }, + { + "const": "bottom-empty", + "type": "string" + }, + { + "const": "left-empty", + "type": "string" + }, + { + "const": "empty", + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to place the mark with respect to facets; one of:\n\n- null (default for most marks) - display the mark in each non-empty facet\n- *top*, *right*, *bottom*, or *left* - display the mark only in facets on the given side\n- *top-empty*, *right-empty*, *bottom-empty*, or *left-empty* (default for axis marks) - display the mark only in facets that have empty space on the given side: either the margin, or an empty facet\n- *empty* - display the mark in empty facets only" + }, + "fill": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill" + }, + "fillOpacity": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill-opacity][1]; a constant number between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill-opacity" + }, + "filter": { + "$ref": "#/definitions/ChannelValue", + "description": "Applies a transform to filter the mark’s index according to the given channel values; only truthy values are retained.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "fx": { + "$ref": "#/definitions/ChannelValue", + "description": "The horizontal facet position channel, for mark-level faceting, bound to the *fx* scale." + }, + "fy": { + "$ref": "#/definitions/ChannelValue", + "description": "The vertical facet position channel, for mark-level faceting, bound to the\n*fy* scale." + }, + "href": { + "$ref": "#/definitions/ChannelValue", + "description": "The [href][1]; a channel specifying URLs for clickable links. May be used in conjunction with the **target** option to open links in another window.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/href" + }, + "imageFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A CSS [filter][1]; a constant string used to adjust the rendering of images, such as *blur(5px)*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/filter" + }, + "margin": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four mark margins: **marginTop**,\n**marginRight**, **marginBottom**, and **marginLeft**; typically defaults to 0, except for axis marks." + }, + "marginBottom": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s bottom margin; the minimum distance in pixels between the bottom edges of the inner and outer plot area." + }, + "marginLeft": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s left margin; the minimum distance in pixels between the left edges of the inner and outer plot area." + }, + "marginRight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s right margin; the minimum distance in pixels between the right edges of the mark’s inner and outer plot area." + }, + "marginTop": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s top margin; the minimum distance in pixels between the top edges of the inner and outer plot area." + }, + "mark": { + "const": "areaY", + "description": "A horizontally-oriented area mark, where the baseline and topline share\n**x** values, as in a time-series area chart where time goes right→.\n\nIf neither **y1** nor **y2** is specified, an implicit stackY transform is applied and **y** defaults to the identity function, assuming that *data* = [*y₀*, *y₁*, *y₂*, …]. Otherwise, if only one of **y1** or **y2** is specified, the other defaults to **y**, which defaults to zero.\n\nIf an **interval** is specified, **x** values are binned accordingly, allowing zeroes for empty bins instead of interpolating across gaps. This is recommended to “regularize” sampled data; for example, if your data represents timestamped observations and you expect one observation per day, use *day* as the **interval**.\n\nVariable aesthetic channels are supported: if the **fill** is defined as a channel, the area will be broken into contiguous overlapping sections when the fill color changes; the fill color will apply to the interval spanning the current data point and the following data point. This behavior also applies to the **fillOpacity**, **stroke**, **strokeOpacity**,\n**strokeWidth**, **opacity**, **href**, **title**, and **ariaLabel** channels. When any of these channels are used, setting an explicit **z** channel (possibly to null) is strongly recommended.", + "type": "string" + }, + "meta": { + "$ref": "#/definitions/Meta", + "description": "Specification metadata." + }, + "mixBlendMode": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [mix-blend-mode][1]; a constant string specifying how to blend content such as *multiply*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode" + }, + "offset": { + "anyOf": [ + { + "$ref": "#/definitions/StackOffset" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "After stacking, an optional **offset** can be applied to translate and scale stacks, say to produce a streamgraph; defaults to null for a zero baseline (**y** = 0 for stackY, and **x** = 0 for stackX). If the *wiggle* offset is used, the default **order** changes to *inside-out*." + }, + "opacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally. For faster rendering, prefer the **strokeOpacity** or **fillOpacity** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/opacity" + }, + "order": { + "anyOf": [ + { + "$ref": "#/definitions/StackOrder" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The order in which stacks are layered; one of:\n\n- null (default) for input order\n- a named stack order method such as *inside-out* or *sum*\n- a field name, for natural order of the corresponding values\n- a function of data, for natural order of the corresponding values\n- an array of explicit **z** values in the desired order\n\nIf the *wiggle* **offset** is used, as for a streamgraph, the default changes to *inside-out*." + }, + "paintOrder": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [paint-order][1]; a constant string specifying the order in which the\n**fill**, **stroke**, and any markers are drawn; defaults to *normal*, which draws the fill, then stroke, then markers; defaults to *stroke* for the text mark to create a “halo” around text to improve legibility.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/paint-order" + }, + "params": { + "$ref": "#/definitions/Params", + "description": "Param and Selection definitions." + }, + "plotDefaults": { + "$ref": "#/definitions/PlotAttributes", + "description": "A default set of attributes to apply to all plot components." + }, + "pointerEvents": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [pointer-events][1] property; a constant string such as *none*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/pointer-events" + }, + "reverse": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Applies a transform to reverse the order of the mark’s index, say for reverse input order." + }, + "select": { + "$ref": "#/definitions/SelectFilter", + "description": "Applies a filter transform after data is loaded to highlight selected values only. For example, `first` and `last` select the first or last values of series only (using the *z* channel to separate series). Meanwhile, `nearestX` and `nearestY` select the point nearest to the pointer along the *x* or *y* channel dimension. Unlike Mosaic selections, a mark level *select* is internal to the mark only, and does not populate a param or selection value to be shared across clients.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "shapeRendering": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [shape-rendering][1]; a constant string such as *crispEdges*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/shape-rendering" + }, + "sort": { + "anyOf": [ + { + "$ref": "#/definitions/SortOrder" + }, + { + "$ref": "#/definitions/ChannelDomainSort" + } + ], + "description": "Either applies a transform to sort the mark’s index by the specified channel values, or imputes ordinal scale domains from this mark’s channels.\n\nWhen imputing ordinal scale domains from channel values, the **sort** option is an object whose keys are ordinal scale names such as *x* or *fx*, and whose values are channel names such as *y*, *y1*, or *y2*. For example, to impute the *y* scale’s domain from the associated *x* channel values in ascending order:\n\n```js sort: {y: \"x\"} ```\n\nFor different sort options for different scales, replace the channel name with a *value* object and per-scale options:\n\n```js sort: {y: {value: \"-x\"}} ```\n\nWhen sorting the mark’s index, the **sort** option is instead one of:\n\n- a channel value definition for sorting given values in ascending order\n- a {value, order} object for sorting given values\n- a {channel, order} object for sorting the named channel’s values" + }, + "stroke": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke" + }, + "strokeDasharray": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dasharray][1]; a constant number indicating the length in pixels of alternating dashes and gaps, or a constant string of numbers separated by spaces or commas (_e.g._, *10 2* for dashes of 10 pixels separated by gaps of 2 pixels), or *none* (the default) for no dashing\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dasharray" + }, + "strokeDashoffset": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dashoffset][1]; a constant indicating the offset in pixels of the first dash along the stroke; defaults to zero.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dashoffset" + }, + "strokeLinecap": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linecap][1]; a constant specifying how to cap stroked paths, such as *butt*, *round*, or *square*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linecap" + }, + "strokeLinejoin": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linejoin][1]; a constant specifying how to join stroked paths, such as *bevel*, *miter*, *miter-clip*, or *round*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linejoin" + }, + "strokeMiterlimit": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-miterlimit][1]; a constant number specifying how to limit the length of *miter* joins on stroked paths.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-miterlimit" + }, + "strokeOpacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-opacity" + }, + "strokeWidth": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-width][1]; a constant number in pixels, or a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-width" + }, + "target": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [target][1]; a constant string specifying the target window (_e.g._,\n*_blank*) for clickable links; used in conjunction with the **href** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/target" + }, + "tension": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The tension option only has an effect on bundle, cardinal and Catmull–Rom splines (*bundle*, *cardinal*, *cardinal-open*, *cardinal-closed*,\n*catmull-rom*, *catmull-rom-open*, and *catmull-rom-closed*). For bundle splines, it corresponds to [beta][1]; for cardinal splines, [tension][2]; for Catmull–Rom splines, [alpha][3].\n\n[1]: https://d3js.org/d3-shape/curve#curveBundle_beta [2]: https://d3js.org/d3-shape/curve#curveCardinal_tension [3]: https://d3js.org/d3-shape/curve#curveCatmullRom_alpha" + }, + "tip": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/TipPointer" + }, + { + "properties": { + "anchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The tip anchor specifies how to orient the tip box relative to its anchor position; it refers to the part of the tip box that is attached to the anchor point. For example, the *top-left* anchor places the top-left corner of tip box near the anchor position, hence placing the tip box below and to the right of the anchor position." + }, + "fontFamily": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font-family][1]; a constant; defaults to the plot’s font family, which is typically [*system-ui*][2].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-family [2]: https://drafts.csswg.org/css-fonts-4/#valdef-font-family-system-ui" + }, + "fontSize": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font size][1] in pixels; either a constant or a channel; defaults to the plot’s font size, which is typically 10. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-size" + }, + "fontStyle": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font style][1]; a constant; defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-style" + }, + "fontVariant": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font variant][1]; a constant; if the **text** channel contains numbers or dates, defaults to *tabular-nums* to facilitate comparing numbers; otherwise defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant" + }, + "fontWeight": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font weight][1]; a constant; defaults to the plot’s font weight, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight" + }, + "format": { + "additionalProperties": false, + "description": "How channel values are formatted for display. If a format is a string, it is interpreted as a (UTC) time format for temporal channels, and otherwise a number format.", + "properties": { + "ariaLabel": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fill": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fillOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fontSize": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fx": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fy": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "geometry": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "height": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "href": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "length": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "opacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "path": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "r": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "rotate": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "src": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "stroke": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeWidth": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "symbol": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "text": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "title": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "weight": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "width": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "z": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + } + }, + "type": "object" + }, + "frameAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The frame anchor specifies defaults for **x** and **y** based on the plot’s frame; it may be one of the four sides (*top*, *right*, *bottom*, *left*), one of the four corners (*top-left*, *top-right*, *bottom-right*,\n*bottom-left*), or the *middle* of the frame. For example, for tips distributed horizontally at the top of the frame:\n\n```js Plot.tip(data, {x: \"date\", frameAnchor: \"top\"}) ```" + }, + "lineHeight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line height in ems; defaults to 1. The line height affects the (typically vertical) separation between adjacent baselines of text, as well as the separation between the text and its anchor point." + }, + "lineWidth": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line width in ems (e.g., 10 for about 20 characters); defaults to infinity, disabling wrapping and clipping.\n\nIf **textOverflow** is null, lines will be wrapped at the specified length. If a line is split at a soft hyphen (\\xad), a hyphen (-) will be displayed at the end of the line. If **textOverflow** is not null, lines will be clipped according to the given strategy." + }, + "monospace": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, changes the default **fontFamily** to *monospace*, and uses simplified monospaced text metrics calculations." + }, + "pathFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The image filter for the tip’s box; defaults to a drop shadow." + }, + "pointer": { + "$ref": "#/definitions/TipPointer" + }, + "pointerSize": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The size of the tip’s pointer in pixels; defaults to 12." + }, + "preferredAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If an explicit tip anchor is not specified, an anchor is chosen automatically such that the tip fits within the plot’s frame; if the preferred anchor fits, it is chosen." + }, + "textAnchor": { + "anyOf": [ + { + "const": "start", + "type": "string" + }, + { + "const": "middle", + "type": "string" + }, + { + "const": "end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [text anchor][1] controls how text is aligned (typically horizontally) relative to its anchor point; it is one of *start*, *end*, or *middle*. If the frame anchor is *left*, *top-left*, or *bottom-left*, the default text anchor is *start*; if the frame anchor is *right*, *top-right*, or\n*bottom-right*, the default is *end*; otherwise it is *middle*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/text-anchor" + }, + "textOverflow": { + "anyOf": [ + { + "type": "null" + }, + { + "const": "clip", + "type": "string" + }, + { + "const": "ellipsis", + "type": "string" + }, + { + "const": "clip-start", + "type": "string" + }, + { + "const": "clip-end", + "type": "string" + }, + { + "const": "ellipsis-start", + "type": "string" + }, + { + "const": "ellipsis-middle", + "type": "string" + }, + { + "const": "ellipsis-end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How truncate (or wrap) lines of text longer than the given **lineWidth**; one of:\n\n- null (default) - preserve overflowing characters (and wrap if needed)\n- *clip* or *clip-end* - remove characters from the end\n- *clip-start* - remove characters from the start\n- *ellipsis* or *ellipsis-end* - replace characters from the end with an ellipsis (…)\n- *ellipsis-start* - replace characters from the start with an ellipsis (…)\n- *ellipsis-middle* - replace characters from the middle with an ellipsis (…)\n\nIf no **title** was specified, if text requires truncation, a title containing the non-truncated text will be implicitly added." + }, + "textPadding": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The padding around the text in pixels; defaults to 8." + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + } + }, + "type": "object" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to generate a tooltip for this mark, and any tip options." + }, + "title": { + "$ref": "#/definitions/ChannelValue", + "description": "The title; a channel specifying accessible, short textual descriptions as strings (possibly with newlines). If the tip option is specified, the title will be displayed with an interactive tooltip instead of using the SVG [title element][1].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/title" + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel, typically bound to the *x* scale; defaults to the zero-based index of the data [0, 1, 2, …]." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position (or length) channel, typically bound to the *y* scale.\n\nIf neither **y1** nor **y2** is specified, an implicit stackY transform is applied and **y** defaults to the identity function, assuming that *data* = [*y₀*, *y₁*, *y₂*, …]. Otherwise, if only one of **y1** or **y2** is specified, the other defaults to **y**, which defaults to zero." + }, + "y1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The required primary (starting, often bottom) vertical position channel, representing the area’s baseline, typically bound to the *y* scale. For areaY, setting this option disables the implicit stackY transform." + }, + "y2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The optional secondary (ending, often top) vertical position channel, representing the area’s topline, typically bound to the *y* scale; if not specified, **y1** is used. For areaY, setting this option disables the implicit stackY transform." + }, + "z": { + "$ref": "#/definitions/ChannelValue", + "description": "An optional ordinal channel for grouping data into (possibly stacked) series to be drawn as separate areas; defaults to **fill** if a channel, or\n**stroke** if a channel." + } + }, + "required": [ + "data", + "mark" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "$schema": { + "description": "A [JSON schema](http://json-schema.org/) URL for this specification, such as https://uwdata.github.io/mosaic/schema/latest.json. This property enables validation and autocomplete in editors with JSON schema support.", + "format": "uri", + "type": "string" + }, + "ariaDescription": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-description][1]; a constant textual description.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-description" + }, + "ariaHidden": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-hidden][1] state; a constant indicating whether the element is exposed to an accessibility API.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-hidden" + }, + "ariaLabel": { + "$ref": "#/definitions/ChannelValue", + "description": "The [aria-label][1]; a channel specifying short textual labels representing the value in the accessibility tree.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-label" + }, + "bend": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The angle, a constant in degrees, between the straight line intersecting the arrow’s two control points and the outgoing tangent direction of the arrow from the start point. The angle must be within ±90°; a positive angle will produce a clockwise curve, while a negative angle will produce a counterclockwise curve; zero (the default) will produce a straight line. Use true for 22.5°." + }, + "clip": { + "anyOf": [ + { + "const": "frame", + "type": "string" + }, + { + "const": "sphere", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to clip the mark; one of:\n\n- *frame* or true - clip to the plot’s frame (inner area)\n- *sphere* - clip to the projected sphere (*e.g.*, front hemisphere)\n- null or false - do not clip\n\nThe *sphere* clip option requires a geographic projection." + }, + "config": { + "$ref": "#/definitions/Config", + "description": "Configuration options." + }, + "data": { + "$ref": "#/definitions/Data", + "description": "Dataset definitions." + }, + "dx": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The horizontal offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "dy": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The vertical offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "facet": { + "anyOf": [ + { + "const": "auto", + "type": "string" + }, + { + "const": "include", + "type": "string" + }, + { + "const": "exclude", + "type": "string" + }, + { + "const": "super", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to enable or disable faceting; one of:\n\n- *auto* (default) - automatically determine if this mark should be faceted\n- *include* (or true) - draw the subset of the mark’s data in the current facet\n- *exclude* - draw the subset of the mark’s data *not* in the current facet\n- *super* - draw this mark in a single frame that covers all facets\n- null (or false) - repeat this mark’s data across all facets (*i.e.*, no faceting)\n\nWhen a mark uses *super* faceting, it is not allowed to use position scales (*x*, *y*, *fx*, or *fy*); *super* faceting is intended for decorations, such as labels and legends.\n\nWhen top-level faceting is used, the default *auto* setting is equivalent to *include* when the mark data is strictly equal to the top-level facet data; otherwise it is equivalent to null. When the *include* or *exclude* facet mode is chosen, the mark data must be parallel to the top-level facet data: the data must have the same length and order. If the data are not parallel, then the wrong data may be shown in each facet. The default\n*auto* therefore requires strict equality (`===`) for safety, and using the facet data as mark data is recommended when using the *exclude* facet mode. (To construct parallel data safely, consider using [*array*.map][1] on the facet data.)\n\nWhen mark-level faceting is used, the default *auto* setting is equivalent to *include*: the mark will be faceted if either the **fx** or **fy** channel option (or both) is specified. The null or false option will disable faceting, while *exclude* draws the subset of the mark’s data *not* in the current facet.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map" + }, + "facetAnchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "right", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "const": "left", + "type": "string" + }, + { + "const": "top-left", + "type": "string" + }, + { + "const": "top-right", + "type": "string" + }, + { + "const": "bottom-left", + "type": "string" + }, + { + "const": "bottom-right", + "type": "string" + }, + { + "const": "top-empty", + "type": "string" + }, + { + "const": "right-empty", + "type": "string" + }, + { + "const": "bottom-empty", + "type": "string" + }, + { + "const": "left-empty", + "type": "string" + }, + { + "const": "empty", + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to place the mark with respect to facets; one of:\n\n- null (default for most marks) - display the mark in each non-empty facet\n- *top*, *right*, *bottom*, or *left* - display the mark only in facets on the given side\n- *top-empty*, *right-empty*, *bottom-empty*, or *left-empty* (default for axis marks) - display the mark only in facets that have empty space on the given side: either the margin, or an empty facet\n- *empty* - display the mark in empty facets only" + }, + "fill": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill" + }, + "fillOpacity": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill-opacity][1]; a constant number between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill-opacity" + }, + "filter": { + "$ref": "#/definitions/ChannelValue", + "description": "Applies a transform to filter the mark’s index according to the given channel values; only truthy values are retained.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "fx": { + "$ref": "#/definitions/ChannelValue", + "description": "The horizontal facet position channel, for mark-level faceting, bound to the *fx* scale." + }, + "fy": { + "$ref": "#/definitions/ChannelValue", + "description": "The vertical facet position channel, for mark-level faceting, bound to the\n*fy* scale." + }, + "headAngle": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How pointy the arrowhead is, in degrees; a constant typically between 0° and 180°, and defaults to 60°." + }, + "headLength": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The size of the arrowhead relative to the **strokeWidth**; a constant. Assuming the default of stroke width 1.5px, this is the length of the arrowhead’s side in pixels." + }, + "href": { + "$ref": "#/definitions/ChannelValue", + "description": "The [href][1]; a channel specifying URLs for clickable links. May be used in conjunction with the **target** option to open links in another window.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/href" + }, + "imageFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A CSS [filter][1]; a constant string used to adjust the rendering of images, such as *blur(5px)*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/filter" + }, + "inset": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for **insetStart** and **insetEnd**." + }, + "insetEnd": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The ending inset, a constant in pixels; defaults to 0. A positive inset shortens the arrow by moving the ending point towards the starting point, while a negative inset extends it by moving the ending point in the opposite direction. A positive ending inset may be useful if the arrow points to a dot." + }, + "insetStart": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The starting inset, a constant in pixels; defaults to 0. A positive inset shortens the arrow by moving the starting point towards the endpoint point, while a negative inset extends it by moving the starting point in the opposite direction. A positive starting inset may be useful if the arrow emerges from a dot." + }, + "margin": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four mark margins: **marginTop**,\n**marginRight**, **marginBottom**, and **marginLeft**; typically defaults to 0, except for axis marks." + }, + "marginBottom": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s bottom margin; the minimum distance in pixels between the bottom edges of the inner and outer plot area." + }, + "marginLeft": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s left margin; the minimum distance in pixels between the left edges of the inner and outer plot area." + }, + "marginRight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s right margin; the minimum distance in pixels between the right edges of the mark’s inner and outer plot area." + }, + "marginTop": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s top margin; the minimum distance in pixels between the top edges of the inner and outer plot area." + }, + "mark": { + "const": "arrow", + "description": "An arrow mark, drawing (possibly swoopy) arrows connecting pairs of points.", + "type": "string" + }, + "meta": { + "$ref": "#/definitions/Meta", + "description": "Specification metadata." + }, + "mixBlendMode": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [mix-blend-mode][1]; a constant string specifying how to blend content such as *multiply*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode" + }, + "opacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally. For faster rendering, prefer the **strokeOpacity** or **fillOpacity** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/opacity" + }, + "paintOrder": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [paint-order][1]; a constant string specifying the order in which the\n**fill**, **stroke**, and any markers are drawn; defaults to *normal*, which draws the fill, then stroke, then markers; defaults to *stroke* for the text mark to create a “halo” around text to improve legibility.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/paint-order" + }, + "params": { + "$ref": "#/definitions/Params", + "description": "Param and Selection definitions." + }, + "plotDefaults": { + "$ref": "#/definitions/PlotAttributes", + "description": "A default set of attributes to apply to all plot components." + }, + "pointerEvents": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [pointer-events][1] property; a constant string such as *none*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/pointer-events" + }, + "reverse": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Applies a transform to reverse the order of the mark’s index, say for reverse input order." + }, + "select": { + "$ref": "#/definitions/SelectFilter", + "description": "Applies a filter transform after data is loaded to highlight selected values only. For example, `first` and `last` select the first or last values of series only (using the *z* channel to separate series). Meanwhile, `nearestX` and `nearestY` select the point nearest to the pointer along the *x* or *y* channel dimension. Unlike Mosaic selections, a mark level *select* is internal to the mark only, and does not populate a param or selection value to be shared across clients.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "shapeRendering": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [shape-rendering][1]; a constant string such as *crispEdges*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/shape-rendering" + }, + "sort": { + "anyOf": [ + { + "$ref": "#/definitions/SortOrder" + }, + { + "$ref": "#/definitions/ChannelDomainSort" + } + ], + "description": "Either applies a transform to sort the mark’s index by the specified channel values, or imputes ordinal scale domains from this mark’s channels.\n\nWhen imputing ordinal scale domains from channel values, the **sort** option is an object whose keys are ordinal scale names such as *x* or *fx*, and whose values are channel names such as *y*, *y1*, or *y2*. For example, to impute the *y* scale’s domain from the associated *x* channel values in ascending order:\n\n```js sort: {y: \"x\"} ```\n\nFor different sort options for different scales, replace the channel name with a *value* object and per-scale options:\n\n```js sort: {y: {value: \"-x\"}} ```\n\nWhen sorting the mark’s index, the **sort** option is instead one of:\n\n- a channel value definition for sorting given values in ascending order\n- a {value, order} object for sorting given values\n- a {channel, order} object for sorting the named channel’s values" + }, + "stroke": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke" + }, + "strokeDasharray": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dasharray][1]; a constant number indicating the length in pixels of alternating dashes and gaps, or a constant string of numbers separated by spaces or commas (_e.g._, *10 2* for dashes of 10 pixels separated by gaps of 2 pixels), or *none* (the default) for no dashing\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dasharray" + }, + "strokeDashoffset": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dashoffset][1]; a constant indicating the offset in pixels of the first dash along the stroke; defaults to zero.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dashoffset" + }, + "strokeLinecap": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linecap][1]; a constant specifying how to cap stroked paths, such as *butt*, *round*, or *square*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linecap" + }, + "strokeLinejoin": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linejoin][1]; a constant specifying how to join stroked paths, such as *bevel*, *miter*, *miter-clip*, or *round*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linejoin" + }, + "strokeMiterlimit": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-miterlimit][1]; a constant number specifying how to limit the length of *miter* joins on stroked paths.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-miterlimit" + }, + "strokeOpacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-opacity" + }, + "strokeWidth": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-width][1]; a constant number in pixels, or a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-width" + }, + "sweep": { + "anyOf": [ + { + "type": "number" + }, + { + "const": "+x", + "type": "string" + }, + { + "const": "-x", + "type": "string" + }, + { + "const": "+y", + "type": "string" + }, + { + "const": "-y", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The sweep order; defaults to 1 indicating a positive (clockwise) bend angle; -1 indicates a negative (anticlockwise) bend angle; 0 effectively clears the bend angle. If set to *-x*, the bend angle is flipped when the ending point is to the left of the starting point — ensuring all arrows bulge up (down if bend is negative); if set to *-y*, the bend angle is flipped when the ending point is above the starting point — ensuring all arrows bulge right (left if bend is negative); the sign is negated for\n*+x* and *+y*." + }, + "target": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [target][1]; a constant string specifying the target window (_e.g._,\n*_blank*) for clickable links; used in conjunction with the **href** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/target" + }, + "tip": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/TipPointer" + }, + { + "properties": { + "anchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The tip anchor specifies how to orient the tip box relative to its anchor position; it refers to the part of the tip box that is attached to the anchor point. For example, the *top-left* anchor places the top-left corner of tip box near the anchor position, hence placing the tip box below and to the right of the anchor position." + }, + "fontFamily": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font-family][1]; a constant; defaults to the plot’s font family, which is typically [*system-ui*][2].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-family [2]: https://drafts.csswg.org/css-fonts-4/#valdef-font-family-system-ui" + }, + "fontSize": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font size][1] in pixels; either a constant or a channel; defaults to the plot’s font size, which is typically 10. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-size" + }, + "fontStyle": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font style][1]; a constant; defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-style" + }, + "fontVariant": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font variant][1]; a constant; if the **text** channel contains numbers or dates, defaults to *tabular-nums* to facilitate comparing numbers; otherwise defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant" + }, + "fontWeight": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font weight][1]; a constant; defaults to the plot’s font weight, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight" + }, + "format": { + "additionalProperties": false, + "description": "How channel values are formatted for display. If a format is a string, it is interpreted as a (UTC) time format for temporal channels, and otherwise a number format.", + "properties": { + "ariaLabel": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fill": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fillOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fontSize": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fx": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fy": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "geometry": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "height": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "href": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "length": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "opacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "path": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "r": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "rotate": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "src": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "stroke": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeWidth": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "symbol": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "text": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "title": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "weight": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "width": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "z": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + } + }, + "type": "object" + }, + "frameAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The frame anchor specifies defaults for **x** and **y** based on the plot’s frame; it may be one of the four sides (*top*, *right*, *bottom*, *left*), one of the four corners (*top-left*, *top-right*, *bottom-right*,\n*bottom-left*), or the *middle* of the frame. For example, for tips distributed horizontally at the top of the frame:\n\n```js Plot.tip(data, {x: \"date\", frameAnchor: \"top\"}) ```" + }, + "lineHeight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line height in ems; defaults to 1. The line height affects the (typically vertical) separation between adjacent baselines of text, as well as the separation between the text and its anchor point." + }, + "lineWidth": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line width in ems (e.g., 10 for about 20 characters); defaults to infinity, disabling wrapping and clipping.\n\nIf **textOverflow** is null, lines will be wrapped at the specified length. If a line is split at a soft hyphen (\\xad), a hyphen (-) will be displayed at the end of the line. If **textOverflow** is not null, lines will be clipped according to the given strategy." + }, + "monospace": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, changes the default **fontFamily** to *monospace*, and uses simplified monospaced text metrics calculations." + }, + "pathFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The image filter for the tip’s box; defaults to a drop shadow." + }, + "pointer": { + "$ref": "#/definitions/TipPointer" + }, + "pointerSize": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The size of the tip’s pointer in pixels; defaults to 12." + }, + "preferredAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If an explicit tip anchor is not specified, an anchor is chosen automatically such that the tip fits within the plot’s frame; if the preferred anchor fits, it is chosen." + }, + "textAnchor": { + "anyOf": [ + { + "const": "start", + "type": "string" + }, + { + "const": "middle", + "type": "string" + }, + { + "const": "end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [text anchor][1] controls how text is aligned (typically horizontally) relative to its anchor point; it is one of *start*, *end*, or *middle*. If the frame anchor is *left*, *top-left*, or *bottom-left*, the default text anchor is *start*; if the frame anchor is *right*, *top-right*, or\n*bottom-right*, the default is *end*; otherwise it is *middle*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/text-anchor" + }, + "textOverflow": { + "anyOf": [ + { + "type": "null" + }, + { + "const": "clip", + "type": "string" + }, + { + "const": "ellipsis", + "type": "string" + }, + { + "const": "clip-start", + "type": "string" + }, + { + "const": "clip-end", + "type": "string" + }, + { + "const": "ellipsis-start", + "type": "string" + }, + { + "const": "ellipsis-middle", + "type": "string" + }, + { + "const": "ellipsis-end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How truncate (or wrap) lines of text longer than the given **lineWidth**; one of:\n\n- null (default) - preserve overflowing characters (and wrap if needed)\n- *clip* or *clip-end* - remove characters from the end\n- *clip-start* - remove characters from the start\n- *ellipsis* or *ellipsis-end* - replace characters from the end with an ellipsis (…)\n- *ellipsis-start* - replace characters from the start with an ellipsis (…)\n- *ellipsis-middle* - replace characters from the middle with an ellipsis (…)\n\nIf no **title** was specified, if text requires truncation, a title containing the non-truncated text will be implicitly added." + }, + "textPadding": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The padding around the text in pixels; defaults to 8." + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + } + }, + "type": "object" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to generate a tooltip for this mark, and any tip options." + }, + "title": { + "$ref": "#/definitions/ChannelValue", + "description": "The title; a channel specifying accessible, short textual descriptions as strings (possibly with newlines). If the tip option is specified, the title will be displayed with an interactive tooltip instead of using the SVG [title element][1].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/title" + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position, for vertical arrows; typically bound to the *x* scale; shorthand for setting defaults for both **x1** and **x2**." + }, + "x1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting horizontal position; typically bound to the *x* scale; also sets a default for **x2**." + }, + "x2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending horizontal position; typically bound to the *x* scale; also sets a default for **x1**." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position, for horizontal arrows; typically bound to the *y* scale; shorthand for setting defaults for both **y1** and **y2**." + }, + "y1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting vertical position; typically bound to the *y* scale; also sets a default for **y2**." + }, + "y2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending vertical position; typically bound to the *y* scale; also sets a default for **y1**." + } + }, + "required": [ + "data", + "mark" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "$schema": { + "description": "A [JSON schema](http://json-schema.org/) URL for this specification, such as https://uwdata.github.io/mosaic/schema/latest.json. This property enables validation and autocomplete in editors with JSON schema support.", + "format": "uri", + "type": "string" + }, + "anchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "right", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "const": "left", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The side of the frame on which to place the axis: *top* or *bottom* for horizontal axes (axisX and axisFx) and their associated vertical grids (gridX and gridFx), or *left* or *right* for vertical axes (axisY and axisFY) and their associated horizontal grids (gridY and gridFy).\n\nThe default **anchor** depends on the associated scale:\n\n- *x* - *bottom*\n- *y* - *left*\n- *fx* - *top* if there is a *bottom* *x* axis, and otherwise *bottom*\n- *fy* - *right* if there is a *left* *y* axis, and otherwise *right*\n\nFor grids, the **anchor** also affects the extent of grid lines when the opposite dimension is specified (**x** for gridY and **y** for gridX)." + }, + "ariaDescription": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-description][1]; a constant textual description.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-description" + }, + "ariaHidden": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-hidden][1] state; a constant indicating whether the element is exposed to an accessibility API.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-hidden" + }, + "ariaLabel": { + "$ref": "#/definitions/ChannelValue", + "description": "The [aria-label][1]; a channel specifying short textual labels representing the value in the accessibility tree.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-label" + }, + "clip": { + "anyOf": [ + { + "const": "frame", + "type": "string" + }, + { + "const": "sphere", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to clip the mark; one of:\n\n- *frame* or true - clip to the plot’s frame (inner area)\n- *sphere* - clip to the projected sphere (*e.g.*, front hemisphere)\n- null or false - do not clip\n\nThe *sphere* clip option requires a geographic projection." + }, + "color": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A shorthand for setting both **fill** and **stroke**; affects the stroke of tick vectors and grid rules, and the fill of tick texts and axis label texts; defaults to *currentColor*." + }, + "config": { + "$ref": "#/definitions/Config", + "description": "Configuration options." + }, + "data": { + "$ref": "#/definitions/Data", + "description": "Dataset definitions." + }, + "dx": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The horizontal offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "dy": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The vertical offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "facet": { + "anyOf": [ + { + "const": "auto", + "type": "string" + }, + { + "const": "include", + "type": "string" + }, + { + "const": "exclude", + "type": "string" + }, + { + "const": "super", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to enable or disable faceting; one of:\n\n- *auto* (default) - automatically determine if this mark should be faceted\n- *include* (or true) - draw the subset of the mark’s data in the current facet\n- *exclude* - draw the subset of the mark’s data *not* in the current facet\n- *super* - draw this mark in a single frame that covers all facets\n- null (or false) - repeat this mark’s data across all facets (*i.e.*, no faceting)\n\nWhen a mark uses *super* faceting, it is not allowed to use position scales (*x*, *y*, *fx*, or *fy*); *super* faceting is intended for decorations, such as labels and legends.\n\nWhen top-level faceting is used, the default *auto* setting is equivalent to *include* when the mark data is strictly equal to the top-level facet data; otherwise it is equivalent to null. When the *include* or *exclude* facet mode is chosen, the mark data must be parallel to the top-level facet data: the data must have the same length and order. If the data are not parallel, then the wrong data may be shown in each facet. The default\n*auto* therefore requires strict equality (`===`) for safety, and using the facet data as mark data is recommended when using the *exclude* facet mode. (To construct parallel data safely, consider using [*array*.map][1] on the facet data.)\n\nWhen mark-level faceting is used, the default *auto* setting is equivalent to *include*: the mark will be faceted if either the **fx** or **fy** channel option (or both) is specified. The null or false option will disable faceting, while *exclude* draws the subset of the mark’s data *not* in the current facet.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map" + }, + "facetAnchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "right", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "const": "left", + "type": "string" + }, + { + "const": "top-left", + "type": "string" + }, + { + "const": "top-right", + "type": "string" + }, + { + "const": "bottom-left", + "type": "string" + }, + { + "const": "bottom-right", + "type": "string" + }, + { + "const": "top-empty", + "type": "string" + }, + { + "const": "right-empty", + "type": "string" + }, + { + "const": "bottom-empty", + "type": "string" + }, + { + "const": "left-empty", + "type": "string" + }, + { + "const": "empty", + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to place the mark with respect to facets; one of:\n\n- null (default for most marks) - display the mark in each non-empty facet\n- *top*, *right*, *bottom*, or *left* - display the mark only in facets on the given side\n- *top-empty*, *right-empty*, *bottom-empty*, or *left-empty* (default for axis marks) - display the mark only in facets that have empty space on the given side: either the margin, or an empty facet\n- *empty* - display the mark in empty facets only" + }, + "fill": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill" + }, + "fillOpacity": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill-opacity][1]; a constant number between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill-opacity" + }, + "filter": { + "$ref": "#/definitions/ChannelValue", + "description": "Applies a transform to filter the mark’s index according to the given channel values; only truthy values are retained.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "fontFamily": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font-family][1]; a constant; defaults to the plot’s font family, which is typically [*system-ui*][2].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-family [2]: https://drafts.csswg.org/css-fonts-4/#valdef-font-family-system-ui" + }, + "fontSize": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font size][1] in pixels; either a constant or a channel; defaults to the plot’s font size, which is typically 10. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-size" + }, + "fontStyle": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font style][1]; a constant; defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-style" + }, + "fontVariant": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font variant][1]; a constant; if the **text** channel contains numbers or dates, defaults to *tabular-nums* to facilitate comparing numbers; otherwise defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant" + }, + "fontWeight": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font weight][1]; a constant; defaults to the plot’s font weight, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight" + }, + "frameAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The frame anchor specifies defaults for **x** and **y**, along with\n**textAnchor** and **lineAnchor**, based on the plot’s frame; it may be one of the four sides (*top*, *right*, *bottom*, *left*), one of the four corners (*top-left*, *top-right*, *bottom-right*, *bottom-left*), or the\n*middle* of the frame." + }, + "fx": { + "$ref": "#/definitions/ChannelValue", + "description": "The horizontal facet position channel, for mark-level faceting, bound to the *fx* scale." + }, + "fy": { + "$ref": "#/definitions/ChannelValue", + "description": "The vertical facet position channel, for mark-level faceting, bound to the\n*fy* scale." + }, + "href": { + "$ref": "#/definitions/ChannelValue", + "description": "The [href][1]; a channel specifying URLs for clickable links. May be used in conjunction with the **target** option to open links in another window.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/href" + }, + "imageFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A CSS [filter][1]; a constant string used to adjust the rendering of images, such as *blur(5px)*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/filter" + }, + "inset": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four insets: **insetTop**,\n**insetRight**, **insetBottom**, and **insetLeft**. All insets typically default to zero, though not always (say when using bin transform). A positive inset reduces effective area, while a negative inset increases it." + }, + "insetBottom": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Insets the bottom edge by the specified number of pixels. A positive value insets towards the top edge (reducing effective area), while a negative value insets away from the top edge (increasing it)." + }, + "insetTop": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Insets the top edge by the specified number of pixels. A positive value insets towards the bottom edge (reducing effective area), while a negative value insets away from the bottom edge (increasing it)." + }, + "interval": { + "anyOf": [ + { + "$ref": "#/definitions/Interval" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Enforces uniformity for data at regular intervals, such as integer values or daily samples. The interval may be one of:\n\n- a named time interval such as *day* (for date intervals)\n- a number (for number intervals), defining intervals at integer multiples of *n*\n\nThis option sets the internal transform to the given interval’s\n*interval*.floor function. In addition, the default **domain** will align with interval boundaries." + }, + "label": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A textual label to show on the axis or legend; if null, show no label. By default the scale label is inferred from channel definitions, possibly with an arrow (↑, →, ↓, or ←) to indicate the direction of increasing value.\n\nFor axes and legends only." + }, + "labelAnchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "right", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "const": "left", + "type": "string" + }, + { + "const": "center", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Where to place the axis **label** relative to the plot’s frame. For vertical position scales (*y* and *fy*), may be *top*, *bottom*, or\n*center*; for horizontal position scales (*x* and *fx*), may be *left*,\n*right*, or *center*. Defaults to *center* for ordinal scales (including\n*fx* and *fy*), and otherwise *top* for *y*, and *right* for *x*." + }, + "labelArrow": { + "anyOf": [ + { + "const": "auto", + "type": "string" + }, + { + "const": "up", + "type": "string" + }, + { + "const": "right", + "type": "string" + }, + { + "const": "down", + "type": "string" + }, + { + "const": "left", + "type": "string" + }, + { + "const": "none", + "type": "string" + }, + { + "const": true, + "type": "boolean" + }, + { + "const": false, + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to apply a directional arrow such as → or ↑ to the scale label. If\n*auto* (the default), the presence of the arrow depends on whether the scale is ordinal." + }, + "labelOffset": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The axis **label** position offset (in pixels); default depends on margins and orientation." + }, + "lineAnchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "middle", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line anchor controls how text is aligned (typically vertically) relative to its anchor point; it is one of *top*, *bottom*, or *middle*. If the frame anchor is *top*, *top-left*, or *top-right*, the default line anchor is *top*; if the frame anchor is *bottom*, *bottom-right*, or\n*bottom-left*, the default is *bottom*; otherwise it is *middle*." + }, + "lineHeight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line height in ems; defaults to 1. The line height affects the (typically vertical) separation between adjacent baselines of text, as well as the separation between the text and its anchor point." + }, + "lineWidth": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line width in ems (e.g., 10 for about 20 characters); defaults to infinity, disabling wrapping and clipping.\n\nIf **textOverflow** is null, lines will be wrapped at the specified length. If a line is split at a soft hyphen (\\xad), a hyphen (-) will be displayed at the end of the line. If **textOverflow** is not null, lines will be clipped according to the given strategy." + }, + "margin": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four mark margins: **marginTop**,\n**marginRight**, **marginBottom**, and **marginLeft**; typically defaults to 0, except for axis marks." + }, + "marginBottom": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s bottom margin; the minimum distance in pixels between the bottom edges of the inner and outer plot area." + }, + "marginLeft": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s left margin; the minimum distance in pixels between the left edges of the inner and outer plot area." + }, + "marginRight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s right margin; the minimum distance in pixels between the right edges of the mark’s inner and outer plot area." + }, + "marginTop": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s top margin; the minimum distance in pixels between the top edges of the inner and outer plot area." + }, + "mark": { + "const": "axisX", + "description": "An axis mark to document the visual encoding of the horizontal position\n*x* scale, comprised of (up to) three marks: a vector for ticks, a text for tick labels, and another text for an axis label. The data defaults to tick values sampled from the *x* scale’s domain; if desired, use one of the **ticks**, **tickSpacing**, or **interval** options.\n\nThe **facetAnchor** option defaults to *bottom-empty* if **anchor** is\n*bottom*, and *top-empty* if **anchor** is *top*. The default margins likewise depend on **anchor** as follows; in order of **marginTop**,\n**marginRight**, **marginBottom**, and **marginLeft**, in pixels:\n\n- *top* - 30, 20, 0, 20\n- *bottom* - 0, 20, 30, 20\n\nFor simplicity, and for consistent layout across plots, default axis margins are not affected by tick labels. If tick labels are too long, either increase the margin or shorten the labels: use the *k* SI-prefix tick format; use the\n**transform** *y*-scale option to show thousands or millions; or use the\n**textOverflow** and **lineWidth** options to clip.", + "type": "string" + }, + "marker": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for markerStart, markerMid, and markerEnd; one of:\n\n- a marker name such as *arrow* or *circle*\n- *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*" + }, + "markerEnd": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The marker for the ending point of a line segment; one of:\n\n- a marker name such as *arrow* or *circle*\n* *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*" + }, + "markerMid": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The marker for any middle (interior) points of a line segment. If the line segment only has a start and end point, this option has no effect. One of:\n\n- a marker name such as *arrow* or *circle*\n* *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*\n* a function - a custom marker function; see below" + }, + "markerStart": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The marker for the starting point of a line segment; one of:\n\n- a marker name such as *arrow* or *circle*\n* *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*" + }, + "meta": { + "$ref": "#/definitions/Meta", + "description": "Specification metadata." + }, + "mixBlendMode": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [mix-blend-mode][1]; a constant string specifying how to blend content such as *multiply*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode" + }, + "monospace": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, changes the default **fontFamily** to *monospace*, and uses simplified monospaced text metrics calculations." + }, + "opacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "A shorthand for setting both **fillOpacity** and **strokeOpacity**; affects the stroke opacity of tick vectors and grid rules, and the fill opacity of tick texts and axis label texts; defaults to 1 for axes and 0.1 for grids." + }, + "paintOrder": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [paint-order][1]; a constant string specifying the order in which the\n**fill**, **stroke**, and any markers are drawn; defaults to *normal*, which draws the fill, then stroke, then markers; defaults to *stroke* for the text mark to create a “halo” around text to improve legibility.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/paint-order" + }, + "params": { + "$ref": "#/definitions/Params", + "description": "Param and Selection definitions." + }, + "plotDefaults": { + "$ref": "#/definitions/PlotAttributes", + "description": "A default set of attributes to apply to all plot components." + }, + "pointerEvents": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [pointer-events][1] property; a constant string such as *none*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/pointer-events" + }, + "reverse": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Applies a transform to reverse the order of the mark’s index, say for reverse input order." + }, + "rotate": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The rotation angle in degrees clockwise; a constant or a channel; defaults to 0°. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel." + }, + "select": { + "$ref": "#/definitions/SelectFilter", + "description": "Applies a filter transform after data is loaded to highlight selected values only. For example, `first` and `last` select the first or last values of series only (using the *z* channel to separate series). Meanwhile, `nearestX` and `nearestY` select the point nearest to the pointer along the *x* or *y* channel dimension. Unlike Mosaic selections, a mark level *select* is internal to the mark only, and does not populate a param or selection value to be shared across clients.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "shapeRendering": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [shape-rendering][1]; a constant string such as *crispEdges*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/shape-rendering" + }, + "sort": { + "anyOf": [ + { + "$ref": "#/definitions/SortOrder" + }, + { + "$ref": "#/definitions/ChannelDomainSort" + } + ], + "description": "Either applies a transform to sort the mark’s index by the specified channel values, or imputes ordinal scale domains from this mark’s channels.\n\nWhen imputing ordinal scale domains from channel values, the **sort** option is an object whose keys are ordinal scale names such as *x* or *fx*, and whose values are channel names such as *y*, *y1*, or *y2*. For example, to impute the *y* scale’s domain from the associated *x* channel values in ascending order:\n\n```js sort: {y: \"x\"} ```\n\nFor different sort options for different scales, replace the channel name with a *value* object and per-scale options:\n\n```js sort: {y: {value: \"-x\"}} ```\n\nWhen sorting the mark’s index, the **sort** option is instead one of:\n\n- a channel value definition for sorting given values in ascending order\n- a {value, order} object for sorting given values\n- a {channel, order} object for sorting the named channel’s values" + }, + "stroke": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke" + }, + "strokeDasharray": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dasharray][1]; a constant number indicating the length in pixels of alternating dashes and gaps, or a constant string of numbers separated by spaces or commas (_e.g._, *10 2* for dashes of 10 pixels separated by gaps of 2 pixels), or *none* (the default) for no dashing\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dasharray" + }, + "strokeDashoffset": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dashoffset][1]; a constant indicating the offset in pixels of the first dash along the stroke; defaults to zero.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dashoffset" + }, + "strokeLinecap": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linecap][1]; a constant specifying how to cap stroked paths, such as *butt*, *round*, or *square*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linecap" + }, + "strokeLinejoin": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linejoin][1]; a constant specifying how to join stroked paths, such as *bevel*, *miter*, *miter-clip*, or *round*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linejoin" + }, + "strokeMiterlimit": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-miterlimit][1]; a constant number specifying how to limit the length of *miter* joins on stroked paths.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-miterlimit" + }, + "strokeOpacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-opacity" + }, + "strokeWidth": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-width][1]; a constant number in pixels, or a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-width" + }, + "target": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [target][1]; a constant string specifying the target window (_e.g._,\n*_blank*) for clickable links; used in conjunction with the **href** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/target" + }, + "text": { + "$ref": "#/definitions/ChannelValue", + "description": "The text contents channel, possibly with line breaks (\\n, \\r\\n, or \\r). If not specified, defaults to the zero-based index [0, 1, 2, …]." + }, + "textAnchor": { + "anyOf": [ + { + "const": "start", + "type": "string" + }, + { + "const": "middle", + "type": "string" + }, + { + "const": "end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [text anchor][1] controls how text is aligned (typically horizontally) relative to its anchor point; it is one of *start*, *end*, or *middle*. If the frame anchor is *left*, *top-left*, or *bottom-left*, the default text anchor is *start*; if the frame anchor is *right*, *top-right*, or\n*bottom-right*, the default is *end*; otherwise it is *middle*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/text-anchor" + }, + "textOverflow": { + "anyOf": [ + { + "type": "null" + }, + { + "const": "clip", + "type": "string" + }, + { + "const": "ellipsis", + "type": "string" + }, + { + "const": "clip-start", + "type": "string" + }, + { + "const": "clip-end", + "type": "string" + }, + { + "const": "ellipsis-start", + "type": "string" + }, + { + "const": "ellipsis-middle", + "type": "string" + }, + { + "const": "ellipsis-end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How truncate (or wrap) lines of text longer than the given **lineWidth**; one of:\n\n- null (default) - preserve overflowing characters (and wrap if needed)\n- *clip* or *clip-end* - remove characters from the end\n- *clip-start* - remove characters from the start\n- *ellipsis* or *ellipsis-end* - replace characters from the end with an ellipsis (…)\n- *ellipsis-start* - replace characters from the start with an ellipsis (…)\n- *ellipsis-middle* - replace characters from the middle with an ellipsis (…)\n\nIf no **title** was specified, if text requires truncation, a title containing the non-truncated text will be implicitly added." + }, + "textStroke": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The tick text **stroke**, say for a *white* outline to improve legibility; defaults to null." + }, + "textStrokeOpacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The tick text **strokeOpacity**; defaults to 1; has no effect unless **textStroke** is set." + }, + "textStrokeWidth": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The tick text **strokeWidth**; defaults to 4; has no effect unless **textStroke** is set." + }, + "tickFormat": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to format inputs (abstract values) for axis tick labels; one of:\n\n- a [d3-format][1] string for numeric scales\n- a [d3-time-format][2] string for temporal scales\n\n[1]: https://d3js.org/d3-time [2]: https://d3js.org/d3-time-format" + }, + "tickPadding": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The distance between an axis tick mark and its associated text label (in pixels); often defaults to 3, but may be affected by **xTickSize** and\n**xTickRotate**." + }, + "tickRotate": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The rotation angle of axis tick labels in degrees clocksize; defaults to 0." + }, + "tickSize": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The length of axis tick marks in pixels; negative values extend in the opposite direction. Defaults to 6 for *x* and *y* axes and *color* and\n*opacity* *ramp* legends, and 0 for *fx* and *fy* axes." + }, + "tickSpacing": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The desired approximate spacing between adjacent axis ticks, affecting the default **ticks**; defaults to 80 pixels for *x* and *fx*, and 35 pixels for *y* and *fy*." + }, + "ticks": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/Interval" + }, + { + "items": {}, + "type": "array" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The desired approximate number of axis ticks, or an explicit array of tick values, or an interval such as *day* or *month*." + }, + "tip": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/TipPointer" + }, + { + "properties": { + "anchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The tip anchor specifies how to orient the tip box relative to its anchor position; it refers to the part of the tip box that is attached to the anchor point. For example, the *top-left* anchor places the top-left corner of tip box near the anchor position, hence placing the tip box below and to the right of the anchor position." + }, + "fontFamily": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font-family][1]; a constant; defaults to the plot’s font family, which is typically [*system-ui*][2].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-family [2]: https://drafts.csswg.org/css-fonts-4/#valdef-font-family-system-ui" + }, + "fontSize": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font size][1] in pixels; either a constant or a channel; defaults to the plot’s font size, which is typically 10. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-size" + }, + "fontStyle": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font style][1]; a constant; defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-style" + }, + "fontVariant": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font variant][1]; a constant; if the **text** channel contains numbers or dates, defaults to *tabular-nums* to facilitate comparing numbers; otherwise defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant" + }, + "fontWeight": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font weight][1]; a constant; defaults to the plot’s font weight, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight" + }, + "format": { + "additionalProperties": false, + "description": "How channel values are formatted for display. If a format is a string, it is interpreted as a (UTC) time format for temporal channels, and otherwise a number format.", + "properties": { + "ariaLabel": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fill": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fillOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fontSize": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fx": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fy": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "geometry": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "height": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "href": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "length": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "opacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "path": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "r": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "rotate": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "src": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "stroke": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeWidth": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "symbol": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "text": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "title": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "weight": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "width": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "z": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + } + }, + "type": "object" + }, + "frameAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The frame anchor specifies defaults for **x** and **y** based on the plot’s frame; it may be one of the four sides (*top*, *right*, *bottom*, *left*), one of the four corners (*top-left*, *top-right*, *bottom-right*,\n*bottom-left*), or the *middle* of the frame. For example, for tips distributed horizontally at the top of the frame:\n\n```js Plot.tip(data, {x: \"date\", frameAnchor: \"top\"}) ```" + }, + "lineHeight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line height in ems; defaults to 1. The line height affects the (typically vertical) separation between adjacent baselines of text, as well as the separation between the text and its anchor point." + }, + "lineWidth": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line width in ems (e.g., 10 for about 20 characters); defaults to infinity, disabling wrapping and clipping.\n\nIf **textOverflow** is null, lines will be wrapped at the specified length. If a line is split at a soft hyphen (\\xad), a hyphen (-) will be displayed at the end of the line. If **textOverflow** is not null, lines will be clipped according to the given strategy." + }, + "monospace": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, changes the default **fontFamily** to *monospace*, and uses simplified monospaced text metrics calculations." + }, + "pathFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The image filter for the tip’s box; defaults to a drop shadow." + }, + "pointer": { + "$ref": "#/definitions/TipPointer" + }, + "pointerSize": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The size of the tip’s pointer in pixels; defaults to 12." + }, + "preferredAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If an explicit tip anchor is not specified, an anchor is chosen automatically such that the tip fits within the plot’s frame; if the preferred anchor fits, it is chosen." + }, + "textAnchor": { + "anyOf": [ + { + "const": "start", + "type": "string" + }, + { + "const": "middle", + "type": "string" + }, + { + "const": "end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [text anchor][1] controls how text is aligned (typically horizontally) relative to its anchor point; it is one of *start*, *end*, or *middle*. If the frame anchor is *left*, *top-left*, or *bottom-left*, the default text anchor is *start*; if the frame anchor is *right*, *top-right*, or\n*bottom-right*, the default is *end*; otherwise it is *middle*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/text-anchor" + }, + "textOverflow": { + "anyOf": [ + { + "type": "null" + }, + { + "const": "clip", + "type": "string" + }, + { + "const": "ellipsis", + "type": "string" + }, + { + "const": "clip-start", + "type": "string" + }, + { + "const": "clip-end", + "type": "string" + }, + { + "const": "ellipsis-start", + "type": "string" + }, + { + "const": "ellipsis-middle", + "type": "string" + }, + { + "const": "ellipsis-end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How truncate (or wrap) lines of text longer than the given **lineWidth**; one of:\n\n- null (default) - preserve overflowing characters (and wrap if needed)\n- *clip* or *clip-end* - remove characters from the end\n- *clip-start* - remove characters from the start\n- *ellipsis* or *ellipsis-end* - replace characters from the end with an ellipsis (…)\n- *ellipsis-start* - replace characters from the start with an ellipsis (…)\n- *ellipsis-middle* - replace characters from the middle with an ellipsis (…)\n\nIf no **title** was specified, if text requires truncation, a title containing the non-truncated text will be implicitly added." + }, + "textPadding": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The padding around the text in pixels; defaults to 8." + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + } + }, + "type": "object" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to generate a tooltip for this mark, and any tip options." + }, + "title": { + "$ref": "#/definitions/ChannelValue", + "description": "The title; a channel specifying accessible, short textual descriptions as strings (possibly with newlines). If the tip option is specified, the title will be displayed with an interactive tooltip instead of using the SVG [title element][1].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/title" + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel specifying the text’s anchor point, typically bound to the *x* scale." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel specifying the text’s anchor point, typically bound to the *y* scale." + }, + "z": { + "$ref": "#/definitions/ChannelValue", + "description": "An optional ordinal channel for grouping data into series." + } + }, + "required": [ + "mark" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "$schema": { + "description": "A [JSON schema](http://json-schema.org/) URL for this specification, such as https://uwdata.github.io/mosaic/schema/latest.json. This property enables validation and autocomplete in editors with JSON schema support.", + "format": "uri", + "type": "string" + }, + "anchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "right", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "const": "left", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The side of the frame on which to place the axis: *top* or *bottom* for horizontal axes (axisX and axisFx) and their associated vertical grids (gridX and gridFx), or *left* or *right* for vertical axes (axisY and axisFY) and their associated horizontal grids (gridY and gridFy).\n\nThe default **anchor** depends on the associated scale:\n\n- *x* - *bottom*\n- *y* - *left*\n- *fx* - *top* if there is a *bottom* *x* axis, and otherwise *bottom*\n- *fy* - *right* if there is a *left* *y* axis, and otherwise *right*\n\nFor grids, the **anchor** also affects the extent of grid lines when the opposite dimension is specified (**x** for gridY and **y** for gridX)." + }, + "ariaDescription": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-description][1]; a constant textual description.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-description" + }, + "ariaHidden": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-hidden][1] state; a constant indicating whether the element is exposed to an accessibility API.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-hidden" + }, + "ariaLabel": { + "$ref": "#/definitions/ChannelValue", + "description": "The [aria-label][1]; a channel specifying short textual labels representing the value in the accessibility tree.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-label" + }, + "clip": { + "anyOf": [ + { + "const": "frame", + "type": "string" + }, + { + "const": "sphere", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to clip the mark; one of:\n\n- *frame* or true - clip to the plot’s frame (inner area)\n- *sphere* - clip to the projected sphere (*e.g.*, front hemisphere)\n- null or false - do not clip\n\nThe *sphere* clip option requires a geographic projection." + }, + "color": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A shorthand for setting both **fill** and **stroke**; affects the stroke of tick vectors and grid rules, and the fill of tick texts and axis label texts; defaults to *currentColor*." + }, + "config": { + "$ref": "#/definitions/Config", + "description": "Configuration options." + }, + "data": { + "$ref": "#/definitions/Data", + "description": "Dataset definitions." + }, + "dx": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The horizontal offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "dy": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The vertical offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "facet": { + "anyOf": [ + { + "const": "auto", + "type": "string" + }, + { + "const": "include", + "type": "string" + }, + { + "const": "exclude", + "type": "string" + }, + { + "const": "super", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to enable or disable faceting; one of:\n\n- *auto* (default) - automatically determine if this mark should be faceted\n- *include* (or true) - draw the subset of the mark’s data in the current facet\n- *exclude* - draw the subset of the mark’s data *not* in the current facet\n- *super* - draw this mark in a single frame that covers all facets\n- null (or false) - repeat this mark’s data across all facets (*i.e.*, no faceting)\n\nWhen a mark uses *super* faceting, it is not allowed to use position scales (*x*, *y*, *fx*, or *fy*); *super* faceting is intended for decorations, such as labels and legends.\n\nWhen top-level faceting is used, the default *auto* setting is equivalent to *include* when the mark data is strictly equal to the top-level facet data; otherwise it is equivalent to null. When the *include* or *exclude* facet mode is chosen, the mark data must be parallel to the top-level facet data: the data must have the same length and order. If the data are not parallel, then the wrong data may be shown in each facet. The default\n*auto* therefore requires strict equality (`===`) for safety, and using the facet data as mark data is recommended when using the *exclude* facet mode. (To construct parallel data safely, consider using [*array*.map][1] on the facet data.)\n\nWhen mark-level faceting is used, the default *auto* setting is equivalent to *include*: the mark will be faceted if either the **fx** or **fy** channel option (or both) is specified. The null or false option will disable faceting, while *exclude* draws the subset of the mark’s data *not* in the current facet.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map" + }, + "facetAnchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "right", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "const": "left", + "type": "string" + }, + { + "const": "top-left", + "type": "string" + }, + { + "const": "top-right", + "type": "string" + }, + { + "const": "bottom-left", + "type": "string" + }, + { + "const": "bottom-right", + "type": "string" + }, + { + "const": "top-empty", + "type": "string" + }, + { + "const": "right-empty", + "type": "string" + }, + { + "const": "bottom-empty", + "type": "string" + }, + { + "const": "left-empty", + "type": "string" + }, + { + "const": "empty", + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to place the mark with respect to facets; one of:\n\n- null (default for most marks) - display the mark in each non-empty facet\n- *top*, *right*, *bottom*, or *left* - display the mark only in facets on the given side\n- *top-empty*, *right-empty*, *bottom-empty*, or *left-empty* (default for axis marks) - display the mark only in facets that have empty space on the given side: either the margin, or an empty facet\n- *empty* - display the mark in empty facets only" + }, + "fill": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill" + }, + "fillOpacity": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill-opacity][1]; a constant number between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill-opacity" + }, + "filter": { + "$ref": "#/definitions/ChannelValue", + "description": "Applies a transform to filter the mark’s index according to the given channel values; only truthy values are retained.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "fontFamily": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font-family][1]; a constant; defaults to the plot’s font family, which is typically [*system-ui*][2].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-family [2]: https://drafts.csswg.org/css-fonts-4/#valdef-font-family-system-ui" + }, + "fontSize": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font size][1] in pixels; either a constant or a channel; defaults to the plot’s font size, which is typically 10. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-size" + }, + "fontStyle": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font style][1]; a constant; defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-style" + }, + "fontVariant": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font variant][1]; a constant; if the **text** channel contains numbers or dates, defaults to *tabular-nums* to facilitate comparing numbers; otherwise defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant" + }, + "fontWeight": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font weight][1]; a constant; defaults to the plot’s font weight, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight" + }, + "frameAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The frame anchor specifies defaults for **x** and **y**, along with\n**textAnchor** and **lineAnchor**, based on the plot’s frame; it may be one of the four sides (*top*, *right*, *bottom*, *left*), one of the four corners (*top-left*, *top-right*, *bottom-right*, *bottom-left*), or the\n*middle* of the frame." + }, + "fx": { + "$ref": "#/definitions/ChannelValue", + "description": "The horizontal facet position channel, for mark-level faceting, bound to the *fx* scale." + }, + "fy": { + "$ref": "#/definitions/ChannelValue", + "description": "The vertical facet position channel, for mark-level faceting, bound to the\n*fy* scale." + }, + "href": { + "$ref": "#/definitions/ChannelValue", + "description": "The [href][1]; a channel specifying URLs for clickable links. May be used in conjunction with the **target** option to open links in another window.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/href" + }, + "imageFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A CSS [filter][1]; a constant string used to adjust the rendering of images, such as *blur(5px)*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/filter" + }, + "inset": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four insets: **insetTop**,\n**insetRight**, **insetBottom**, and **insetLeft**. All insets typically default to zero, though not always (say when using bin transform). A positive inset reduces effective area, while a negative inset increases it." + }, + "insetLeft": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Insets the left edge by the specified number of pixels. A positive value insets towards the right edge (reducing effective area), while a negative value insets away from the right edge (increasing it)." + }, + "insetRight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Insets the right edge by the specified number of pixels. A positive value insets towards the left edge (reducing effective area), while a negative value insets away from the left edge (increasing it)." + }, + "interval": { + "anyOf": [ + { + "$ref": "#/definitions/Interval" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Enforces uniformity for data at regular intervals, such as integer values or daily samples. The interval may be one of:\n\n- a named time interval such as *day* (for date intervals)\n- a number (for number intervals), defining intervals at integer multiples of *n*\n\nThis option sets the internal transform to the given interval’s\n*interval*.floor function. In addition, the default **domain** will align with interval boundaries." + }, + "label": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A textual label to show on the axis or legend; if null, show no label. By default the scale label is inferred from channel definitions, possibly with an arrow (↑, →, ↓, or ←) to indicate the direction of increasing value.\n\nFor axes and legends only." + }, + "labelAnchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "right", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "const": "left", + "type": "string" + }, + { + "const": "center", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Where to place the axis **label** relative to the plot’s frame. For vertical position scales (*y* and *fy*), may be *top*, *bottom*, or\n*center*; for horizontal position scales (*x* and *fx*), may be *left*,\n*right*, or *center*. Defaults to *center* for ordinal scales (including\n*fx* and *fy*), and otherwise *top* for *y*, and *right* for *x*." + }, + "labelArrow": { + "anyOf": [ + { + "const": "auto", + "type": "string" + }, + { + "const": "up", + "type": "string" + }, + { + "const": "right", + "type": "string" + }, + { + "const": "down", + "type": "string" + }, + { + "const": "left", + "type": "string" + }, + { + "const": "none", + "type": "string" + }, + { + "const": true, + "type": "boolean" + }, + { + "const": false, + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to apply a directional arrow such as → or ↑ to the scale label. If\n*auto* (the default), the presence of the arrow depends on whether the scale is ordinal." + }, + "labelOffset": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The axis **label** position offset (in pixels); default depends on margins and orientation." + }, + "lineAnchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "middle", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line anchor controls how text is aligned (typically vertically) relative to its anchor point; it is one of *top*, *bottom*, or *middle*. If the frame anchor is *top*, *top-left*, or *top-right*, the default line anchor is *top*; if the frame anchor is *bottom*, *bottom-right*, or\n*bottom-left*, the default is *bottom*; otherwise it is *middle*." + }, + "lineHeight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line height in ems; defaults to 1. The line height affects the (typically vertical) separation between adjacent baselines of text, as well as the separation between the text and its anchor point." + }, + "lineWidth": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line width in ems (e.g., 10 for about 20 characters); defaults to infinity, disabling wrapping and clipping.\n\nIf **textOverflow** is null, lines will be wrapped at the specified length. If a line is split at a soft hyphen (\\xad), a hyphen (-) will be displayed at the end of the line. If **textOverflow** is not null, lines will be clipped according to the given strategy." + }, + "margin": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four mark margins: **marginTop**,\n**marginRight**, **marginBottom**, and **marginLeft**; typically defaults to 0, except for axis marks." + }, + "marginBottom": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s bottom margin; the minimum distance in pixels between the bottom edges of the inner and outer plot area." + }, + "marginLeft": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s left margin; the minimum distance in pixels between the left edges of the inner and outer plot area." + }, + "marginRight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s right margin; the minimum distance in pixels between the right edges of the mark’s inner and outer plot area." + }, + "marginTop": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s top margin; the minimum distance in pixels between the top edges of the inner and outer plot area." + }, + "mark": { + "const": "axisY", + "description": "An axis mark to document the visual encoding of the vertical position *y* scale, comprised of (up to) three marks: a vector for ticks, a text for tick labels, and another text for an axis label. The data defaults to tick values sampled from the *y* scale’s domain; if desired, use one of the\n**ticks**, **tickSpacing**, or **interval** options.\n\nThe **facetAnchor** option defaults to *right-empty* if **anchor** is\n*right*, and *left-empty* if **anchor** is *left*. The default margins likewise depend on **anchor** as follows; in order of **marginTop**,\n**marginRight**, **marginBottom**, and **marginLeft**, in pixels:\n\n- *right* - 20, 40, 20, 0\n- *left* - 20, 0, 20, 40\n\nFor simplicity, and for consistent layout across plots, default axis margins are not affected by tick labels. If tick labels are too long, either increase the margin or shorten the labels: use the *k* SI-prefix tick format; or use the **textOverflow** and **lineWidth** options to clip.", + "type": "string" + }, + "marker": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for markerStart, markerMid, and markerEnd; one of:\n\n- a marker name such as *arrow* or *circle*\n- *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*" + }, + "markerEnd": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The marker for the ending point of a line segment; one of:\n\n- a marker name such as *arrow* or *circle*\n* *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*" + }, + "markerMid": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The marker for any middle (interior) points of a line segment. If the line segment only has a start and end point, this option has no effect. One of:\n\n- a marker name such as *arrow* or *circle*\n* *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*\n* a function - a custom marker function; see below" + }, + "markerStart": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The marker for the starting point of a line segment; one of:\n\n- a marker name such as *arrow* or *circle*\n* *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*" + }, + "meta": { + "$ref": "#/definitions/Meta", + "description": "Specification metadata." + }, + "mixBlendMode": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [mix-blend-mode][1]; a constant string specifying how to blend content such as *multiply*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode" + }, + "monospace": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, changes the default **fontFamily** to *monospace*, and uses simplified monospaced text metrics calculations." + }, + "opacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "A shorthand for setting both **fillOpacity** and **strokeOpacity**; affects the stroke opacity of tick vectors and grid rules, and the fill opacity of tick texts and axis label texts; defaults to 1 for axes and 0.1 for grids." + }, + "paintOrder": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [paint-order][1]; a constant string specifying the order in which the\n**fill**, **stroke**, and any markers are drawn; defaults to *normal*, which draws the fill, then stroke, then markers; defaults to *stroke* for the text mark to create a “halo” around text to improve legibility.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/paint-order" + }, + "params": { + "$ref": "#/definitions/Params", + "description": "Param and Selection definitions." + }, + "plotDefaults": { + "$ref": "#/definitions/PlotAttributes", + "description": "A default set of attributes to apply to all plot components." + }, + "pointerEvents": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [pointer-events][1] property; a constant string such as *none*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/pointer-events" + }, + "reverse": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Applies a transform to reverse the order of the mark’s index, say for reverse input order." + }, + "rotate": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The rotation angle in degrees clockwise; a constant or a channel; defaults to 0°. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel." + }, + "select": { + "$ref": "#/definitions/SelectFilter", + "description": "Applies a filter transform after data is loaded to highlight selected values only. For example, `first` and `last` select the first or last values of series only (using the *z* channel to separate series). Meanwhile, `nearestX` and `nearestY` select the point nearest to the pointer along the *x* or *y* channel dimension. Unlike Mosaic selections, a mark level *select* is internal to the mark only, and does not populate a param or selection value to be shared across clients.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "shapeRendering": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [shape-rendering][1]; a constant string such as *crispEdges*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/shape-rendering" + }, + "sort": { + "anyOf": [ + { + "$ref": "#/definitions/SortOrder" + }, + { + "$ref": "#/definitions/ChannelDomainSort" + } + ], + "description": "Either applies a transform to sort the mark’s index by the specified channel values, or imputes ordinal scale domains from this mark’s channels.\n\nWhen imputing ordinal scale domains from channel values, the **sort** option is an object whose keys are ordinal scale names such as *x* or *fx*, and whose values are channel names such as *y*, *y1*, or *y2*. For example, to impute the *y* scale’s domain from the associated *x* channel values in ascending order:\n\n```js sort: {y: \"x\"} ```\n\nFor different sort options for different scales, replace the channel name with a *value* object and per-scale options:\n\n```js sort: {y: {value: \"-x\"}} ```\n\nWhen sorting the mark’s index, the **sort** option is instead one of:\n\n- a channel value definition for sorting given values in ascending order\n- a {value, order} object for sorting given values\n- a {channel, order} object for sorting the named channel’s values" + }, + "stroke": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke" + }, + "strokeDasharray": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dasharray][1]; a constant number indicating the length in pixels of alternating dashes and gaps, or a constant string of numbers separated by spaces or commas (_e.g._, *10 2* for dashes of 10 pixels separated by gaps of 2 pixels), or *none* (the default) for no dashing\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dasharray" + }, + "strokeDashoffset": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dashoffset][1]; a constant indicating the offset in pixels of the first dash along the stroke; defaults to zero.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dashoffset" + }, + "strokeLinecap": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linecap][1]; a constant specifying how to cap stroked paths, such as *butt*, *round*, or *square*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linecap" + }, + "strokeLinejoin": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linejoin][1]; a constant specifying how to join stroked paths, such as *bevel*, *miter*, *miter-clip*, or *round*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linejoin" + }, + "strokeMiterlimit": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-miterlimit][1]; a constant number specifying how to limit the length of *miter* joins on stroked paths.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-miterlimit" + }, + "strokeOpacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-opacity" + }, + "strokeWidth": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-width][1]; a constant number in pixels, or a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-width" + }, + "target": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [target][1]; a constant string specifying the target window (_e.g._,\n*_blank*) for clickable links; used in conjunction with the **href** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/target" + }, + "text": { + "$ref": "#/definitions/ChannelValue", + "description": "The text contents channel, possibly with line breaks (\\n, \\r\\n, or \\r). If not specified, defaults to the zero-based index [0, 1, 2, …]." + }, + "textAnchor": { + "anyOf": [ + { + "const": "start", + "type": "string" + }, + { + "const": "middle", + "type": "string" + }, + { + "const": "end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [text anchor][1] controls how text is aligned (typically horizontally) relative to its anchor point; it is one of *start*, *end*, or *middle*. If the frame anchor is *left*, *top-left*, or *bottom-left*, the default text anchor is *start*; if the frame anchor is *right*, *top-right*, or\n*bottom-right*, the default is *end*; otherwise it is *middle*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/text-anchor" + }, + "textOverflow": { + "anyOf": [ + { + "type": "null" + }, + { + "const": "clip", + "type": "string" + }, + { + "const": "ellipsis", + "type": "string" + }, + { + "const": "clip-start", + "type": "string" + }, + { + "const": "clip-end", + "type": "string" + }, + { + "const": "ellipsis-start", + "type": "string" + }, + { + "const": "ellipsis-middle", + "type": "string" + }, + { + "const": "ellipsis-end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How truncate (or wrap) lines of text longer than the given **lineWidth**; one of:\n\n- null (default) - preserve overflowing characters (and wrap if needed)\n- *clip* or *clip-end* - remove characters from the end\n- *clip-start* - remove characters from the start\n- *ellipsis* or *ellipsis-end* - replace characters from the end with an ellipsis (…)\n- *ellipsis-start* - replace characters from the start with an ellipsis (…)\n- *ellipsis-middle* - replace characters from the middle with an ellipsis (…)\n\nIf no **title** was specified, if text requires truncation, a title containing the non-truncated text will be implicitly added." + }, + "textStroke": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The tick text **stroke**, say for a *white* outline to improve legibility; defaults to null." + }, + "textStrokeOpacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The tick text **strokeOpacity**; defaults to 1; has no effect unless **textStroke** is set." + }, + "textStrokeWidth": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The tick text **strokeWidth**; defaults to 4; has no effect unless **textStroke** is set." + }, + "tickFormat": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to format inputs (abstract values) for axis tick labels; one of:\n\n- a [d3-format][1] string for numeric scales\n- a [d3-time-format][2] string for temporal scales\n\n[1]: https://d3js.org/d3-time [2]: https://d3js.org/d3-time-format" + }, + "tickPadding": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The distance between an axis tick mark and its associated text label (in pixels); often defaults to 3, but may be affected by **xTickSize** and\n**xTickRotate**." + }, + "tickRotate": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The rotation angle of axis tick labels in degrees clocksize; defaults to 0." + }, + "tickSize": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The length of axis tick marks in pixels; negative values extend in the opposite direction. Defaults to 6 for *x* and *y* axes and *color* and\n*opacity* *ramp* legends, and 0 for *fx* and *fy* axes." + }, + "tickSpacing": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The desired approximate spacing between adjacent axis ticks, affecting the default **ticks**; defaults to 80 pixels for *x* and *fx*, and 35 pixels for *y* and *fy*." + }, + "ticks": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/Interval" + }, + { + "items": {}, + "type": "array" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The desired approximate number of axis ticks, or an explicit array of tick values, or an interval such as *day* or *month*." + }, + "tip": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/TipPointer" + }, + { + "properties": { + "anchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The tip anchor specifies how to orient the tip box relative to its anchor position; it refers to the part of the tip box that is attached to the anchor point. For example, the *top-left* anchor places the top-left corner of tip box near the anchor position, hence placing the tip box below and to the right of the anchor position." + }, + "fontFamily": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font-family][1]; a constant; defaults to the plot’s font family, which is typically [*system-ui*][2].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-family [2]: https://drafts.csswg.org/css-fonts-4/#valdef-font-family-system-ui" + }, + "fontSize": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font size][1] in pixels; either a constant or a channel; defaults to the plot’s font size, which is typically 10. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-size" + }, + "fontStyle": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font style][1]; a constant; defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-style" + }, + "fontVariant": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font variant][1]; a constant; if the **text** channel contains numbers or dates, defaults to *tabular-nums* to facilitate comparing numbers; otherwise defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant" + }, + "fontWeight": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font weight][1]; a constant; defaults to the plot’s font weight, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight" + }, + "format": { + "additionalProperties": false, + "description": "How channel values are formatted for display. If a format is a string, it is interpreted as a (UTC) time format for temporal channels, and otherwise a number format.", + "properties": { + "ariaLabel": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fill": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fillOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fontSize": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fx": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fy": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "geometry": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "height": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "href": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "length": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "opacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "path": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "r": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "rotate": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "src": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "stroke": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeWidth": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "symbol": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "text": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "title": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "weight": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "width": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "z": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + } + }, + "type": "object" + }, + "frameAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The frame anchor specifies defaults for **x** and **y** based on the plot’s frame; it may be one of the four sides (*top*, *right*, *bottom*, *left*), one of the four corners (*top-left*, *top-right*, *bottom-right*,\n*bottom-left*), or the *middle* of the frame. For example, for tips distributed horizontally at the top of the frame:\n\n```js Plot.tip(data, {x: \"date\", frameAnchor: \"top\"}) ```" + }, + "lineHeight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line height in ems; defaults to 1. The line height affects the (typically vertical) separation between adjacent baselines of text, as well as the separation between the text and its anchor point." + }, + "lineWidth": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line width in ems (e.g., 10 for about 20 characters); defaults to infinity, disabling wrapping and clipping.\n\nIf **textOverflow** is null, lines will be wrapped at the specified length. If a line is split at a soft hyphen (\\xad), a hyphen (-) will be displayed at the end of the line. If **textOverflow** is not null, lines will be clipped according to the given strategy." + }, + "monospace": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, changes the default **fontFamily** to *monospace*, and uses simplified monospaced text metrics calculations." + }, + "pathFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The image filter for the tip’s box; defaults to a drop shadow." + }, + "pointer": { + "$ref": "#/definitions/TipPointer" + }, + "pointerSize": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The size of the tip’s pointer in pixels; defaults to 12." + }, + "preferredAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If an explicit tip anchor is not specified, an anchor is chosen automatically such that the tip fits within the plot’s frame; if the preferred anchor fits, it is chosen." + }, + "textAnchor": { + "anyOf": [ + { + "const": "start", + "type": "string" + }, + { + "const": "middle", + "type": "string" + }, + { + "const": "end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [text anchor][1] controls how text is aligned (typically horizontally) relative to its anchor point; it is one of *start*, *end*, or *middle*. If the frame anchor is *left*, *top-left*, or *bottom-left*, the default text anchor is *start*; if the frame anchor is *right*, *top-right*, or\n*bottom-right*, the default is *end*; otherwise it is *middle*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/text-anchor" + }, + "textOverflow": { + "anyOf": [ + { + "type": "null" + }, + { + "const": "clip", + "type": "string" + }, + { + "const": "ellipsis", + "type": "string" + }, + { + "const": "clip-start", + "type": "string" + }, + { + "const": "clip-end", + "type": "string" + }, + { + "const": "ellipsis-start", + "type": "string" + }, + { + "const": "ellipsis-middle", + "type": "string" + }, + { + "const": "ellipsis-end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How truncate (or wrap) lines of text longer than the given **lineWidth**; one of:\n\n- null (default) - preserve overflowing characters (and wrap if needed)\n- *clip* or *clip-end* - remove characters from the end\n- *clip-start* - remove characters from the start\n- *ellipsis* or *ellipsis-end* - replace characters from the end with an ellipsis (…)\n- *ellipsis-start* - replace characters from the start with an ellipsis (…)\n- *ellipsis-middle* - replace characters from the middle with an ellipsis (…)\n\nIf no **title** was specified, if text requires truncation, a title containing the non-truncated text will be implicitly added." + }, + "textPadding": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The padding around the text in pixels; defaults to 8." + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + } + }, + "type": "object" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to generate a tooltip for this mark, and any tip options." + }, + "title": { + "$ref": "#/definitions/ChannelValue", + "description": "The title; a channel specifying accessible, short textual descriptions as strings (possibly with newlines). If the tip option is specified, the title will be displayed with an interactive tooltip instead of using the SVG [title element][1].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/title" + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel specifying the text’s anchor point, typically bound to the *x* scale." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel specifying the text’s anchor point, typically bound to the *y* scale." + }, + "z": { + "$ref": "#/definitions/ChannelValue", + "description": "An optional ordinal channel for grouping data into series." + } + }, + "required": [ + "mark" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "$schema": { + "description": "A [JSON schema](http://json-schema.org/) URL for this specification, such as https://uwdata.github.io/mosaic/schema/latest.json. This property enables validation and autocomplete in editors with JSON schema support.", + "format": "uri", + "type": "string" + }, + "anchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "right", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "const": "left", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The side of the frame on which to place the axis: *top* or *bottom* for horizontal axes (axisX and axisFx) and their associated vertical grids (gridX and gridFx), or *left* or *right* for vertical axes (axisY and axisFY) and their associated horizontal grids (gridY and gridFy).\n\nThe default **anchor** depends on the associated scale:\n\n- *x* - *bottom*\n- *y* - *left*\n- *fx* - *top* if there is a *bottom* *x* axis, and otherwise *bottom*\n- *fy* - *right* if there is a *left* *y* axis, and otherwise *right*\n\nFor grids, the **anchor** also affects the extent of grid lines when the opposite dimension is specified (**x** for gridY and **y** for gridX)." + }, + "ariaDescription": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-description][1]; a constant textual description.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-description" + }, + "ariaHidden": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-hidden][1] state; a constant indicating whether the element is exposed to an accessibility API.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-hidden" + }, + "ariaLabel": { + "$ref": "#/definitions/ChannelValue", + "description": "The [aria-label][1]; a channel specifying short textual labels representing the value in the accessibility tree.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-label" + }, + "clip": { + "anyOf": [ + { + "const": "frame", + "type": "string" + }, + { + "const": "sphere", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to clip the mark; one of:\n\n- *frame* or true - clip to the plot’s frame (inner area)\n- *sphere* - clip to the projected sphere (*e.g.*, front hemisphere)\n- null or false - do not clip\n\nThe *sphere* clip option requires a geographic projection." + }, + "color": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A shorthand for setting both **fill** and **stroke**; affects the stroke of tick vectors and grid rules, and the fill of tick texts and axis label texts; defaults to *currentColor*." + }, + "config": { + "$ref": "#/definitions/Config", + "description": "Configuration options." + }, + "data": { + "$ref": "#/definitions/Data", + "description": "Dataset definitions." + }, + "dx": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The horizontal offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "dy": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The vertical offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "facet": { + "anyOf": [ + { + "const": "auto", + "type": "string" + }, + { + "const": "include", + "type": "string" + }, + { + "const": "exclude", + "type": "string" + }, + { + "const": "super", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to enable or disable faceting; one of:\n\n- *auto* (default) - automatically determine if this mark should be faceted\n- *include* (or true) - draw the subset of the mark’s data in the current facet\n- *exclude* - draw the subset of the mark’s data *not* in the current facet\n- *super* - draw this mark in a single frame that covers all facets\n- null (or false) - repeat this mark’s data across all facets (*i.e.*, no faceting)\n\nWhen a mark uses *super* faceting, it is not allowed to use position scales (*x*, *y*, *fx*, or *fy*); *super* faceting is intended for decorations, such as labels and legends.\n\nWhen top-level faceting is used, the default *auto* setting is equivalent to *include* when the mark data is strictly equal to the top-level facet data; otherwise it is equivalent to null. When the *include* or *exclude* facet mode is chosen, the mark data must be parallel to the top-level facet data: the data must have the same length and order. If the data are not parallel, then the wrong data may be shown in each facet. The default\n*auto* therefore requires strict equality (`===`) for safety, and using the facet data as mark data is recommended when using the *exclude* facet mode. (To construct parallel data safely, consider using [*array*.map][1] on the facet data.)\n\nWhen mark-level faceting is used, the default *auto* setting is equivalent to *include*: the mark will be faceted if either the **fx** or **fy** channel option (or both) is specified. The null or false option will disable faceting, while *exclude* draws the subset of the mark’s data *not* in the current facet.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map" + }, + "facetAnchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "right", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "const": "left", + "type": "string" + }, + { + "const": "top-left", + "type": "string" + }, + { + "const": "top-right", + "type": "string" + }, + { + "const": "bottom-left", + "type": "string" + }, + { + "const": "bottom-right", + "type": "string" + }, + { + "const": "top-empty", + "type": "string" + }, + { + "const": "right-empty", + "type": "string" + }, + { + "const": "bottom-empty", + "type": "string" + }, + { + "const": "left-empty", + "type": "string" + }, + { + "const": "empty", + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to place the mark with respect to facets; one of:\n\n- null (default for most marks) - display the mark in each non-empty facet\n- *top*, *right*, *bottom*, or *left* - display the mark only in facets on the given side\n- *top-empty*, *right-empty*, *bottom-empty*, or *left-empty* (default for axis marks) - display the mark only in facets that have empty space on the given side: either the margin, or an empty facet\n- *empty* - display the mark in empty facets only" + }, + "fill": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill" + }, + "fillOpacity": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill-opacity][1]; a constant number between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill-opacity" + }, + "filter": { + "$ref": "#/definitions/ChannelValue", + "description": "Applies a transform to filter the mark’s index according to the given channel values; only truthy values are retained.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "fontFamily": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font-family][1]; a constant; defaults to the plot’s font family, which is typically [*system-ui*][2].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-family [2]: https://drafts.csswg.org/css-fonts-4/#valdef-font-family-system-ui" + }, + "fontSize": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font size][1] in pixels; either a constant or a channel; defaults to the plot’s font size, which is typically 10. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-size" + }, + "fontStyle": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font style][1]; a constant; defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-style" + }, + "fontVariant": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font variant][1]; a constant; if the **text** channel contains numbers or dates, defaults to *tabular-nums* to facilitate comparing numbers; otherwise defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant" + }, + "fontWeight": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font weight][1]; a constant; defaults to the plot’s font weight, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight" + }, + "frameAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The frame anchor specifies defaults for **x** and **y**, along with\n**textAnchor** and **lineAnchor**, based on the plot’s frame; it may be one of the four sides (*top*, *right*, *bottom*, *left*), one of the four corners (*top-left*, *top-right*, *bottom-right*, *bottom-left*), or the\n*middle* of the frame." + }, + "fx": { + "$ref": "#/definitions/ChannelValue", + "description": "The horizontal facet position channel, for mark-level faceting, bound to the *fx* scale." + }, + "fy": { + "$ref": "#/definitions/ChannelValue", + "description": "The vertical facet position channel, for mark-level faceting, bound to the\n*fy* scale." + }, + "href": { + "$ref": "#/definitions/ChannelValue", + "description": "The [href][1]; a channel specifying URLs for clickable links. May be used in conjunction with the **target** option to open links in another window.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/href" + }, + "imageFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A CSS [filter][1]; a constant string used to adjust the rendering of images, such as *blur(5px)*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/filter" + }, + "inset": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four insets: **insetTop**,\n**insetRight**, **insetBottom**, and **insetLeft**. All insets typically default to zero, though not always (say when using bin transform). A positive inset reduces effective area, while a negative inset increases it." + }, + "insetBottom": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Insets the bottom edge by the specified number of pixels. A positive value insets towards the top edge (reducing effective area), while a negative value insets away from the top edge (increasing it)." + }, + "insetTop": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Insets the top edge by the specified number of pixels. A positive value insets towards the bottom edge (reducing effective area), while a negative value insets away from the bottom edge (increasing it)." + }, + "interval": { + "anyOf": [ + { + "$ref": "#/definitions/Interval" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Enforces uniformity for data at regular intervals, such as integer values or daily samples. The interval may be one of:\n\n- a named time interval such as *day* (for date intervals)\n- a number (for number intervals), defining intervals at integer multiples of *n*\n\nThis option sets the internal transform to the given interval’s\n*interval*.floor function. In addition, the default **domain** will align with interval boundaries." + }, + "label": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A textual label to show on the axis or legend; if null, show no label. By default the scale label is inferred from channel definitions, possibly with an arrow (↑, →, ↓, or ←) to indicate the direction of increasing value.\n\nFor axes and legends only." + }, + "labelAnchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "right", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "const": "left", + "type": "string" + }, + { + "const": "center", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Where to place the axis **label** relative to the plot’s frame. For vertical position scales (*y* and *fy*), may be *top*, *bottom*, or\n*center*; for horizontal position scales (*x* and *fx*), may be *left*,\n*right*, or *center*. Defaults to *center* for ordinal scales (including\n*fx* and *fy*), and otherwise *top* for *y*, and *right* for *x*." + }, + "labelArrow": { + "anyOf": [ + { + "const": "auto", + "type": "string" + }, + { + "const": "up", + "type": "string" + }, + { + "const": "right", + "type": "string" + }, + { + "const": "down", + "type": "string" + }, + { + "const": "left", + "type": "string" + }, + { + "const": "none", + "type": "string" + }, + { + "const": true, + "type": "boolean" + }, + { + "const": false, + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to apply a directional arrow such as → or ↑ to the scale label. If\n*auto* (the default), the presence of the arrow depends on whether the scale is ordinal." + }, + "labelOffset": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The axis **label** position offset (in pixels); default depends on margins and orientation." + }, + "lineAnchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "middle", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line anchor controls how text is aligned (typically vertically) relative to its anchor point; it is one of *top*, *bottom*, or *middle*. If the frame anchor is *top*, *top-left*, or *top-right*, the default line anchor is *top*; if the frame anchor is *bottom*, *bottom-right*, or\n*bottom-left*, the default is *bottom*; otherwise it is *middle*." + }, + "lineHeight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line height in ems; defaults to 1. The line height affects the (typically vertical) separation between adjacent baselines of text, as well as the separation between the text and its anchor point." + }, + "lineWidth": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line width in ems (e.g., 10 for about 20 characters); defaults to infinity, disabling wrapping and clipping.\n\nIf **textOverflow** is null, lines will be wrapped at the specified length. If a line is split at a soft hyphen (\\xad), a hyphen (-) will be displayed at the end of the line. If **textOverflow** is not null, lines will be clipped according to the given strategy." + }, + "margin": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four mark margins: **marginTop**,\n**marginRight**, **marginBottom**, and **marginLeft**; typically defaults to 0, except for axis marks." + }, + "marginBottom": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s bottom margin; the minimum distance in pixels between the bottom edges of the inner and outer plot area." + }, + "marginLeft": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s left margin; the minimum distance in pixels between the left edges of the inner and outer plot area." + }, + "marginRight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s right margin; the minimum distance in pixels between the right edges of the mark’s inner and outer plot area." + }, + "marginTop": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s top margin; the minimum distance in pixels between the top edges of the inner and outer plot area." + }, + "mark": { + "const": "axisFx", + "description": "An axis mark to document the visual encoding of the horizontal facet position *fx* scale, comprised of (up to) three marks: a vector for ticks, a text for tick labels, and another text for an axis label. The data defaults to the *fx* scale’s domain; if desired, use one of the **ticks**,\n**tickSpacing**, or **interval** options.\n\nThe **facetAnchor** and **frameAnchor** options defaults to **anchor**. The default margins likewise depend on **anchor** as follows; in order of\n**marginTop**, **marginRight**, **marginBottom**, and **marginLeft**, in pixels:\n\n- *top* - 30, 20, 0, 20\n- *bottom* - 0, 20, 30, 20\n\nFor simplicity, and for consistent layout across plots, default axis margins are not affected by tick labels. If tick labels are too long, either increase the margin or shorten the labels: use the *k* SI-prefix tick format; use the\n**transform** *y*-scale option to show thousands or millions; or use the\n**textOverflow** and **lineWidth** options to clip.", + "type": "string" + }, + "marker": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for markerStart, markerMid, and markerEnd; one of:\n\n- a marker name such as *arrow* or *circle*\n- *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*" + }, + "markerEnd": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The marker for the ending point of a line segment; one of:\n\n- a marker name such as *arrow* or *circle*\n* *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*" + }, + "markerMid": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The marker for any middle (interior) points of a line segment. If the line segment only has a start and end point, this option has no effect. One of:\n\n- a marker name such as *arrow* or *circle*\n* *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*\n* a function - a custom marker function; see below" + }, + "markerStart": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The marker for the starting point of a line segment; one of:\n\n- a marker name such as *arrow* or *circle*\n* *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*" + }, + "meta": { + "$ref": "#/definitions/Meta", + "description": "Specification metadata." + }, + "mixBlendMode": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [mix-blend-mode][1]; a constant string specifying how to blend content such as *multiply*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode" + }, + "monospace": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, changes the default **fontFamily** to *monospace*, and uses simplified monospaced text metrics calculations." + }, + "opacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "A shorthand for setting both **fillOpacity** and **strokeOpacity**; affects the stroke opacity of tick vectors and grid rules, and the fill opacity of tick texts and axis label texts; defaults to 1 for axes and 0.1 for grids." + }, + "paintOrder": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [paint-order][1]; a constant string specifying the order in which the\n**fill**, **stroke**, and any markers are drawn; defaults to *normal*, which draws the fill, then stroke, then markers; defaults to *stroke* for the text mark to create a “halo” around text to improve legibility.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/paint-order" + }, + "params": { + "$ref": "#/definitions/Params", + "description": "Param and Selection definitions." + }, + "plotDefaults": { + "$ref": "#/definitions/PlotAttributes", + "description": "A default set of attributes to apply to all plot components." + }, + "pointerEvents": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [pointer-events][1] property; a constant string such as *none*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/pointer-events" + }, + "reverse": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Applies a transform to reverse the order of the mark’s index, say for reverse input order." + }, + "rotate": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The rotation angle in degrees clockwise; a constant or a channel; defaults to 0°. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel." + }, + "select": { + "$ref": "#/definitions/SelectFilter", + "description": "Applies a filter transform after data is loaded to highlight selected values only. For example, `first` and `last` select the first or last values of series only (using the *z* channel to separate series). Meanwhile, `nearestX` and `nearestY` select the point nearest to the pointer along the *x* or *y* channel dimension. Unlike Mosaic selections, a mark level *select* is internal to the mark only, and does not populate a param or selection value to be shared across clients.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "shapeRendering": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [shape-rendering][1]; a constant string such as *crispEdges*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/shape-rendering" + }, + "sort": { + "anyOf": [ + { + "$ref": "#/definitions/SortOrder" + }, + { + "$ref": "#/definitions/ChannelDomainSort" + } + ], + "description": "Either applies a transform to sort the mark’s index by the specified channel values, or imputes ordinal scale domains from this mark’s channels.\n\nWhen imputing ordinal scale domains from channel values, the **sort** option is an object whose keys are ordinal scale names such as *x* or *fx*, and whose values are channel names such as *y*, *y1*, or *y2*. For example, to impute the *y* scale’s domain from the associated *x* channel values in ascending order:\n\n```js sort: {y: \"x\"} ```\n\nFor different sort options for different scales, replace the channel name with a *value* object and per-scale options:\n\n```js sort: {y: {value: \"-x\"}} ```\n\nWhen sorting the mark’s index, the **sort** option is instead one of:\n\n- a channel value definition for sorting given values in ascending order\n- a {value, order} object for sorting given values\n- a {channel, order} object for sorting the named channel’s values" + }, + "stroke": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke" + }, + "strokeDasharray": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dasharray][1]; a constant number indicating the length in pixels of alternating dashes and gaps, or a constant string of numbers separated by spaces or commas (_e.g._, *10 2* for dashes of 10 pixels separated by gaps of 2 pixels), or *none* (the default) for no dashing\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dasharray" + }, + "strokeDashoffset": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dashoffset][1]; a constant indicating the offset in pixels of the first dash along the stroke; defaults to zero.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dashoffset" + }, + "strokeLinecap": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linecap][1]; a constant specifying how to cap stroked paths, such as *butt*, *round*, or *square*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linecap" + }, + "strokeLinejoin": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linejoin][1]; a constant specifying how to join stroked paths, such as *bevel*, *miter*, *miter-clip*, or *round*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linejoin" + }, + "strokeMiterlimit": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-miterlimit][1]; a constant number specifying how to limit the length of *miter* joins on stroked paths.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-miterlimit" + }, + "strokeOpacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-opacity" + }, + "strokeWidth": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-width][1]; a constant number in pixels, or a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-width" + }, + "target": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [target][1]; a constant string specifying the target window (_e.g._,\n*_blank*) for clickable links; used in conjunction with the **href** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/target" + }, + "text": { + "$ref": "#/definitions/ChannelValue", + "description": "The text contents channel, possibly with line breaks (\\n, \\r\\n, or \\r). If not specified, defaults to the zero-based index [0, 1, 2, …]." + }, + "textAnchor": { + "anyOf": [ + { + "const": "start", + "type": "string" + }, + { + "const": "middle", + "type": "string" + }, + { + "const": "end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [text anchor][1] controls how text is aligned (typically horizontally) relative to its anchor point; it is one of *start*, *end*, or *middle*. If the frame anchor is *left*, *top-left*, or *bottom-left*, the default text anchor is *start*; if the frame anchor is *right*, *top-right*, or\n*bottom-right*, the default is *end*; otherwise it is *middle*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/text-anchor" + }, + "textOverflow": { + "anyOf": [ + { + "type": "null" + }, + { + "const": "clip", + "type": "string" + }, + { + "const": "ellipsis", + "type": "string" + }, + { + "const": "clip-start", + "type": "string" + }, + { + "const": "clip-end", + "type": "string" + }, + { + "const": "ellipsis-start", + "type": "string" + }, + { + "const": "ellipsis-middle", + "type": "string" + }, + { + "const": "ellipsis-end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How truncate (or wrap) lines of text longer than the given **lineWidth**; one of:\n\n- null (default) - preserve overflowing characters (and wrap if needed)\n- *clip* or *clip-end* - remove characters from the end\n- *clip-start* - remove characters from the start\n- *ellipsis* or *ellipsis-end* - replace characters from the end with an ellipsis (…)\n- *ellipsis-start* - replace characters from the start with an ellipsis (…)\n- *ellipsis-middle* - replace characters from the middle with an ellipsis (…)\n\nIf no **title** was specified, if text requires truncation, a title containing the non-truncated text will be implicitly added." + }, + "textStroke": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The tick text **stroke**, say for a *white* outline to improve legibility; defaults to null." + }, + "textStrokeOpacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The tick text **strokeOpacity**; defaults to 1; has no effect unless **textStroke** is set." + }, + "textStrokeWidth": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The tick text **strokeWidth**; defaults to 4; has no effect unless **textStroke** is set." + }, + "tickFormat": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to format inputs (abstract values) for axis tick labels; one of:\n\n- a [d3-format][1] string for numeric scales\n- a [d3-time-format][2] string for temporal scales\n\n[1]: https://d3js.org/d3-time [2]: https://d3js.org/d3-time-format" + }, + "tickPadding": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The distance between an axis tick mark and its associated text label (in pixels); often defaults to 3, but may be affected by **xTickSize** and\n**xTickRotate**." + }, + "tickRotate": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The rotation angle of axis tick labels in degrees clocksize; defaults to 0." + }, + "tickSize": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The length of axis tick marks in pixels; negative values extend in the opposite direction. Defaults to 6 for *x* and *y* axes and *color* and\n*opacity* *ramp* legends, and 0 for *fx* and *fy* axes." + }, + "tickSpacing": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The desired approximate spacing between adjacent axis ticks, affecting the default **ticks**; defaults to 80 pixels for *x* and *fx*, and 35 pixels for *y* and *fy*." + }, + "ticks": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/Interval" + }, + { + "items": {}, + "type": "array" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The desired approximate number of axis ticks, or an explicit array of tick values, or an interval such as *day* or *month*." + }, + "tip": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/TipPointer" + }, + { + "properties": { + "anchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The tip anchor specifies how to orient the tip box relative to its anchor position; it refers to the part of the tip box that is attached to the anchor point. For example, the *top-left* anchor places the top-left corner of tip box near the anchor position, hence placing the tip box below and to the right of the anchor position." + }, + "fontFamily": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font-family][1]; a constant; defaults to the plot’s font family, which is typically [*system-ui*][2].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-family [2]: https://drafts.csswg.org/css-fonts-4/#valdef-font-family-system-ui" + }, + "fontSize": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font size][1] in pixels; either a constant or a channel; defaults to the plot’s font size, which is typically 10. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-size" + }, + "fontStyle": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font style][1]; a constant; defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-style" + }, + "fontVariant": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font variant][1]; a constant; if the **text** channel contains numbers or dates, defaults to *tabular-nums* to facilitate comparing numbers; otherwise defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant" + }, + "fontWeight": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font weight][1]; a constant; defaults to the plot’s font weight, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight" + }, + "format": { + "additionalProperties": false, + "description": "How channel values are formatted for display. If a format is a string, it is interpreted as a (UTC) time format for temporal channels, and otherwise a number format.", + "properties": { + "ariaLabel": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fill": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fillOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fontSize": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fx": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fy": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "geometry": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "height": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "href": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "length": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "opacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "path": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "r": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "rotate": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "src": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "stroke": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeWidth": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "symbol": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "text": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "title": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "weight": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "width": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "z": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + } + }, + "type": "object" + }, + "frameAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The frame anchor specifies defaults for **x** and **y** based on the plot’s frame; it may be one of the four sides (*top*, *right*, *bottom*, *left*), one of the four corners (*top-left*, *top-right*, *bottom-right*,\n*bottom-left*), or the *middle* of the frame. For example, for tips distributed horizontally at the top of the frame:\n\n```js Plot.tip(data, {x: \"date\", frameAnchor: \"top\"}) ```" + }, + "lineHeight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line height in ems; defaults to 1. The line height affects the (typically vertical) separation between adjacent baselines of text, as well as the separation between the text and its anchor point." + }, + "lineWidth": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line width in ems (e.g., 10 for about 20 characters); defaults to infinity, disabling wrapping and clipping.\n\nIf **textOverflow** is null, lines will be wrapped at the specified length. If a line is split at a soft hyphen (\\xad), a hyphen (-) will be displayed at the end of the line. If **textOverflow** is not null, lines will be clipped according to the given strategy." + }, + "monospace": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, changes the default **fontFamily** to *monospace*, and uses simplified monospaced text metrics calculations." + }, + "pathFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The image filter for the tip’s box; defaults to a drop shadow." + }, + "pointer": { + "$ref": "#/definitions/TipPointer" + }, + "pointerSize": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The size of the tip’s pointer in pixels; defaults to 12." + }, + "preferredAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If an explicit tip anchor is not specified, an anchor is chosen automatically such that the tip fits within the plot’s frame; if the preferred anchor fits, it is chosen." + }, + "textAnchor": { + "anyOf": [ + { + "const": "start", + "type": "string" + }, + { + "const": "middle", + "type": "string" + }, + { + "const": "end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [text anchor][1] controls how text is aligned (typically horizontally) relative to its anchor point; it is one of *start*, *end*, or *middle*. If the frame anchor is *left*, *top-left*, or *bottom-left*, the default text anchor is *start*; if the frame anchor is *right*, *top-right*, or\n*bottom-right*, the default is *end*; otherwise it is *middle*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/text-anchor" + }, + "textOverflow": { + "anyOf": [ + { + "type": "null" + }, + { + "const": "clip", + "type": "string" + }, + { + "const": "ellipsis", + "type": "string" + }, + { + "const": "clip-start", + "type": "string" + }, + { + "const": "clip-end", + "type": "string" + }, + { + "const": "ellipsis-start", + "type": "string" + }, + { + "const": "ellipsis-middle", + "type": "string" + }, + { + "const": "ellipsis-end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How truncate (or wrap) lines of text longer than the given **lineWidth**; one of:\n\n- null (default) - preserve overflowing characters (and wrap if needed)\n- *clip* or *clip-end* - remove characters from the end\n- *clip-start* - remove characters from the start\n- *ellipsis* or *ellipsis-end* - replace characters from the end with an ellipsis (…)\n- *ellipsis-start* - replace characters from the start with an ellipsis (…)\n- *ellipsis-middle* - replace characters from the middle with an ellipsis (…)\n\nIf no **title** was specified, if text requires truncation, a title containing the non-truncated text will be implicitly added." + }, + "textPadding": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The padding around the text in pixels; defaults to 8." + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + } + }, + "type": "object" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to generate a tooltip for this mark, and any tip options." + }, + "title": { + "$ref": "#/definitions/ChannelValue", + "description": "The title; a channel specifying accessible, short textual descriptions as strings (possibly with newlines). If the tip option is specified, the title will be displayed with an interactive tooltip instead of using the SVG [title element][1].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/title" + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel specifying the text’s anchor point, typically bound to the *x* scale." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel specifying the text’s anchor point, typically bound to the *y* scale." + }, + "z": { + "$ref": "#/definitions/ChannelValue", + "description": "An optional ordinal channel for grouping data into series." + } + }, + "required": [ + "mark" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "$schema": { + "description": "A [JSON schema](http://json-schema.org/) URL for this specification, such as https://uwdata.github.io/mosaic/schema/latest.json. This property enables validation and autocomplete in editors with JSON schema support.", + "format": "uri", + "type": "string" + }, + "anchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "right", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "const": "left", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The side of the frame on which to place the axis: *top* or *bottom* for horizontal axes (axisX and axisFx) and their associated vertical grids (gridX and gridFx), or *left* or *right* for vertical axes (axisY and axisFY) and their associated horizontal grids (gridY and gridFy).\n\nThe default **anchor** depends on the associated scale:\n\n- *x* - *bottom*\n- *y* - *left*\n- *fx* - *top* if there is a *bottom* *x* axis, and otherwise *bottom*\n- *fy* - *right* if there is a *left* *y* axis, and otherwise *right*\n\nFor grids, the **anchor** also affects the extent of grid lines when the opposite dimension is specified (**x** for gridY and **y** for gridX)." + }, + "ariaDescription": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-description][1]; a constant textual description.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-description" + }, + "ariaHidden": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-hidden][1] state; a constant indicating whether the element is exposed to an accessibility API.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-hidden" + }, + "ariaLabel": { + "$ref": "#/definitions/ChannelValue", + "description": "The [aria-label][1]; a channel specifying short textual labels representing the value in the accessibility tree.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-label" + }, + "clip": { + "anyOf": [ + { + "const": "frame", + "type": "string" + }, + { + "const": "sphere", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to clip the mark; one of:\n\n- *frame* or true - clip to the plot’s frame (inner area)\n- *sphere* - clip to the projected sphere (*e.g.*, front hemisphere)\n- null or false - do not clip\n\nThe *sphere* clip option requires a geographic projection." + }, + "color": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A shorthand for setting both **fill** and **stroke**; affects the stroke of tick vectors and grid rules, and the fill of tick texts and axis label texts; defaults to *currentColor*." + }, + "config": { + "$ref": "#/definitions/Config", + "description": "Configuration options." + }, + "data": { + "$ref": "#/definitions/Data", + "description": "Dataset definitions." + }, + "dx": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The horizontal offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "dy": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The vertical offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "facet": { + "anyOf": [ + { + "const": "auto", + "type": "string" + }, + { + "const": "include", + "type": "string" + }, + { + "const": "exclude", + "type": "string" + }, + { + "const": "super", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to enable or disable faceting; one of:\n\n- *auto* (default) - automatically determine if this mark should be faceted\n- *include* (or true) - draw the subset of the mark’s data in the current facet\n- *exclude* - draw the subset of the mark’s data *not* in the current facet\n- *super* - draw this mark in a single frame that covers all facets\n- null (or false) - repeat this mark’s data across all facets (*i.e.*, no faceting)\n\nWhen a mark uses *super* faceting, it is not allowed to use position scales (*x*, *y*, *fx*, or *fy*); *super* faceting is intended for decorations, such as labels and legends.\n\nWhen top-level faceting is used, the default *auto* setting is equivalent to *include* when the mark data is strictly equal to the top-level facet data; otherwise it is equivalent to null. When the *include* or *exclude* facet mode is chosen, the mark data must be parallel to the top-level facet data: the data must have the same length and order. If the data are not parallel, then the wrong data may be shown in each facet. The default\n*auto* therefore requires strict equality (`===`) for safety, and using the facet data as mark data is recommended when using the *exclude* facet mode. (To construct parallel data safely, consider using [*array*.map][1] on the facet data.)\n\nWhen mark-level faceting is used, the default *auto* setting is equivalent to *include*: the mark will be faceted if either the **fx** or **fy** channel option (or both) is specified. The null or false option will disable faceting, while *exclude* draws the subset of the mark’s data *not* in the current facet.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map" + }, + "facetAnchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "right", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "const": "left", + "type": "string" + }, + { + "const": "top-left", + "type": "string" + }, + { + "const": "top-right", + "type": "string" + }, + { + "const": "bottom-left", + "type": "string" + }, + { + "const": "bottom-right", + "type": "string" + }, + { + "const": "top-empty", + "type": "string" + }, + { + "const": "right-empty", + "type": "string" + }, + { + "const": "bottom-empty", + "type": "string" + }, + { + "const": "left-empty", + "type": "string" + }, + { + "const": "empty", + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to place the mark with respect to facets; one of:\n\n- null (default for most marks) - display the mark in each non-empty facet\n- *top*, *right*, *bottom*, or *left* - display the mark only in facets on the given side\n- *top-empty*, *right-empty*, *bottom-empty*, or *left-empty* (default for axis marks) - display the mark only in facets that have empty space on the given side: either the margin, or an empty facet\n- *empty* - display the mark in empty facets only" + }, + "fill": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill" + }, + "fillOpacity": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill-opacity][1]; a constant number between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill-opacity" + }, + "filter": { + "$ref": "#/definitions/ChannelValue", + "description": "Applies a transform to filter the mark’s index according to the given channel values; only truthy values are retained.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "fontFamily": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font-family][1]; a constant; defaults to the plot’s font family, which is typically [*system-ui*][2].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-family [2]: https://drafts.csswg.org/css-fonts-4/#valdef-font-family-system-ui" + }, + "fontSize": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font size][1] in pixels; either a constant or a channel; defaults to the plot’s font size, which is typically 10. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-size" + }, + "fontStyle": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font style][1]; a constant; defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-style" + }, + "fontVariant": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font variant][1]; a constant; if the **text** channel contains numbers or dates, defaults to *tabular-nums* to facilitate comparing numbers; otherwise defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant" + }, + "fontWeight": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font weight][1]; a constant; defaults to the plot’s font weight, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight" + }, + "frameAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The frame anchor specifies defaults for **x** and **y**, along with\n**textAnchor** and **lineAnchor**, based on the plot’s frame; it may be one of the four sides (*top*, *right*, *bottom*, *left*), one of the four corners (*top-left*, *top-right*, *bottom-right*, *bottom-left*), or the\n*middle* of the frame." + }, + "fx": { + "$ref": "#/definitions/ChannelValue", + "description": "The horizontal facet position channel, for mark-level faceting, bound to the *fx* scale." + }, + "fy": { + "$ref": "#/definitions/ChannelValue", + "description": "The vertical facet position channel, for mark-level faceting, bound to the\n*fy* scale." + }, + "href": { + "$ref": "#/definitions/ChannelValue", + "description": "The [href][1]; a channel specifying URLs for clickable links. May be used in conjunction with the **target** option to open links in another window.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/href" + }, + "imageFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A CSS [filter][1]; a constant string used to adjust the rendering of images, such as *blur(5px)*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/filter" + }, + "inset": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four insets: **insetTop**,\n**insetRight**, **insetBottom**, and **insetLeft**. All insets typically default to zero, though not always (say when using bin transform). A positive inset reduces effective area, while a negative inset increases it." + }, + "insetLeft": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Insets the left edge by the specified number of pixels. A positive value insets towards the right edge (reducing effective area), while a negative value insets away from the right edge (increasing it)." + }, + "insetRight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Insets the right edge by the specified number of pixels. A positive value insets towards the left edge (reducing effective area), while a negative value insets away from the left edge (increasing it)." + }, + "interval": { + "anyOf": [ + { + "$ref": "#/definitions/Interval" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Enforces uniformity for data at regular intervals, such as integer values or daily samples. The interval may be one of:\n\n- a named time interval such as *day* (for date intervals)\n- a number (for number intervals), defining intervals at integer multiples of *n*\n\nThis option sets the internal transform to the given interval’s\n*interval*.floor function. In addition, the default **domain** will align with interval boundaries." + }, + "label": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A textual label to show on the axis or legend; if null, show no label. By default the scale label is inferred from channel definitions, possibly with an arrow (↑, →, ↓, or ←) to indicate the direction of increasing value.\n\nFor axes and legends only." + }, + "labelAnchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "right", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "const": "left", + "type": "string" + }, + { + "const": "center", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Where to place the axis **label** relative to the plot’s frame. For vertical position scales (*y* and *fy*), may be *top*, *bottom*, or\n*center*; for horizontal position scales (*x* and *fx*), may be *left*,\n*right*, or *center*. Defaults to *center* for ordinal scales (including\n*fx* and *fy*), and otherwise *top* for *y*, and *right* for *x*." + }, + "labelArrow": { + "anyOf": [ + { + "const": "auto", + "type": "string" + }, + { + "const": "up", + "type": "string" + }, + { + "const": "right", + "type": "string" + }, + { + "const": "down", + "type": "string" + }, + { + "const": "left", + "type": "string" + }, + { + "const": "none", + "type": "string" + }, + { + "const": true, + "type": "boolean" + }, + { + "const": false, + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to apply a directional arrow such as → or ↑ to the scale label. If\n*auto* (the default), the presence of the arrow depends on whether the scale is ordinal." + }, + "labelOffset": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The axis **label** position offset (in pixels); default depends on margins and orientation." + }, + "lineAnchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "middle", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line anchor controls how text is aligned (typically vertically) relative to its anchor point; it is one of *top*, *bottom*, or *middle*. If the frame anchor is *top*, *top-left*, or *top-right*, the default line anchor is *top*; if the frame anchor is *bottom*, *bottom-right*, or\n*bottom-left*, the default is *bottom*; otherwise it is *middle*." + }, + "lineHeight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line height in ems; defaults to 1. The line height affects the (typically vertical) separation between adjacent baselines of text, as well as the separation between the text and its anchor point." + }, + "lineWidth": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line width in ems (e.g., 10 for about 20 characters); defaults to infinity, disabling wrapping and clipping.\n\nIf **textOverflow** is null, lines will be wrapped at the specified length. If a line is split at a soft hyphen (\\xad), a hyphen (-) will be displayed at the end of the line. If **textOverflow** is not null, lines will be clipped according to the given strategy." + }, + "margin": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four mark margins: **marginTop**,\n**marginRight**, **marginBottom**, and **marginLeft**; typically defaults to 0, except for axis marks." + }, + "marginBottom": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s bottom margin; the minimum distance in pixels between the bottom edges of the inner and outer plot area." + }, + "marginLeft": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s left margin; the minimum distance in pixels between the left edges of the inner and outer plot area." + }, + "marginRight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s right margin; the minimum distance in pixels between the right edges of the mark’s inner and outer plot area." + }, + "marginTop": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s top margin; the minimum distance in pixels between the top edges of the inner and outer plot area." + }, + "mark": { + "const": "axisFy", + "description": "An axis mark to document the visual encoding of the vertical facet position *fy* scale, comprised of (up to) three marks: a vector for ticks, a text for tick labels, and another text for an axis label. The data defaults to the *fy* scale’s domain; if desired, use one of the **ticks**,\n**tickSpacing**, or **interval** options.\n\nThe **facetAnchor** option defaults to *right-empty* if **anchor** is\n*right*, and *left-empty* if **anchor** is *left*. The default margins likewise depend on **anchor** as follows; in order of **marginTop**,\n**marginRight**, **marginBottom**, and **marginLeft**, in pixels:\n\n- *right* - 20, 40, 20, 0\n- *left* - 20, 0, 20, 40\n\nFor simplicity, and for consistent layout across plots, default axis margins are not affected by tick labels. If tick labels are too long, either increase the margin or shorten the labels: use the *k* SI-prefix tick format; or use the **textOverflow** and **lineWidth** options to clip.", + "type": "string" + }, + "marker": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for markerStart, markerMid, and markerEnd; one of:\n\n- a marker name such as *arrow* or *circle*\n- *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*" + }, + "markerEnd": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The marker for the ending point of a line segment; one of:\n\n- a marker name such as *arrow* or *circle*\n* *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*" + }, + "markerMid": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The marker for any middle (interior) points of a line segment. If the line segment only has a start and end point, this option has no effect. One of:\n\n- a marker name such as *arrow* or *circle*\n* *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*\n* a function - a custom marker function; see below" + }, + "markerStart": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The marker for the starting point of a line segment; one of:\n\n- a marker name such as *arrow* or *circle*\n* *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*" + }, + "meta": { + "$ref": "#/definitions/Meta", + "description": "Specification metadata." + }, + "mixBlendMode": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [mix-blend-mode][1]; a constant string specifying how to blend content such as *multiply*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode" + }, + "monospace": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, changes the default **fontFamily** to *monospace*, and uses simplified monospaced text metrics calculations." + }, + "opacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "A shorthand for setting both **fillOpacity** and **strokeOpacity**; affects the stroke opacity of tick vectors and grid rules, and the fill opacity of tick texts and axis label texts; defaults to 1 for axes and 0.1 for grids." + }, + "paintOrder": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [paint-order][1]; a constant string specifying the order in which the\n**fill**, **stroke**, and any markers are drawn; defaults to *normal*, which draws the fill, then stroke, then markers; defaults to *stroke* for the text mark to create a “halo” around text to improve legibility.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/paint-order" + }, + "params": { + "$ref": "#/definitions/Params", + "description": "Param and Selection definitions." + }, + "plotDefaults": { + "$ref": "#/definitions/PlotAttributes", + "description": "A default set of attributes to apply to all plot components." + }, + "pointerEvents": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [pointer-events][1] property; a constant string such as *none*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/pointer-events" + }, + "reverse": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Applies a transform to reverse the order of the mark’s index, say for reverse input order." + }, + "rotate": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The rotation angle in degrees clockwise; a constant or a channel; defaults to 0°. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel." + }, + "select": { + "$ref": "#/definitions/SelectFilter", + "description": "Applies a filter transform after data is loaded to highlight selected values only. For example, `first` and `last` select the first or last values of series only (using the *z* channel to separate series). Meanwhile, `nearestX` and `nearestY` select the point nearest to the pointer along the *x* or *y* channel dimension. Unlike Mosaic selections, a mark level *select* is internal to the mark only, and does not populate a param or selection value to be shared across clients.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "shapeRendering": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [shape-rendering][1]; a constant string such as *crispEdges*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/shape-rendering" + }, + "sort": { + "anyOf": [ + { + "$ref": "#/definitions/SortOrder" + }, + { + "$ref": "#/definitions/ChannelDomainSort" + } + ], + "description": "Either applies a transform to sort the mark’s index by the specified channel values, or imputes ordinal scale domains from this mark’s channels.\n\nWhen imputing ordinal scale domains from channel values, the **sort** option is an object whose keys are ordinal scale names such as *x* or *fx*, and whose values are channel names such as *y*, *y1*, or *y2*. For example, to impute the *y* scale’s domain from the associated *x* channel values in ascending order:\n\n```js sort: {y: \"x\"} ```\n\nFor different sort options for different scales, replace the channel name with a *value* object and per-scale options:\n\n```js sort: {y: {value: \"-x\"}} ```\n\nWhen sorting the mark’s index, the **sort** option is instead one of:\n\n- a channel value definition for sorting given values in ascending order\n- a {value, order} object for sorting given values\n- a {channel, order} object for sorting the named channel’s values" + }, + "stroke": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke" + }, + "strokeDasharray": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dasharray][1]; a constant number indicating the length in pixels of alternating dashes and gaps, or a constant string of numbers separated by spaces or commas (_e.g._, *10 2* for dashes of 10 pixels separated by gaps of 2 pixels), or *none* (the default) for no dashing\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dasharray" + }, + "strokeDashoffset": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dashoffset][1]; a constant indicating the offset in pixels of the first dash along the stroke; defaults to zero.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dashoffset" + }, + "strokeLinecap": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linecap][1]; a constant specifying how to cap stroked paths, such as *butt*, *round*, or *square*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linecap" + }, + "strokeLinejoin": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linejoin][1]; a constant specifying how to join stroked paths, such as *bevel*, *miter*, *miter-clip*, or *round*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linejoin" + }, + "strokeMiterlimit": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-miterlimit][1]; a constant number specifying how to limit the length of *miter* joins on stroked paths.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-miterlimit" + }, + "strokeOpacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-opacity" + }, + "strokeWidth": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-width][1]; a constant number in pixels, or a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-width" + }, + "target": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [target][1]; a constant string specifying the target window (_e.g._,\n*_blank*) for clickable links; used in conjunction with the **href** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/target" + }, + "text": { + "$ref": "#/definitions/ChannelValue", + "description": "The text contents channel, possibly with line breaks (\\n, \\r\\n, or \\r). If not specified, defaults to the zero-based index [0, 1, 2, …]." + }, + "textAnchor": { + "anyOf": [ + { + "const": "start", + "type": "string" + }, + { + "const": "middle", + "type": "string" + }, + { + "const": "end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [text anchor][1] controls how text is aligned (typically horizontally) relative to its anchor point; it is one of *start*, *end*, or *middle*. If the frame anchor is *left*, *top-left*, or *bottom-left*, the default text anchor is *start*; if the frame anchor is *right*, *top-right*, or\n*bottom-right*, the default is *end*; otherwise it is *middle*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/text-anchor" + }, + "textOverflow": { + "anyOf": [ + { + "type": "null" + }, + { + "const": "clip", + "type": "string" + }, + { + "const": "ellipsis", + "type": "string" + }, + { + "const": "clip-start", + "type": "string" + }, + { + "const": "clip-end", + "type": "string" + }, + { + "const": "ellipsis-start", + "type": "string" + }, + { + "const": "ellipsis-middle", + "type": "string" + }, + { + "const": "ellipsis-end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How truncate (or wrap) lines of text longer than the given **lineWidth**; one of:\n\n- null (default) - preserve overflowing characters (and wrap if needed)\n- *clip* or *clip-end* - remove characters from the end\n- *clip-start* - remove characters from the start\n- *ellipsis* or *ellipsis-end* - replace characters from the end with an ellipsis (…)\n- *ellipsis-start* - replace characters from the start with an ellipsis (…)\n- *ellipsis-middle* - replace characters from the middle with an ellipsis (…)\n\nIf no **title** was specified, if text requires truncation, a title containing the non-truncated text will be implicitly added." + }, + "textStroke": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The tick text **stroke**, say for a *white* outline to improve legibility; defaults to null." + }, + "textStrokeOpacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The tick text **strokeOpacity**; defaults to 1; has no effect unless **textStroke** is set." + }, + "textStrokeWidth": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The tick text **strokeWidth**; defaults to 4; has no effect unless **textStroke** is set." + }, + "tickFormat": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to format inputs (abstract values) for axis tick labels; one of:\n\n- a [d3-format][1] string for numeric scales\n- a [d3-time-format][2] string for temporal scales\n\n[1]: https://d3js.org/d3-time [2]: https://d3js.org/d3-time-format" + }, + "tickPadding": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The distance between an axis tick mark and its associated text label (in pixels); often defaults to 3, but may be affected by **xTickSize** and\n**xTickRotate**." + }, + "tickRotate": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The rotation angle of axis tick labels in degrees clocksize; defaults to 0." + }, + "tickSize": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The length of axis tick marks in pixels; negative values extend in the opposite direction. Defaults to 6 for *x* and *y* axes and *color* and\n*opacity* *ramp* legends, and 0 for *fx* and *fy* axes." + }, + "tickSpacing": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The desired approximate spacing between adjacent axis ticks, affecting the default **ticks**; defaults to 80 pixels for *x* and *fx*, and 35 pixels for *y* and *fy*." + }, + "ticks": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/Interval" + }, + { + "items": {}, + "type": "array" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The desired approximate number of axis ticks, or an explicit array of tick values, or an interval such as *day* or *month*." + }, + "tip": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/TipPointer" + }, + { + "properties": { + "anchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The tip anchor specifies how to orient the tip box relative to its anchor position; it refers to the part of the tip box that is attached to the anchor point. For example, the *top-left* anchor places the top-left corner of tip box near the anchor position, hence placing the tip box below and to the right of the anchor position." + }, + "fontFamily": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font-family][1]; a constant; defaults to the plot’s font family, which is typically [*system-ui*][2].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-family [2]: https://drafts.csswg.org/css-fonts-4/#valdef-font-family-system-ui" + }, + "fontSize": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font size][1] in pixels; either a constant or a channel; defaults to the plot’s font size, which is typically 10. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-size" + }, + "fontStyle": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font style][1]; a constant; defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-style" + }, + "fontVariant": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font variant][1]; a constant; if the **text** channel contains numbers or dates, defaults to *tabular-nums* to facilitate comparing numbers; otherwise defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant" + }, + "fontWeight": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font weight][1]; a constant; defaults to the plot’s font weight, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight" + }, + "format": { + "additionalProperties": false, + "description": "How channel values are formatted for display. If a format is a string, it is interpreted as a (UTC) time format for temporal channels, and otherwise a number format.", + "properties": { + "ariaLabel": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fill": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fillOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fontSize": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fx": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fy": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "geometry": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "height": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "href": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "length": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "opacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "path": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "r": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "rotate": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "src": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "stroke": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeWidth": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "symbol": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "text": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "title": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "weight": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "width": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "z": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + } + }, + "type": "object" + }, + "frameAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The frame anchor specifies defaults for **x** and **y** based on the plot’s frame; it may be one of the four sides (*top*, *right*, *bottom*, *left*), one of the four corners (*top-left*, *top-right*, *bottom-right*,\n*bottom-left*), or the *middle* of the frame. For example, for tips distributed horizontally at the top of the frame:\n\n```js Plot.tip(data, {x: \"date\", frameAnchor: \"top\"}) ```" + }, + "lineHeight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line height in ems; defaults to 1. The line height affects the (typically vertical) separation between adjacent baselines of text, as well as the separation between the text and its anchor point." + }, + "lineWidth": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line width in ems (e.g., 10 for about 20 characters); defaults to infinity, disabling wrapping and clipping.\n\nIf **textOverflow** is null, lines will be wrapped at the specified length. If a line is split at a soft hyphen (\\xad), a hyphen (-) will be displayed at the end of the line. If **textOverflow** is not null, lines will be clipped according to the given strategy." + }, + "monospace": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, changes the default **fontFamily** to *monospace*, and uses simplified monospaced text metrics calculations." + }, + "pathFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The image filter for the tip’s box; defaults to a drop shadow." + }, + "pointer": { + "$ref": "#/definitions/TipPointer" + }, + "pointerSize": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The size of the tip’s pointer in pixels; defaults to 12." + }, + "preferredAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If an explicit tip anchor is not specified, an anchor is chosen automatically such that the tip fits within the plot’s frame; if the preferred anchor fits, it is chosen." + }, + "textAnchor": { + "anyOf": [ + { + "const": "start", + "type": "string" + }, + { + "const": "middle", + "type": "string" + }, + { + "const": "end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [text anchor][1] controls how text is aligned (typically horizontally) relative to its anchor point; it is one of *start*, *end*, or *middle*. If the frame anchor is *left*, *top-left*, or *bottom-left*, the default text anchor is *start*; if the frame anchor is *right*, *top-right*, or\n*bottom-right*, the default is *end*; otherwise it is *middle*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/text-anchor" + }, + "textOverflow": { + "anyOf": [ + { + "type": "null" + }, + { + "const": "clip", + "type": "string" + }, + { + "const": "ellipsis", + "type": "string" + }, + { + "const": "clip-start", + "type": "string" + }, + { + "const": "clip-end", + "type": "string" + }, + { + "const": "ellipsis-start", + "type": "string" + }, + { + "const": "ellipsis-middle", + "type": "string" + }, + { + "const": "ellipsis-end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How truncate (or wrap) lines of text longer than the given **lineWidth**; one of:\n\n- null (default) - preserve overflowing characters (and wrap if needed)\n- *clip* or *clip-end* - remove characters from the end\n- *clip-start* - remove characters from the start\n- *ellipsis* or *ellipsis-end* - replace characters from the end with an ellipsis (…)\n- *ellipsis-start* - replace characters from the start with an ellipsis (…)\n- *ellipsis-middle* - replace characters from the middle with an ellipsis (…)\n\nIf no **title** was specified, if text requires truncation, a title containing the non-truncated text will be implicitly added." + }, + "textPadding": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The padding around the text in pixels; defaults to 8." + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + } + }, + "type": "object" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to generate a tooltip for this mark, and any tip options." + }, + "title": { + "$ref": "#/definitions/ChannelValue", + "description": "The title; a channel specifying accessible, short textual descriptions as strings (possibly with newlines). If the tip option is specified, the title will be displayed with an interactive tooltip instead of using the SVG [title element][1].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/title" + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel specifying the text’s anchor point, typically bound to the *x* scale." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel specifying the text’s anchor point, typically bound to the *y* scale." + }, + "z": { + "$ref": "#/definitions/ChannelValue", + "description": "An optional ordinal channel for grouping data into series." + } + }, + "required": [ + "mark" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "$schema": { + "description": "A [JSON schema](http://json-schema.org/) URL for this specification, such as https://uwdata.github.io/mosaic/schema/latest.json. This property enables validation and autocomplete in editors with JSON schema support.", + "format": "uri", + "type": "string" + }, + "anchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "right", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "const": "left", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The side of the frame on which to place the axis: *top* or *bottom* for horizontal axes (axisX and axisFx) and their associated vertical grids (gridX and gridFx), or *left* or *right* for vertical axes (axisY and axisFY) and their associated horizontal grids (gridY and gridFy).\n\nThe default **anchor** depends on the associated scale:\n\n- *x* - *bottom*\n- *y* - *left*\n- *fx* - *top* if there is a *bottom* *x* axis, and otherwise *bottom*\n- *fy* - *right* if there is a *left* *y* axis, and otherwise *right*\n\nFor grids, the **anchor** also affects the extent of grid lines when the opposite dimension is specified (**x** for gridY and **y** for gridX)." + }, + "ariaDescription": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-description][1]; a constant textual description.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-description" + }, + "ariaHidden": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-hidden][1] state; a constant indicating whether the element is exposed to an accessibility API.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-hidden" + }, + "ariaLabel": { + "$ref": "#/definitions/ChannelValue", + "description": "The [aria-label][1]; a channel specifying short textual labels representing the value in the accessibility tree.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-label" + }, + "clip": { + "anyOf": [ + { + "const": "frame", + "type": "string" + }, + { + "const": "sphere", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to clip the mark; one of:\n\n- *frame* or true - clip to the plot’s frame (inner area)\n- *sphere* - clip to the projected sphere (*e.g.*, front hemisphere)\n- null or false - do not clip\n\nThe *sphere* clip option requires a geographic projection." + }, + "color": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A shorthand for setting both **fill** and **stroke**; affects the stroke of tick vectors and grid rules, and the fill of tick texts and axis label texts; defaults to *currentColor*." + }, + "config": { + "$ref": "#/definitions/Config", + "description": "Configuration options." + }, + "data": { + "$ref": "#/definitions/Data", + "description": "Dataset definitions." + }, + "dx": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The horizontal offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "dy": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The vertical offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "facet": { + "anyOf": [ + { + "const": "auto", + "type": "string" + }, + { + "const": "include", + "type": "string" + }, + { + "const": "exclude", + "type": "string" + }, + { + "const": "super", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to enable or disable faceting; one of:\n\n- *auto* (default) - automatically determine if this mark should be faceted\n- *include* (or true) - draw the subset of the mark’s data in the current facet\n- *exclude* - draw the subset of the mark’s data *not* in the current facet\n- *super* - draw this mark in a single frame that covers all facets\n- null (or false) - repeat this mark’s data across all facets (*i.e.*, no faceting)\n\nWhen a mark uses *super* faceting, it is not allowed to use position scales (*x*, *y*, *fx*, or *fy*); *super* faceting is intended for decorations, such as labels and legends.\n\nWhen top-level faceting is used, the default *auto* setting is equivalent to *include* when the mark data is strictly equal to the top-level facet data; otherwise it is equivalent to null. When the *include* or *exclude* facet mode is chosen, the mark data must be parallel to the top-level facet data: the data must have the same length and order. If the data are not parallel, then the wrong data may be shown in each facet. The default\n*auto* therefore requires strict equality (`===`) for safety, and using the facet data as mark data is recommended when using the *exclude* facet mode. (To construct parallel data safely, consider using [*array*.map][1] on the facet data.)\n\nWhen mark-level faceting is used, the default *auto* setting is equivalent to *include*: the mark will be faceted if either the **fx** or **fy** channel option (or both) is specified. The null or false option will disable faceting, while *exclude* draws the subset of the mark’s data *not* in the current facet.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map" + }, + "facetAnchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "right", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "const": "left", + "type": "string" + }, + { + "const": "top-left", + "type": "string" + }, + { + "const": "top-right", + "type": "string" + }, + { + "const": "bottom-left", + "type": "string" + }, + { + "const": "bottom-right", + "type": "string" + }, + { + "const": "top-empty", + "type": "string" + }, + { + "const": "right-empty", + "type": "string" + }, + { + "const": "bottom-empty", + "type": "string" + }, + { + "const": "left-empty", + "type": "string" + }, + { + "const": "empty", + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to place the mark with respect to facets; one of:\n\n- null (default for most marks) - display the mark in each non-empty facet\n- *top*, *right*, *bottom*, or *left* - display the mark only in facets on the given side\n- *top-empty*, *right-empty*, *bottom-empty*, or *left-empty* (default for axis marks) - display the mark only in facets that have empty space on the given side: either the margin, or an empty facet\n- *empty* - display the mark in empty facets only" + }, + "fill": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill" + }, + "fillOpacity": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill-opacity][1]; a constant number between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill-opacity" + }, + "filter": { + "$ref": "#/definitions/ChannelValue", + "description": "Applies a transform to filter the mark’s index according to the given channel values; only truthy values are retained.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "fx": { + "$ref": "#/definitions/ChannelValue", + "description": "The horizontal facet position channel, for mark-level faceting, bound to the *fx* scale." + }, + "fy": { + "$ref": "#/definitions/ChannelValue", + "description": "The vertical facet position channel, for mark-level faceting, bound to the\n*fy* scale." + }, + "href": { + "$ref": "#/definitions/ChannelValue", + "description": "The [href][1]; a channel specifying URLs for clickable links. May be used in conjunction with the **target** option to open links in another window.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/href" + }, + "imageFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A CSS [filter][1]; a constant string used to adjust the rendering of images, such as *blur(5px)*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/filter" + }, + "inset": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four insets: **insetTop**,\n**insetRight**, **insetBottom**, and **insetLeft**. All insets typically default to zero, though not always (say when using bin transform). A positive inset reduces effective area, while a negative inset increases it." + }, + "insetBottom": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Insets the bottom edge by the specified number of pixels. A positive value insets towards the top edge (reducing effective area), while a negative value insets away from the top edge (increasing it)." + }, + "insetTop": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Insets the top edge by the specified number of pixels. A positive value insets towards the bottom edge (reducing effective area), while a negative value insets away from the bottom edge (increasing it)." + }, + "interval": { + "anyOf": [ + { + "$ref": "#/definitions/Interval" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Enforces uniformity for data at regular intervals, such as integer values or daily samples. The interval may be one of:\n\n- a named time interval such as *day* (for date intervals)\n- a number (for number intervals), defining intervals at integer multiples of *n*\n\nThis option sets the internal transform to the given interval’s\n*interval*.floor function. In addition, the default **domain** will align with interval boundaries." + }, + "margin": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four mark margins: **marginTop**,\n**marginRight**, **marginBottom**, and **marginLeft**; typically defaults to 0, except for axis marks." + }, + "marginBottom": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s bottom margin; the minimum distance in pixels between the bottom edges of the inner and outer plot area." + }, + "marginLeft": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s left margin; the minimum distance in pixels between the left edges of the inner and outer plot area." + }, + "marginRight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s right margin; the minimum distance in pixels between the right edges of the mark’s inner and outer plot area." + }, + "marginTop": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s top margin; the minimum distance in pixels between the top edges of the inner and outer plot area." + }, + "mark": { + "const": "gridX", + "description": "A horizontally-positioned ruleX mark (a vertical line, |) that renders a grid for the *x* scale. The data defaults to tick values sampled from the\n*x* scale’s domain; if desired, use one of the **ticks**, **tickSpacing**, or **interval** options.", + "type": "string" + }, + "marker": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for markerStart, markerMid, and markerEnd; one of:\n\n- a marker name such as *arrow* or *circle*\n- *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*" + }, + "markerEnd": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The marker for the ending point of a line segment; one of:\n\n- a marker name such as *arrow* or *circle*\n* *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*" + }, + "markerMid": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The marker for any middle (interior) points of a line segment. If the line segment only has a start and end point, this option has no effect. One of:\n\n- a marker name such as *arrow* or *circle*\n* *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*\n* a function - a custom marker function; see below" + }, + "markerStart": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The marker for the starting point of a line segment; one of:\n\n- a marker name such as *arrow* or *circle*\n* *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*" + }, + "meta": { + "$ref": "#/definitions/Meta", + "description": "Specification metadata." + }, + "mixBlendMode": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [mix-blend-mode][1]; a constant string specifying how to blend content such as *multiply*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode" + }, + "opacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "A shorthand for setting both **fillOpacity** and **strokeOpacity**; affects the stroke opacity of tick vectors and grid rules, and the fill opacity of tick texts and axis label texts; defaults to 1 for axes and 0.1 for grids." + }, + "paintOrder": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [paint-order][1]; a constant string specifying the order in which the\n**fill**, **stroke**, and any markers are drawn; defaults to *normal*, which draws the fill, then stroke, then markers; defaults to *stroke* for the text mark to create a “halo” around text to improve legibility.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/paint-order" + }, + "params": { + "$ref": "#/definitions/Params", + "description": "Param and Selection definitions." + }, + "plotDefaults": { + "$ref": "#/definitions/PlotAttributes", + "description": "A default set of attributes to apply to all plot components." + }, + "pointerEvents": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [pointer-events][1] property; a constant string such as *none*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/pointer-events" + }, + "reverse": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Applies a transform to reverse the order of the mark’s index, say for reverse input order." + }, + "select": { + "$ref": "#/definitions/SelectFilter", + "description": "Applies a filter transform after data is loaded to highlight selected values only. For example, `first` and `last` select the first or last values of series only (using the *z* channel to separate series). Meanwhile, `nearestX` and `nearestY` select the point nearest to the pointer along the *x* or *y* channel dimension. Unlike Mosaic selections, a mark level *select* is internal to the mark only, and does not populate a param or selection value to be shared across clients.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "shapeRendering": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [shape-rendering][1]; a constant string such as *crispEdges*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/shape-rendering" + }, + "sort": { + "anyOf": [ + { + "$ref": "#/definitions/SortOrder" + }, + { + "$ref": "#/definitions/ChannelDomainSort" + } + ], + "description": "Either applies a transform to sort the mark’s index by the specified channel values, or imputes ordinal scale domains from this mark’s channels.\n\nWhen imputing ordinal scale domains from channel values, the **sort** option is an object whose keys are ordinal scale names such as *x* or *fx*, and whose values are channel names such as *y*, *y1*, or *y2*. For example, to impute the *y* scale’s domain from the associated *x* channel values in ascending order:\n\n```js sort: {y: \"x\"} ```\n\nFor different sort options for different scales, replace the channel name with a *value* object and per-scale options:\n\n```js sort: {y: {value: \"-x\"}} ```\n\nWhen sorting the mark’s index, the **sort** option is instead one of:\n\n- a channel value definition for sorting given values in ascending order\n- a {value, order} object for sorting given values\n- a {channel, order} object for sorting the named channel’s values" + }, + "stroke": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke" + }, + "strokeDasharray": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dasharray][1]; a constant number indicating the length in pixels of alternating dashes and gaps, or a constant string of numbers separated by spaces or commas (_e.g._, *10 2* for dashes of 10 pixels separated by gaps of 2 pixels), or *none* (the default) for no dashing\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dasharray" + }, + "strokeDashoffset": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dashoffset][1]; a constant indicating the offset in pixels of the first dash along the stroke; defaults to zero.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dashoffset" + }, + "strokeLinecap": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linecap][1]; a constant specifying how to cap stroked paths, such as *butt*, *round*, or *square*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linecap" + }, + "strokeLinejoin": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linejoin][1]; a constant specifying how to join stroked paths, such as *bevel*, *miter*, *miter-clip*, or *round*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linejoin" + }, + "strokeMiterlimit": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-miterlimit][1]; a constant number specifying how to limit the length of *miter* joins on stroked paths.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-miterlimit" + }, + "strokeOpacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-opacity" + }, + "strokeWidth": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-width][1]; a constant number in pixels, or a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-width" + }, + "target": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [target][1]; a constant string specifying the target window (_e.g._,\n*_blank*) for clickable links; used in conjunction with the **href** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/target" + }, + "tickSpacing": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The desired approximate spacing between adjacent axis ticks, affecting the default **ticks**; defaults to 80 pixels for *x* and *fx*, and 35 pixels for *y* and *fy*." + }, + "ticks": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/Interval" + }, + { + "items": {}, + "type": "array" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The desired approximate number of axis ticks, or an explicit array of tick values, or an interval such as *day* or *month*." + }, + "tip": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/TipPointer" + }, + { + "properties": { + "anchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The tip anchor specifies how to orient the tip box relative to its anchor position; it refers to the part of the tip box that is attached to the anchor point. For example, the *top-left* anchor places the top-left corner of tip box near the anchor position, hence placing the tip box below and to the right of the anchor position." + }, + "fontFamily": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font-family][1]; a constant; defaults to the plot’s font family, which is typically [*system-ui*][2].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-family [2]: https://drafts.csswg.org/css-fonts-4/#valdef-font-family-system-ui" + }, + "fontSize": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font size][1] in pixels; either a constant or a channel; defaults to the plot’s font size, which is typically 10. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-size" + }, + "fontStyle": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font style][1]; a constant; defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-style" + }, + "fontVariant": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font variant][1]; a constant; if the **text** channel contains numbers or dates, defaults to *tabular-nums* to facilitate comparing numbers; otherwise defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant" + }, + "fontWeight": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font weight][1]; a constant; defaults to the plot’s font weight, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight" + }, + "format": { + "additionalProperties": false, + "description": "How channel values are formatted for display. If a format is a string, it is interpreted as a (UTC) time format for temporal channels, and otherwise a number format.", + "properties": { + "ariaLabel": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fill": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fillOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fontSize": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fx": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fy": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "geometry": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "height": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "href": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "length": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "opacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "path": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "r": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "rotate": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "src": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "stroke": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeWidth": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "symbol": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "text": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "title": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "weight": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "width": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "z": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + } + }, + "type": "object" + }, + "frameAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The frame anchor specifies defaults for **x** and **y** based on the plot’s frame; it may be one of the four sides (*top*, *right*, *bottom*, *left*), one of the four corners (*top-left*, *top-right*, *bottom-right*,\n*bottom-left*), or the *middle* of the frame. For example, for tips distributed horizontally at the top of the frame:\n\n```js Plot.tip(data, {x: \"date\", frameAnchor: \"top\"}) ```" + }, + "lineHeight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line height in ems; defaults to 1. The line height affects the (typically vertical) separation between adjacent baselines of text, as well as the separation between the text and its anchor point." + }, + "lineWidth": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line width in ems (e.g., 10 for about 20 characters); defaults to infinity, disabling wrapping and clipping.\n\nIf **textOverflow** is null, lines will be wrapped at the specified length. If a line is split at a soft hyphen (\\xad), a hyphen (-) will be displayed at the end of the line. If **textOverflow** is not null, lines will be clipped according to the given strategy." + }, + "monospace": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, changes the default **fontFamily** to *monospace*, and uses simplified monospaced text metrics calculations." + }, + "pathFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The image filter for the tip’s box; defaults to a drop shadow." + }, + "pointer": { + "$ref": "#/definitions/TipPointer" + }, + "pointerSize": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The size of the tip’s pointer in pixels; defaults to 12." + }, + "preferredAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If an explicit tip anchor is not specified, an anchor is chosen automatically such that the tip fits within the plot’s frame; if the preferred anchor fits, it is chosen." + }, + "textAnchor": { + "anyOf": [ + { + "const": "start", + "type": "string" + }, + { + "const": "middle", + "type": "string" + }, + { + "const": "end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [text anchor][1] controls how text is aligned (typically horizontally) relative to its anchor point; it is one of *start*, *end*, or *middle*. If the frame anchor is *left*, *top-left*, or *bottom-left*, the default text anchor is *start*; if the frame anchor is *right*, *top-right*, or\n*bottom-right*, the default is *end*; otherwise it is *middle*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/text-anchor" + }, + "textOverflow": { + "anyOf": [ + { + "type": "null" + }, + { + "const": "clip", + "type": "string" + }, + { + "const": "ellipsis", + "type": "string" + }, + { + "const": "clip-start", + "type": "string" + }, + { + "const": "clip-end", + "type": "string" + }, + { + "const": "ellipsis-start", + "type": "string" + }, + { + "const": "ellipsis-middle", + "type": "string" + }, + { + "const": "ellipsis-end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How truncate (or wrap) lines of text longer than the given **lineWidth**; one of:\n\n- null (default) - preserve overflowing characters (and wrap if needed)\n- *clip* or *clip-end* - remove characters from the end\n- *clip-start* - remove characters from the start\n- *ellipsis* or *ellipsis-end* - replace characters from the end with an ellipsis (…)\n- *ellipsis-start* - replace characters from the start with an ellipsis (…)\n- *ellipsis-middle* - replace characters from the middle with an ellipsis (…)\n\nIf no **title** was specified, if text requires truncation, a title containing the non-truncated text will be implicitly added." + }, + "textPadding": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The padding around the text in pixels; defaults to 8." + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + } + }, + "type": "object" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to generate a tooltip for this mark, and any tip options." + }, + "title": { + "$ref": "#/definitions/ChannelValue", + "description": "The title; a channel specifying accessible, short textual descriptions as strings (possibly with newlines). If the tip option is specified, the title will be displayed with an interactive tooltip instead of using the SVG [title element][1].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/title" + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position of the tick; an optional channel bound to the *x* scale. If not specified, the rule will be horizontally centered in the plot’s frame." + }, + "y": { + "$ref": "#/definitions/ChannelValueIntervalSpec", + "description": "Shorthand for specifying both the primary and secondary vertical position of the tick as the bounds of the containing interval; can only be used in conjunction with the **interval** option." + }, + "y1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The primary (starting, often bottom) vertical position of the tick; a channel bound to the *y* scale.\n\nIf *y* represents ordinal values, use a tickX mark instead." + }, + "y2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The secondary (ending, often top) vertical position of the tick; a channel bound to the *y* scale.\n\nIf *y* represents ordinal values, use a tickX mark instead." + } + }, + "required": [ + "mark" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "$schema": { + "description": "A [JSON schema](http://json-schema.org/) URL for this specification, such as https://uwdata.github.io/mosaic/schema/latest.json. This property enables validation and autocomplete in editors with JSON schema support.", + "format": "uri", + "type": "string" + }, + "anchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "right", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "const": "left", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The side of the frame on which to place the axis: *top* or *bottom* for horizontal axes (axisX and axisFx) and their associated vertical grids (gridX and gridFx), or *left* or *right* for vertical axes (axisY and axisFY) and their associated horizontal grids (gridY and gridFy).\n\nThe default **anchor** depends on the associated scale:\n\n- *x* - *bottom*\n- *y* - *left*\n- *fx* - *top* if there is a *bottom* *x* axis, and otherwise *bottom*\n- *fy* - *right* if there is a *left* *y* axis, and otherwise *right*\n\nFor grids, the **anchor** also affects the extent of grid lines when the opposite dimension is specified (**x** for gridY and **y** for gridX)." + }, + "ariaDescription": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-description][1]; a constant textual description.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-description" + }, + "ariaHidden": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-hidden][1] state; a constant indicating whether the element is exposed to an accessibility API.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-hidden" + }, + "ariaLabel": { + "$ref": "#/definitions/ChannelValue", + "description": "The [aria-label][1]; a channel specifying short textual labels representing the value in the accessibility tree.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-label" + }, + "clip": { + "anyOf": [ + { + "const": "frame", + "type": "string" + }, + { + "const": "sphere", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to clip the mark; one of:\n\n- *frame* or true - clip to the plot’s frame (inner area)\n- *sphere* - clip to the projected sphere (*e.g.*, front hemisphere)\n- null or false - do not clip\n\nThe *sphere* clip option requires a geographic projection." + }, + "color": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A shorthand for setting both **fill** and **stroke**; affects the stroke of tick vectors and grid rules, and the fill of tick texts and axis label texts; defaults to *currentColor*." + }, + "config": { + "$ref": "#/definitions/Config", + "description": "Configuration options." + }, + "data": { + "$ref": "#/definitions/Data", + "description": "Dataset definitions." + }, + "dx": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The horizontal offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "dy": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The vertical offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "facet": { + "anyOf": [ + { + "const": "auto", + "type": "string" + }, + { + "const": "include", + "type": "string" + }, + { + "const": "exclude", + "type": "string" + }, + { + "const": "super", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to enable or disable faceting; one of:\n\n- *auto* (default) - automatically determine if this mark should be faceted\n- *include* (or true) - draw the subset of the mark’s data in the current facet\n- *exclude* - draw the subset of the mark’s data *not* in the current facet\n- *super* - draw this mark in a single frame that covers all facets\n- null (or false) - repeat this mark’s data across all facets (*i.e.*, no faceting)\n\nWhen a mark uses *super* faceting, it is not allowed to use position scales (*x*, *y*, *fx*, or *fy*); *super* faceting is intended for decorations, such as labels and legends.\n\nWhen top-level faceting is used, the default *auto* setting is equivalent to *include* when the mark data is strictly equal to the top-level facet data; otherwise it is equivalent to null. When the *include* or *exclude* facet mode is chosen, the mark data must be parallel to the top-level facet data: the data must have the same length and order. If the data are not parallel, then the wrong data may be shown in each facet. The default\n*auto* therefore requires strict equality (`===`) for safety, and using the facet data as mark data is recommended when using the *exclude* facet mode. (To construct parallel data safely, consider using [*array*.map][1] on the facet data.)\n\nWhen mark-level faceting is used, the default *auto* setting is equivalent to *include*: the mark will be faceted if either the **fx** or **fy** channel option (or both) is specified. The null or false option will disable faceting, while *exclude* draws the subset of the mark’s data *not* in the current facet.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map" + }, + "facetAnchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "right", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "const": "left", + "type": "string" + }, + { + "const": "top-left", + "type": "string" + }, + { + "const": "top-right", + "type": "string" + }, + { + "const": "bottom-left", + "type": "string" + }, + { + "const": "bottom-right", + "type": "string" + }, + { + "const": "top-empty", + "type": "string" + }, + { + "const": "right-empty", + "type": "string" + }, + { + "const": "bottom-empty", + "type": "string" + }, + { + "const": "left-empty", + "type": "string" + }, + { + "const": "empty", + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to place the mark with respect to facets; one of:\n\n- null (default for most marks) - display the mark in each non-empty facet\n- *top*, *right*, *bottom*, or *left* - display the mark only in facets on the given side\n- *top-empty*, *right-empty*, *bottom-empty*, or *left-empty* (default for axis marks) - display the mark only in facets that have empty space on the given side: either the margin, or an empty facet\n- *empty* - display the mark in empty facets only" + }, + "fill": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill" + }, + "fillOpacity": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill-opacity][1]; a constant number between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill-opacity" + }, + "filter": { + "$ref": "#/definitions/ChannelValue", + "description": "Applies a transform to filter the mark’s index according to the given channel values; only truthy values are retained.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "fx": { + "$ref": "#/definitions/ChannelValue", + "description": "The horizontal facet position channel, for mark-level faceting, bound to the *fx* scale." + }, + "fy": { + "$ref": "#/definitions/ChannelValue", + "description": "The vertical facet position channel, for mark-level faceting, bound to the\n*fy* scale." + }, + "href": { + "$ref": "#/definitions/ChannelValue", + "description": "The [href][1]; a channel specifying URLs for clickable links. May be used in conjunction with the **target** option to open links in another window.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/href" + }, + "imageFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A CSS [filter][1]; a constant string used to adjust the rendering of images, such as *blur(5px)*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/filter" + }, + "inset": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four insets: **insetTop**,\n**insetRight**, **insetBottom**, and **insetLeft**. All insets typically default to zero, though not always (say when using bin transform). A positive inset reduces effective area, while a negative inset increases it." + }, + "insetLeft": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Insets the left edge by the specified number of pixels. A positive value insets towards the right edge (reducing effective area), while a negative value insets away from the right edge (increasing it)." + }, + "insetRight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Insets the right edge by the specified number of pixels. A positive value insets towards the left edge (reducing effective area), while a negative value insets away from the left edge (increasing it)." + }, + "interval": { + "anyOf": [ + { + "$ref": "#/definitions/Interval" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Enforces uniformity for data at regular intervals, such as integer values or daily samples. The interval may be one of:\n\n- a named time interval such as *day* (for date intervals)\n- a number (for number intervals), defining intervals at integer multiples of *n*\n\nThis option sets the internal transform to the given interval’s\n*interval*.floor function. In addition, the default **domain** will align with interval boundaries." + }, + "margin": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four mark margins: **marginTop**,\n**marginRight**, **marginBottom**, and **marginLeft**; typically defaults to 0, except for axis marks." + }, + "marginBottom": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s bottom margin; the minimum distance in pixels between the bottom edges of the inner and outer plot area." + }, + "marginLeft": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s left margin; the minimum distance in pixels between the left edges of the inner and outer plot area." + }, + "marginRight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s right margin; the minimum distance in pixels between the right edges of the mark’s inner and outer plot area." + }, + "marginTop": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s top margin; the minimum distance in pixels between the top edges of the inner and outer plot area." + }, + "mark": { + "const": "gridY", + "description": "A vertically-positioned ruleY mark (a horizontal line, —) that renders a grid for the *y* scale. The data defaults to tick values sampled from the\n*y* scale’s domain; if desired, use one of the **ticks**, **tickSpacing**, or **interval** options.", + "type": "string" + }, + "marker": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for markerStart, markerMid, and markerEnd; one of:\n\n- a marker name such as *arrow* or *circle*\n- *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*" + }, + "markerEnd": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The marker for the ending point of a line segment; one of:\n\n- a marker name such as *arrow* or *circle*\n* *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*" + }, + "markerMid": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The marker for any middle (interior) points of a line segment. If the line segment only has a start and end point, this option has no effect. One of:\n\n- a marker name such as *arrow* or *circle*\n* *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*\n* a function - a custom marker function; see below" + }, + "markerStart": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The marker for the starting point of a line segment; one of:\n\n- a marker name such as *arrow* or *circle*\n* *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*" + }, + "meta": { + "$ref": "#/definitions/Meta", + "description": "Specification metadata." + }, + "mixBlendMode": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [mix-blend-mode][1]; a constant string specifying how to blend content such as *multiply*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode" + }, + "opacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "A shorthand for setting both **fillOpacity** and **strokeOpacity**; affects the stroke opacity of tick vectors and grid rules, and the fill opacity of tick texts and axis label texts; defaults to 1 for axes and 0.1 for grids." + }, + "paintOrder": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [paint-order][1]; a constant string specifying the order in which the\n**fill**, **stroke**, and any markers are drawn; defaults to *normal*, which draws the fill, then stroke, then markers; defaults to *stroke* for the text mark to create a “halo” around text to improve legibility.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/paint-order" + }, + "params": { + "$ref": "#/definitions/Params", + "description": "Param and Selection definitions." + }, + "plotDefaults": { + "$ref": "#/definitions/PlotAttributes", + "description": "A default set of attributes to apply to all plot components." + }, + "pointerEvents": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [pointer-events][1] property; a constant string such as *none*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/pointer-events" + }, + "reverse": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Applies a transform to reverse the order of the mark’s index, say for reverse input order." + }, + "select": { + "$ref": "#/definitions/SelectFilter", + "description": "Applies a filter transform after data is loaded to highlight selected values only. For example, `first` and `last` select the first or last values of series only (using the *z* channel to separate series). Meanwhile, `nearestX` and `nearestY` select the point nearest to the pointer along the *x* or *y* channel dimension. Unlike Mosaic selections, a mark level *select* is internal to the mark only, and does not populate a param or selection value to be shared across clients.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "shapeRendering": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [shape-rendering][1]; a constant string such as *crispEdges*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/shape-rendering" + }, + "sort": { + "anyOf": [ + { + "$ref": "#/definitions/SortOrder" + }, + { + "$ref": "#/definitions/ChannelDomainSort" + } + ], + "description": "Either applies a transform to sort the mark’s index by the specified channel values, or imputes ordinal scale domains from this mark’s channels.\n\nWhen imputing ordinal scale domains from channel values, the **sort** option is an object whose keys are ordinal scale names such as *x* or *fx*, and whose values are channel names such as *y*, *y1*, or *y2*. For example, to impute the *y* scale’s domain from the associated *x* channel values in ascending order:\n\n```js sort: {y: \"x\"} ```\n\nFor different sort options for different scales, replace the channel name with a *value* object and per-scale options:\n\n```js sort: {y: {value: \"-x\"}} ```\n\nWhen sorting the mark’s index, the **sort** option is instead one of:\n\n- a channel value definition for sorting given values in ascending order\n- a {value, order} object for sorting given values\n- a {channel, order} object for sorting the named channel’s values" + }, + "stroke": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke" + }, + "strokeDasharray": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dasharray][1]; a constant number indicating the length in pixels of alternating dashes and gaps, or a constant string of numbers separated by spaces or commas (_e.g._, *10 2* for dashes of 10 pixels separated by gaps of 2 pixels), or *none* (the default) for no dashing\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dasharray" + }, + "strokeDashoffset": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dashoffset][1]; a constant indicating the offset in pixels of the first dash along the stroke; defaults to zero.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dashoffset" + }, + "strokeLinecap": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linecap][1]; a constant specifying how to cap stroked paths, such as *butt*, *round*, or *square*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linecap" + }, + "strokeLinejoin": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linejoin][1]; a constant specifying how to join stroked paths, such as *bevel*, *miter*, *miter-clip*, or *round*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linejoin" + }, + "strokeMiterlimit": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-miterlimit][1]; a constant number specifying how to limit the length of *miter* joins on stroked paths.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-miterlimit" + }, + "strokeOpacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-opacity" + }, + "strokeWidth": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-width][1]; a constant number in pixels, or a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-width" + }, + "target": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [target][1]; a constant string specifying the target window (_e.g._,\n*_blank*) for clickable links; used in conjunction with the **href** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/target" + }, + "tickSpacing": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The desired approximate spacing between adjacent axis ticks, affecting the default **ticks**; defaults to 80 pixels for *x* and *fx*, and 35 pixels for *y* and *fy*." + }, + "ticks": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/Interval" + }, + { + "items": {}, + "type": "array" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The desired approximate number of axis ticks, or an explicit array of tick values, or an interval such as *day* or *month*." + }, + "tip": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/TipPointer" + }, + { + "properties": { + "anchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The tip anchor specifies how to orient the tip box relative to its anchor position; it refers to the part of the tip box that is attached to the anchor point. For example, the *top-left* anchor places the top-left corner of tip box near the anchor position, hence placing the tip box below and to the right of the anchor position." + }, + "fontFamily": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font-family][1]; a constant; defaults to the plot’s font family, which is typically [*system-ui*][2].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-family [2]: https://drafts.csswg.org/css-fonts-4/#valdef-font-family-system-ui" + }, + "fontSize": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font size][1] in pixels; either a constant or a channel; defaults to the plot’s font size, which is typically 10. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-size" + }, + "fontStyle": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font style][1]; a constant; defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-style" + }, + "fontVariant": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font variant][1]; a constant; if the **text** channel contains numbers or dates, defaults to *tabular-nums* to facilitate comparing numbers; otherwise defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant" + }, + "fontWeight": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font weight][1]; a constant; defaults to the plot’s font weight, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight" + }, + "format": { + "additionalProperties": false, + "description": "How channel values are formatted for display. If a format is a string, it is interpreted as a (UTC) time format for temporal channels, and otherwise a number format.", + "properties": { + "ariaLabel": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fill": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fillOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fontSize": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fx": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fy": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "geometry": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "height": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "href": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "length": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "opacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "path": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "r": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "rotate": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "src": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "stroke": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeWidth": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "symbol": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "text": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "title": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "weight": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "width": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "z": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + } + }, + "type": "object" + }, + "frameAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The frame anchor specifies defaults for **x** and **y** based on the plot’s frame; it may be one of the four sides (*top*, *right*, *bottom*, *left*), one of the four corners (*top-left*, *top-right*, *bottom-right*,\n*bottom-left*), or the *middle* of the frame. For example, for tips distributed horizontally at the top of the frame:\n\n```js Plot.tip(data, {x: \"date\", frameAnchor: \"top\"}) ```" + }, + "lineHeight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line height in ems; defaults to 1. The line height affects the (typically vertical) separation between adjacent baselines of text, as well as the separation between the text and its anchor point." + }, + "lineWidth": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line width in ems (e.g., 10 for about 20 characters); defaults to infinity, disabling wrapping and clipping.\n\nIf **textOverflow** is null, lines will be wrapped at the specified length. If a line is split at a soft hyphen (\\xad), a hyphen (-) will be displayed at the end of the line. If **textOverflow** is not null, lines will be clipped according to the given strategy." + }, + "monospace": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, changes the default **fontFamily** to *monospace*, and uses simplified monospaced text metrics calculations." + }, + "pathFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The image filter for the tip’s box; defaults to a drop shadow." + }, + "pointer": { + "$ref": "#/definitions/TipPointer" + }, + "pointerSize": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The size of the tip’s pointer in pixels; defaults to 12." + }, + "preferredAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If an explicit tip anchor is not specified, an anchor is chosen automatically such that the tip fits within the plot’s frame; if the preferred anchor fits, it is chosen." + }, + "textAnchor": { + "anyOf": [ + { + "const": "start", + "type": "string" + }, + { + "const": "middle", + "type": "string" + }, + { + "const": "end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [text anchor][1] controls how text is aligned (typically horizontally) relative to its anchor point; it is one of *start*, *end*, or *middle*. If the frame anchor is *left*, *top-left*, or *bottom-left*, the default text anchor is *start*; if the frame anchor is *right*, *top-right*, or\n*bottom-right*, the default is *end*; otherwise it is *middle*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/text-anchor" + }, + "textOverflow": { + "anyOf": [ + { + "type": "null" + }, + { + "const": "clip", + "type": "string" + }, + { + "const": "ellipsis", + "type": "string" + }, + { + "const": "clip-start", + "type": "string" + }, + { + "const": "clip-end", + "type": "string" + }, + { + "const": "ellipsis-start", + "type": "string" + }, + { + "const": "ellipsis-middle", + "type": "string" + }, + { + "const": "ellipsis-end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How truncate (or wrap) lines of text longer than the given **lineWidth**; one of:\n\n- null (default) - preserve overflowing characters (and wrap if needed)\n- *clip* or *clip-end* - remove characters from the end\n- *clip-start* - remove characters from the start\n- *ellipsis* or *ellipsis-end* - replace characters from the end with an ellipsis (…)\n- *ellipsis-start* - replace characters from the start with an ellipsis (…)\n- *ellipsis-middle* - replace characters from the middle with an ellipsis (…)\n\nIf no **title** was specified, if text requires truncation, a title containing the non-truncated text will be implicitly added." + }, + "textPadding": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The padding around the text in pixels; defaults to 8." + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + } + }, + "type": "object" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to generate a tooltip for this mark, and any tip options." + }, + "title": { + "$ref": "#/definitions/ChannelValue", + "description": "The title; a channel specifying accessible, short textual descriptions as strings (possibly with newlines). If the tip option is specified, the title will be displayed with an interactive tooltip instead of using the SVG [title element][1].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/title" + }, + "x": { + "$ref": "#/definitions/ChannelValueIntervalSpec", + "description": "Shorthand for specifying both the primary and secondary horizontal position of the tick as the bounds of the containing interval; can only be used in conjunction with the **interval** option." + }, + "x1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The primary (starting, often left) horizontal position of the tick; a channel bound to the *x* scale.\n\nIf *x* represents ordinal values, use a tickY mark instead." + }, + "x2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The secondary (ending, often right) horizontal position of the tick; a channel bound to the *x* scale.\n\nIf *x* represents ordinal values, use a tickY mark instead." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position of the tick; an optional channel bound to the *y* scale. If not specified, the rule will be vertically centered in the plot’s frame." + } + }, + "required": [ + "mark" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "$schema": { + "description": "A [JSON schema](http://json-schema.org/) URL for this specification, such as https://uwdata.github.io/mosaic/schema/latest.json. This property enables validation and autocomplete in editors with JSON schema support.", + "format": "uri", + "type": "string" + }, + "anchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "right", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "const": "left", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The side of the frame on which to place the axis: *top* or *bottom* for horizontal axes (axisX and axisFx) and their associated vertical grids (gridX and gridFx), or *left* or *right* for vertical axes (axisY and axisFY) and their associated horizontal grids (gridY and gridFy).\n\nThe default **anchor** depends on the associated scale:\n\n- *x* - *bottom*\n- *y* - *left*\n- *fx* - *top* if there is a *bottom* *x* axis, and otherwise *bottom*\n- *fy* - *right* if there is a *left* *y* axis, and otherwise *right*\n\nFor grids, the **anchor** also affects the extent of grid lines when the opposite dimension is specified (**x** for gridY and **y** for gridX)." + }, + "ariaDescription": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-description][1]; a constant textual description.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-description" + }, + "ariaHidden": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-hidden][1] state; a constant indicating whether the element is exposed to an accessibility API.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-hidden" + }, + "ariaLabel": { + "$ref": "#/definitions/ChannelValue", + "description": "The [aria-label][1]; a channel specifying short textual labels representing the value in the accessibility tree.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-label" + }, + "clip": { + "anyOf": [ + { + "const": "frame", + "type": "string" + }, + { + "const": "sphere", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to clip the mark; one of:\n\n- *frame* or true - clip to the plot’s frame (inner area)\n- *sphere* - clip to the projected sphere (*e.g.*, front hemisphere)\n- null or false - do not clip\n\nThe *sphere* clip option requires a geographic projection." + }, + "color": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A shorthand for setting both **fill** and **stroke**; affects the stroke of tick vectors and grid rules, and the fill of tick texts and axis label texts; defaults to *currentColor*." + }, + "config": { + "$ref": "#/definitions/Config", + "description": "Configuration options." + }, + "data": { + "$ref": "#/definitions/Data", + "description": "Dataset definitions." + }, + "dx": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The horizontal offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "dy": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The vertical offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "facet": { + "anyOf": [ + { + "const": "auto", + "type": "string" + }, + { + "const": "include", + "type": "string" + }, + { + "const": "exclude", + "type": "string" + }, + { + "const": "super", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to enable or disable faceting; one of:\n\n- *auto* (default) - automatically determine if this mark should be faceted\n- *include* (or true) - draw the subset of the mark’s data in the current facet\n- *exclude* - draw the subset of the mark’s data *not* in the current facet\n- *super* - draw this mark in a single frame that covers all facets\n- null (or false) - repeat this mark’s data across all facets (*i.e.*, no faceting)\n\nWhen a mark uses *super* faceting, it is not allowed to use position scales (*x*, *y*, *fx*, or *fy*); *super* faceting is intended for decorations, such as labels and legends.\n\nWhen top-level faceting is used, the default *auto* setting is equivalent to *include* when the mark data is strictly equal to the top-level facet data; otherwise it is equivalent to null. When the *include* or *exclude* facet mode is chosen, the mark data must be parallel to the top-level facet data: the data must have the same length and order. If the data are not parallel, then the wrong data may be shown in each facet. The default\n*auto* therefore requires strict equality (`===`) for safety, and using the facet data as mark data is recommended when using the *exclude* facet mode. (To construct parallel data safely, consider using [*array*.map][1] on the facet data.)\n\nWhen mark-level faceting is used, the default *auto* setting is equivalent to *include*: the mark will be faceted if either the **fx** or **fy** channel option (or both) is specified. The null or false option will disable faceting, while *exclude* draws the subset of the mark’s data *not* in the current facet.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map" + }, + "facetAnchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "right", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "const": "left", + "type": "string" + }, + { + "const": "top-left", + "type": "string" + }, + { + "const": "top-right", + "type": "string" + }, + { + "const": "bottom-left", + "type": "string" + }, + { + "const": "bottom-right", + "type": "string" + }, + { + "const": "top-empty", + "type": "string" + }, + { + "const": "right-empty", + "type": "string" + }, + { + "const": "bottom-empty", + "type": "string" + }, + { + "const": "left-empty", + "type": "string" + }, + { + "const": "empty", + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to place the mark with respect to facets; one of:\n\n- null (default for most marks) - display the mark in each non-empty facet\n- *top*, *right*, *bottom*, or *left* - display the mark only in facets on the given side\n- *top-empty*, *right-empty*, *bottom-empty*, or *left-empty* (default for axis marks) - display the mark only in facets that have empty space on the given side: either the margin, or an empty facet\n- *empty* - display the mark in empty facets only" + }, + "fill": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill" + }, + "fillOpacity": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill-opacity][1]; a constant number between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill-opacity" + }, + "filter": { + "$ref": "#/definitions/ChannelValue", + "description": "Applies a transform to filter the mark’s index according to the given channel values; only truthy values are retained.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "fx": { + "$ref": "#/definitions/ChannelValue", + "description": "The horizontal facet position channel, for mark-level faceting, bound to the *fx* scale." + }, + "fy": { + "$ref": "#/definitions/ChannelValue", + "description": "The vertical facet position channel, for mark-level faceting, bound to the\n*fy* scale." + }, + "href": { + "$ref": "#/definitions/ChannelValue", + "description": "The [href][1]; a channel specifying URLs for clickable links. May be used in conjunction with the **target** option to open links in another window.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/href" + }, + "imageFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A CSS [filter][1]; a constant string used to adjust the rendering of images, such as *blur(5px)*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/filter" + }, + "inset": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four insets: **insetTop**,\n**insetRight**, **insetBottom**, and **insetLeft**. All insets typically default to zero, though not always (say when using bin transform). A positive inset reduces effective area, while a negative inset increases it." + }, + "insetBottom": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Insets the bottom edge by the specified number of pixels. A positive value insets towards the top edge (reducing effective area), while a negative value insets away from the top edge (increasing it)." + }, + "insetTop": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Insets the top edge by the specified number of pixels. A positive value insets towards the bottom edge (reducing effective area), while a negative value insets away from the bottom edge (increasing it)." + }, + "interval": { + "anyOf": [ + { + "$ref": "#/definitions/Interval" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Enforces uniformity for data at regular intervals, such as integer values or daily samples. The interval may be one of:\n\n- a named time interval such as *day* (for date intervals)\n- a number (for number intervals), defining intervals at integer multiples of *n*\n\nThis option sets the internal transform to the given interval’s\n*interval*.floor function. In addition, the default **domain** will align with interval boundaries." + }, + "margin": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four mark margins: **marginTop**,\n**marginRight**, **marginBottom**, and **marginLeft**; typically defaults to 0, except for axis marks." + }, + "marginBottom": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s bottom margin; the minimum distance in pixels between the bottom edges of the inner and outer plot area." + }, + "marginLeft": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s left margin; the minimum distance in pixels between the left edges of the inner and outer plot area." + }, + "marginRight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s right margin; the minimum distance in pixels between the right edges of the mark’s inner and outer plot area." + }, + "marginTop": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s top margin; the minimum distance in pixels between the top edges of the inner and outer plot area." + }, + "mark": { + "const": "gridFx", + "description": "A horizontally-positioned ruleX mark (a vertical line, |) that renders a grid for the *fx* scale. The data defaults to the *fx* scale’s domain; if desired, use the **ticks** option.", + "type": "string" + }, + "marker": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for markerStart, markerMid, and markerEnd; one of:\n\n- a marker name such as *arrow* or *circle*\n- *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*" + }, + "markerEnd": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The marker for the ending point of a line segment; one of:\n\n- a marker name such as *arrow* or *circle*\n* *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*" + }, + "markerMid": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The marker for any middle (interior) points of a line segment. If the line segment only has a start and end point, this option has no effect. One of:\n\n- a marker name such as *arrow* or *circle*\n* *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*\n* a function - a custom marker function; see below" + }, + "markerStart": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The marker for the starting point of a line segment; one of:\n\n- a marker name such as *arrow* or *circle*\n* *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*" + }, + "meta": { + "$ref": "#/definitions/Meta", + "description": "Specification metadata." + }, + "mixBlendMode": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [mix-blend-mode][1]; a constant string specifying how to blend content such as *multiply*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode" + }, + "opacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "A shorthand for setting both **fillOpacity** and **strokeOpacity**; affects the stroke opacity of tick vectors and grid rules, and the fill opacity of tick texts and axis label texts; defaults to 1 for axes and 0.1 for grids." + }, + "paintOrder": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [paint-order][1]; a constant string specifying the order in which the\n**fill**, **stroke**, and any markers are drawn; defaults to *normal*, which draws the fill, then stroke, then markers; defaults to *stroke* for the text mark to create a “halo” around text to improve legibility.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/paint-order" + }, + "params": { + "$ref": "#/definitions/Params", + "description": "Param and Selection definitions." + }, + "plotDefaults": { + "$ref": "#/definitions/PlotAttributes", + "description": "A default set of attributes to apply to all plot components." + }, + "pointerEvents": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [pointer-events][1] property; a constant string such as *none*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/pointer-events" + }, + "reverse": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Applies a transform to reverse the order of the mark’s index, say for reverse input order." + }, + "select": { + "$ref": "#/definitions/SelectFilter", + "description": "Applies a filter transform after data is loaded to highlight selected values only. For example, `first` and `last` select the first or last values of series only (using the *z* channel to separate series). Meanwhile, `nearestX` and `nearestY` select the point nearest to the pointer along the *x* or *y* channel dimension. Unlike Mosaic selections, a mark level *select* is internal to the mark only, and does not populate a param or selection value to be shared across clients.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "shapeRendering": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [shape-rendering][1]; a constant string such as *crispEdges*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/shape-rendering" + }, + "sort": { + "anyOf": [ + { + "$ref": "#/definitions/SortOrder" + }, + { + "$ref": "#/definitions/ChannelDomainSort" + } + ], + "description": "Either applies a transform to sort the mark’s index by the specified channel values, or imputes ordinal scale domains from this mark’s channels.\n\nWhen imputing ordinal scale domains from channel values, the **sort** option is an object whose keys are ordinal scale names such as *x* or *fx*, and whose values are channel names such as *y*, *y1*, or *y2*. For example, to impute the *y* scale’s domain from the associated *x* channel values in ascending order:\n\n```js sort: {y: \"x\"} ```\n\nFor different sort options for different scales, replace the channel name with a *value* object and per-scale options:\n\n```js sort: {y: {value: \"-x\"}} ```\n\nWhen sorting the mark’s index, the **sort** option is instead one of:\n\n- a channel value definition for sorting given values in ascending order\n- a {value, order} object for sorting given values\n- a {channel, order} object for sorting the named channel’s values" + }, + "stroke": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke" + }, + "strokeDasharray": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dasharray][1]; a constant number indicating the length in pixels of alternating dashes and gaps, or a constant string of numbers separated by spaces or commas (_e.g._, *10 2* for dashes of 10 pixels separated by gaps of 2 pixels), or *none* (the default) for no dashing\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dasharray" + }, + "strokeDashoffset": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dashoffset][1]; a constant indicating the offset in pixels of the first dash along the stroke; defaults to zero.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dashoffset" + }, + "strokeLinecap": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linecap][1]; a constant specifying how to cap stroked paths, such as *butt*, *round*, or *square*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linecap" + }, + "strokeLinejoin": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linejoin][1]; a constant specifying how to join stroked paths, such as *bevel*, *miter*, *miter-clip*, or *round*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linejoin" + }, + "strokeMiterlimit": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-miterlimit][1]; a constant number specifying how to limit the length of *miter* joins on stroked paths.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-miterlimit" + }, + "strokeOpacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-opacity" + }, + "strokeWidth": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-width][1]; a constant number in pixels, or a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-width" + }, + "target": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [target][1]; a constant string specifying the target window (_e.g._,\n*_blank*) for clickable links; used in conjunction with the **href** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/target" + }, + "tickSpacing": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The desired approximate spacing between adjacent axis ticks, affecting the default **ticks**; defaults to 80 pixels for *x* and *fx*, and 35 pixels for *y* and *fy*." + }, + "ticks": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/Interval" + }, + { + "items": {}, + "type": "array" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The desired approximate number of axis ticks, or an explicit array of tick values, or an interval such as *day* or *month*." + }, + "tip": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/TipPointer" + }, + { + "properties": { + "anchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The tip anchor specifies how to orient the tip box relative to its anchor position; it refers to the part of the tip box that is attached to the anchor point. For example, the *top-left* anchor places the top-left corner of tip box near the anchor position, hence placing the tip box below and to the right of the anchor position." + }, + "fontFamily": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font-family][1]; a constant; defaults to the plot’s font family, which is typically [*system-ui*][2].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-family [2]: https://drafts.csswg.org/css-fonts-4/#valdef-font-family-system-ui" + }, + "fontSize": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font size][1] in pixels; either a constant or a channel; defaults to the plot’s font size, which is typically 10. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-size" + }, + "fontStyle": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font style][1]; a constant; defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-style" + }, + "fontVariant": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font variant][1]; a constant; if the **text** channel contains numbers or dates, defaults to *tabular-nums* to facilitate comparing numbers; otherwise defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant" + }, + "fontWeight": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font weight][1]; a constant; defaults to the plot’s font weight, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight" + }, + "format": { + "additionalProperties": false, + "description": "How channel values are formatted for display. If a format is a string, it is interpreted as a (UTC) time format for temporal channels, and otherwise a number format.", + "properties": { + "ariaLabel": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fill": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fillOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fontSize": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fx": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fy": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "geometry": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "height": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "href": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "length": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "opacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "path": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "r": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "rotate": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "src": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "stroke": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeWidth": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "symbol": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "text": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "title": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "weight": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "width": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "z": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + } + }, + "type": "object" + }, + "frameAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The frame anchor specifies defaults for **x** and **y** based on the plot’s frame; it may be one of the four sides (*top*, *right*, *bottom*, *left*), one of the four corners (*top-left*, *top-right*, *bottom-right*,\n*bottom-left*), or the *middle* of the frame. For example, for tips distributed horizontally at the top of the frame:\n\n```js Plot.tip(data, {x: \"date\", frameAnchor: \"top\"}) ```" + }, + "lineHeight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line height in ems; defaults to 1. The line height affects the (typically vertical) separation between adjacent baselines of text, as well as the separation between the text and its anchor point." + }, + "lineWidth": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line width in ems (e.g., 10 for about 20 characters); defaults to infinity, disabling wrapping and clipping.\n\nIf **textOverflow** is null, lines will be wrapped at the specified length. If a line is split at a soft hyphen (\\xad), a hyphen (-) will be displayed at the end of the line. If **textOverflow** is not null, lines will be clipped according to the given strategy." + }, + "monospace": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, changes the default **fontFamily** to *monospace*, and uses simplified monospaced text metrics calculations." + }, + "pathFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The image filter for the tip’s box; defaults to a drop shadow." + }, + "pointer": { + "$ref": "#/definitions/TipPointer" + }, + "pointerSize": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The size of the tip’s pointer in pixels; defaults to 12." + }, + "preferredAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If an explicit tip anchor is not specified, an anchor is chosen automatically such that the tip fits within the plot’s frame; if the preferred anchor fits, it is chosen." + }, + "textAnchor": { + "anyOf": [ + { + "const": "start", + "type": "string" + }, + { + "const": "middle", + "type": "string" + }, + { + "const": "end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [text anchor][1] controls how text is aligned (typically horizontally) relative to its anchor point; it is one of *start*, *end*, or *middle*. If the frame anchor is *left*, *top-left*, or *bottom-left*, the default text anchor is *start*; if the frame anchor is *right*, *top-right*, or\n*bottom-right*, the default is *end*; otherwise it is *middle*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/text-anchor" + }, + "textOverflow": { + "anyOf": [ + { + "type": "null" + }, + { + "const": "clip", + "type": "string" + }, + { + "const": "ellipsis", + "type": "string" + }, + { + "const": "clip-start", + "type": "string" + }, + { + "const": "clip-end", + "type": "string" + }, + { + "const": "ellipsis-start", + "type": "string" + }, + { + "const": "ellipsis-middle", + "type": "string" + }, + { + "const": "ellipsis-end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How truncate (or wrap) lines of text longer than the given **lineWidth**; one of:\n\n- null (default) - preserve overflowing characters (and wrap if needed)\n- *clip* or *clip-end* - remove characters from the end\n- *clip-start* - remove characters from the start\n- *ellipsis* or *ellipsis-end* - replace characters from the end with an ellipsis (…)\n- *ellipsis-start* - replace characters from the start with an ellipsis (…)\n- *ellipsis-middle* - replace characters from the middle with an ellipsis (…)\n\nIf no **title** was specified, if text requires truncation, a title containing the non-truncated text will be implicitly added." + }, + "textPadding": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The padding around the text in pixels; defaults to 8." + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + } + }, + "type": "object" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to generate a tooltip for this mark, and any tip options." + }, + "title": { + "$ref": "#/definitions/ChannelValue", + "description": "The title; a channel specifying accessible, short textual descriptions as strings (possibly with newlines). If the tip option is specified, the title will be displayed with an interactive tooltip instead of using the SVG [title element][1].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/title" + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position of the tick; an optional channel bound to the *x* scale. If not specified, the rule will be horizontally centered in the plot’s frame." + }, + "y": { + "$ref": "#/definitions/ChannelValueIntervalSpec", + "description": "Shorthand for specifying both the primary and secondary vertical position of the tick as the bounds of the containing interval; can only be used in conjunction with the **interval** option." + }, + "y1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The primary (starting, often bottom) vertical position of the tick; a channel bound to the *y* scale.\n\nIf *y* represents ordinal values, use a tickX mark instead." + }, + "y2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The secondary (ending, often top) vertical position of the tick; a channel bound to the *y* scale.\n\nIf *y* represents ordinal values, use a tickX mark instead." + } + }, + "required": [ + "mark" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "$schema": { + "description": "A [JSON schema](http://json-schema.org/) URL for this specification, such as https://uwdata.github.io/mosaic/schema/latest.json. This property enables validation and autocomplete in editors with JSON schema support.", + "format": "uri", + "type": "string" + }, + "anchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "right", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "const": "left", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The side of the frame on which to place the axis: *top* or *bottom* for horizontal axes (axisX and axisFx) and their associated vertical grids (gridX and gridFx), or *left* or *right* for vertical axes (axisY and axisFY) and their associated horizontal grids (gridY and gridFy).\n\nThe default **anchor** depends on the associated scale:\n\n- *x* - *bottom*\n- *y* - *left*\n- *fx* - *top* if there is a *bottom* *x* axis, and otherwise *bottom*\n- *fy* - *right* if there is a *left* *y* axis, and otherwise *right*\n\nFor grids, the **anchor** also affects the extent of grid lines when the opposite dimension is specified (**x** for gridY and **y** for gridX)." + }, + "ariaDescription": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-description][1]; a constant textual description.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-description" + }, + "ariaHidden": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-hidden][1] state; a constant indicating whether the element is exposed to an accessibility API.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-hidden" + }, + "ariaLabel": { + "$ref": "#/definitions/ChannelValue", + "description": "The [aria-label][1]; a channel specifying short textual labels representing the value in the accessibility tree.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-label" + }, + "clip": { + "anyOf": [ + { + "const": "frame", + "type": "string" + }, + { + "const": "sphere", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to clip the mark; one of:\n\n- *frame* or true - clip to the plot’s frame (inner area)\n- *sphere* - clip to the projected sphere (*e.g.*, front hemisphere)\n- null or false - do not clip\n\nThe *sphere* clip option requires a geographic projection." + }, + "color": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A shorthand for setting both **fill** and **stroke**; affects the stroke of tick vectors and grid rules, and the fill of tick texts and axis label texts; defaults to *currentColor*." + }, + "config": { + "$ref": "#/definitions/Config", + "description": "Configuration options." + }, + "data": { + "$ref": "#/definitions/Data", + "description": "Dataset definitions." + }, + "dx": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The horizontal offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "dy": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The vertical offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "facet": { + "anyOf": [ + { + "const": "auto", + "type": "string" + }, + { + "const": "include", + "type": "string" + }, + { + "const": "exclude", + "type": "string" + }, + { + "const": "super", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to enable or disable faceting; one of:\n\n- *auto* (default) - automatically determine if this mark should be faceted\n- *include* (or true) - draw the subset of the mark’s data in the current facet\n- *exclude* - draw the subset of the mark’s data *not* in the current facet\n- *super* - draw this mark in a single frame that covers all facets\n- null (or false) - repeat this mark’s data across all facets (*i.e.*, no faceting)\n\nWhen a mark uses *super* faceting, it is not allowed to use position scales (*x*, *y*, *fx*, or *fy*); *super* faceting is intended for decorations, such as labels and legends.\n\nWhen top-level faceting is used, the default *auto* setting is equivalent to *include* when the mark data is strictly equal to the top-level facet data; otherwise it is equivalent to null. When the *include* or *exclude* facet mode is chosen, the mark data must be parallel to the top-level facet data: the data must have the same length and order. If the data are not parallel, then the wrong data may be shown in each facet. The default\n*auto* therefore requires strict equality (`===`) for safety, and using the facet data as mark data is recommended when using the *exclude* facet mode. (To construct parallel data safely, consider using [*array*.map][1] on the facet data.)\n\nWhen mark-level faceting is used, the default *auto* setting is equivalent to *include*: the mark will be faceted if either the **fx** or **fy** channel option (or both) is specified. The null or false option will disable faceting, while *exclude* draws the subset of the mark’s data *not* in the current facet.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map" + }, + "facetAnchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "right", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "const": "left", + "type": "string" + }, + { + "const": "top-left", + "type": "string" + }, + { + "const": "top-right", + "type": "string" + }, + { + "const": "bottom-left", + "type": "string" + }, + { + "const": "bottom-right", + "type": "string" + }, + { + "const": "top-empty", + "type": "string" + }, + { + "const": "right-empty", + "type": "string" + }, + { + "const": "bottom-empty", + "type": "string" + }, + { + "const": "left-empty", + "type": "string" + }, + { + "const": "empty", + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to place the mark with respect to facets; one of:\n\n- null (default for most marks) - display the mark in each non-empty facet\n- *top*, *right*, *bottom*, or *left* - display the mark only in facets on the given side\n- *top-empty*, *right-empty*, *bottom-empty*, or *left-empty* (default for axis marks) - display the mark only in facets that have empty space on the given side: either the margin, or an empty facet\n- *empty* - display the mark in empty facets only" + }, + "fill": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill" + }, + "fillOpacity": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill-opacity][1]; a constant number between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill-opacity" + }, + "filter": { + "$ref": "#/definitions/ChannelValue", + "description": "Applies a transform to filter the mark’s index according to the given channel values; only truthy values are retained.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "fx": { + "$ref": "#/definitions/ChannelValue", + "description": "The horizontal facet position channel, for mark-level faceting, bound to the *fx* scale." + }, + "fy": { + "$ref": "#/definitions/ChannelValue", + "description": "The vertical facet position channel, for mark-level faceting, bound to the\n*fy* scale." + }, + "href": { + "$ref": "#/definitions/ChannelValue", + "description": "The [href][1]; a channel specifying URLs for clickable links. May be used in conjunction with the **target** option to open links in another window.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/href" + }, + "imageFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A CSS [filter][1]; a constant string used to adjust the rendering of images, such as *blur(5px)*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/filter" + }, + "inset": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four insets: **insetTop**,\n**insetRight**, **insetBottom**, and **insetLeft**. All insets typically default to zero, though not always (say when using bin transform). A positive inset reduces effective area, while a negative inset increases it." + }, + "insetLeft": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Insets the left edge by the specified number of pixels. A positive value insets towards the right edge (reducing effective area), while a negative value insets away from the right edge (increasing it)." + }, + "insetRight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Insets the right edge by the specified number of pixels. A positive value insets towards the left edge (reducing effective area), while a negative value insets away from the left edge (increasing it)." + }, + "interval": { + "anyOf": [ + { + "$ref": "#/definitions/Interval" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Enforces uniformity for data at regular intervals, such as integer values or daily samples. The interval may be one of:\n\n- a named time interval such as *day* (for date intervals)\n- a number (for number intervals), defining intervals at integer multiples of *n*\n\nThis option sets the internal transform to the given interval’s\n*interval*.floor function. In addition, the default **domain** will align with interval boundaries." + }, + "margin": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four mark margins: **marginTop**,\n**marginRight**, **marginBottom**, and **marginLeft**; typically defaults to 0, except for axis marks." + }, + "marginBottom": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s bottom margin; the minimum distance in pixels between the bottom edges of the inner and outer plot area." + }, + "marginLeft": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s left margin; the minimum distance in pixels between the left edges of the inner and outer plot area." + }, + "marginRight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s right margin; the minimum distance in pixels between the right edges of the mark’s inner and outer plot area." + }, + "marginTop": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s top margin; the minimum distance in pixels between the top edges of the inner and outer plot area." + }, + "mark": { + "const": "gridFy", + "description": "A vertically-positioned ruleY mark (a horizontal line, —) that renders a grid for the *fy* scale. The data defaults to the *fy* scale’s domain; if desired, use the **ticks** option.", + "type": "string" + }, + "marker": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for markerStart, markerMid, and markerEnd; one of:\n\n- a marker name such as *arrow* or *circle*\n- *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*" + }, + "markerEnd": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The marker for the ending point of a line segment; one of:\n\n- a marker name such as *arrow* or *circle*\n* *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*" + }, + "markerMid": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The marker for any middle (interior) points of a line segment. If the line segment only has a start and end point, this option has no effect. One of:\n\n- a marker name such as *arrow* or *circle*\n* *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*\n* a function - a custom marker function; see below" + }, + "markerStart": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The marker for the starting point of a line segment; one of:\n\n- a marker name such as *arrow* or *circle*\n* *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*" + }, + "meta": { + "$ref": "#/definitions/Meta", + "description": "Specification metadata." + }, + "mixBlendMode": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [mix-blend-mode][1]; a constant string specifying how to blend content such as *multiply*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode" + }, + "opacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "A shorthand for setting both **fillOpacity** and **strokeOpacity**; affects the stroke opacity of tick vectors and grid rules, and the fill opacity of tick texts and axis label texts; defaults to 1 for axes and 0.1 for grids." + }, + "paintOrder": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [paint-order][1]; a constant string specifying the order in which the\n**fill**, **stroke**, and any markers are drawn; defaults to *normal*, which draws the fill, then stroke, then markers; defaults to *stroke* for the text mark to create a “halo” around text to improve legibility.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/paint-order" + }, + "params": { + "$ref": "#/definitions/Params", + "description": "Param and Selection definitions." + }, + "plotDefaults": { + "$ref": "#/definitions/PlotAttributes", + "description": "A default set of attributes to apply to all plot components." + }, + "pointerEvents": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [pointer-events][1] property; a constant string such as *none*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/pointer-events" + }, + "reverse": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Applies a transform to reverse the order of the mark’s index, say for reverse input order." + }, + "select": { + "$ref": "#/definitions/SelectFilter", + "description": "Applies a filter transform after data is loaded to highlight selected values only. For example, `first` and `last` select the first or last values of series only (using the *z* channel to separate series). Meanwhile, `nearestX` and `nearestY` select the point nearest to the pointer along the *x* or *y* channel dimension. Unlike Mosaic selections, a mark level *select* is internal to the mark only, and does not populate a param or selection value to be shared across clients.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "shapeRendering": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [shape-rendering][1]; a constant string such as *crispEdges*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/shape-rendering" + }, + "sort": { + "anyOf": [ + { + "$ref": "#/definitions/SortOrder" + }, + { + "$ref": "#/definitions/ChannelDomainSort" + } + ], + "description": "Either applies a transform to sort the mark’s index by the specified channel values, or imputes ordinal scale domains from this mark’s channels.\n\nWhen imputing ordinal scale domains from channel values, the **sort** option is an object whose keys are ordinal scale names such as *x* or *fx*, and whose values are channel names such as *y*, *y1*, or *y2*. For example, to impute the *y* scale’s domain from the associated *x* channel values in ascending order:\n\n```js sort: {y: \"x\"} ```\n\nFor different sort options for different scales, replace the channel name with a *value* object and per-scale options:\n\n```js sort: {y: {value: \"-x\"}} ```\n\nWhen sorting the mark’s index, the **sort** option is instead one of:\n\n- a channel value definition for sorting given values in ascending order\n- a {value, order} object for sorting given values\n- a {channel, order} object for sorting the named channel’s values" + }, + "stroke": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke" + }, + "strokeDasharray": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dasharray][1]; a constant number indicating the length in pixels of alternating dashes and gaps, or a constant string of numbers separated by spaces or commas (_e.g._, *10 2* for dashes of 10 pixels separated by gaps of 2 pixels), or *none* (the default) for no dashing\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dasharray" + }, + "strokeDashoffset": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dashoffset][1]; a constant indicating the offset in pixels of the first dash along the stroke; defaults to zero.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dashoffset" + }, + "strokeLinecap": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linecap][1]; a constant specifying how to cap stroked paths, such as *butt*, *round*, or *square*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linecap" + }, + "strokeLinejoin": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linejoin][1]; a constant specifying how to join stroked paths, such as *bevel*, *miter*, *miter-clip*, or *round*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linejoin" + }, + "strokeMiterlimit": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-miterlimit][1]; a constant number specifying how to limit the length of *miter* joins on stroked paths.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-miterlimit" + }, + "strokeOpacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-opacity" + }, + "strokeWidth": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-width][1]; a constant number in pixels, or a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-width" + }, + "target": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [target][1]; a constant string specifying the target window (_e.g._,\n*_blank*) for clickable links; used in conjunction with the **href** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/target" + }, + "tickSpacing": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The desired approximate spacing between adjacent axis ticks, affecting the default **ticks**; defaults to 80 pixels for *x* and *fx*, and 35 pixels for *y* and *fy*." + }, + "ticks": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/Interval" + }, + { + "items": {}, + "type": "array" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The desired approximate number of axis ticks, or an explicit array of tick values, or an interval such as *day* or *month*." + }, + "tip": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/TipPointer" + }, + { + "properties": { + "anchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The tip anchor specifies how to orient the tip box relative to its anchor position; it refers to the part of the tip box that is attached to the anchor point. For example, the *top-left* anchor places the top-left corner of tip box near the anchor position, hence placing the tip box below and to the right of the anchor position." + }, + "fontFamily": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font-family][1]; a constant; defaults to the plot’s font family, which is typically [*system-ui*][2].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-family [2]: https://drafts.csswg.org/css-fonts-4/#valdef-font-family-system-ui" + }, + "fontSize": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font size][1] in pixels; either a constant or a channel; defaults to the plot’s font size, which is typically 10. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-size" + }, + "fontStyle": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font style][1]; a constant; defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-style" + }, + "fontVariant": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font variant][1]; a constant; if the **text** channel contains numbers or dates, defaults to *tabular-nums* to facilitate comparing numbers; otherwise defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant" + }, + "fontWeight": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font weight][1]; a constant; defaults to the plot’s font weight, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight" + }, + "format": { + "additionalProperties": false, + "description": "How channel values are formatted for display. If a format is a string, it is interpreted as a (UTC) time format for temporal channels, and otherwise a number format.", + "properties": { + "ariaLabel": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fill": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fillOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fontSize": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fx": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fy": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "geometry": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "height": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "href": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "length": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "opacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "path": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "r": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "rotate": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "src": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "stroke": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeWidth": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "symbol": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "text": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "title": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "weight": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "width": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "z": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + } + }, + "type": "object" + }, + "frameAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The frame anchor specifies defaults for **x** and **y** based on the plot’s frame; it may be one of the four sides (*top*, *right*, *bottom*, *left*), one of the four corners (*top-left*, *top-right*, *bottom-right*,\n*bottom-left*), or the *middle* of the frame. For example, for tips distributed horizontally at the top of the frame:\n\n```js Plot.tip(data, {x: \"date\", frameAnchor: \"top\"}) ```" + }, + "lineHeight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line height in ems; defaults to 1. The line height affects the (typically vertical) separation between adjacent baselines of text, as well as the separation between the text and its anchor point." + }, + "lineWidth": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line width in ems (e.g., 10 for about 20 characters); defaults to infinity, disabling wrapping and clipping.\n\nIf **textOverflow** is null, lines will be wrapped at the specified length. If a line is split at a soft hyphen (\\xad), a hyphen (-) will be displayed at the end of the line. If **textOverflow** is not null, lines will be clipped according to the given strategy." + }, + "monospace": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, changes the default **fontFamily** to *monospace*, and uses simplified monospaced text metrics calculations." + }, + "pathFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The image filter for the tip’s box; defaults to a drop shadow." + }, + "pointer": { + "$ref": "#/definitions/TipPointer" + }, + "pointerSize": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The size of the tip’s pointer in pixels; defaults to 12." + }, + "preferredAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If an explicit tip anchor is not specified, an anchor is chosen automatically such that the tip fits within the plot’s frame; if the preferred anchor fits, it is chosen." + }, + "textAnchor": { + "anyOf": [ + { + "const": "start", + "type": "string" + }, + { + "const": "middle", + "type": "string" + }, + { + "const": "end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [text anchor][1] controls how text is aligned (typically horizontally) relative to its anchor point; it is one of *start*, *end*, or *middle*. If the frame anchor is *left*, *top-left*, or *bottom-left*, the default text anchor is *start*; if the frame anchor is *right*, *top-right*, or\n*bottom-right*, the default is *end*; otherwise it is *middle*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/text-anchor" + }, + "textOverflow": { + "anyOf": [ + { + "type": "null" + }, + { + "const": "clip", + "type": "string" + }, + { + "const": "ellipsis", + "type": "string" + }, + { + "const": "clip-start", + "type": "string" + }, + { + "const": "clip-end", + "type": "string" + }, + { + "const": "ellipsis-start", + "type": "string" + }, + { + "const": "ellipsis-middle", + "type": "string" + }, + { + "const": "ellipsis-end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How truncate (or wrap) lines of text longer than the given **lineWidth**; one of:\n\n- null (default) - preserve overflowing characters (and wrap if needed)\n- *clip* or *clip-end* - remove characters from the end\n- *clip-start* - remove characters from the start\n- *ellipsis* or *ellipsis-end* - replace characters from the end with an ellipsis (…)\n- *ellipsis-start* - replace characters from the start with an ellipsis (…)\n- *ellipsis-middle* - replace characters from the middle with an ellipsis (…)\n\nIf no **title** was specified, if text requires truncation, a title containing the non-truncated text will be implicitly added." + }, + "textPadding": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The padding around the text in pixels; defaults to 8." + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + } + }, + "type": "object" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to generate a tooltip for this mark, and any tip options." + }, + "title": { + "$ref": "#/definitions/ChannelValue", + "description": "The title; a channel specifying accessible, short textual descriptions as strings (possibly with newlines). If the tip option is specified, the title will be displayed with an interactive tooltip instead of using the SVG [title element][1].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/title" + }, + "x": { + "$ref": "#/definitions/ChannelValueIntervalSpec", + "description": "Shorthand for specifying both the primary and secondary horizontal position of the tick as the bounds of the containing interval; can only be used in conjunction with the **interval** option." + }, + "x1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The primary (starting, often left) horizontal position of the tick; a channel bound to the *x* scale.\n\nIf *x* represents ordinal values, use a tickY mark instead." + }, + "x2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The secondary (ending, often right) horizontal position of the tick; a channel bound to the *x* scale.\n\nIf *x* represents ordinal values, use a tickY mark instead." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position of the tick; an optional channel bound to the *y* scale. If not specified, the rule will be vertically centered in the plot’s frame." + } + }, + "required": [ + "mark" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "$schema": { + "description": "A [JSON schema](http://json-schema.org/) URL for this specification, such as https://uwdata.github.io/mosaic/schema/latest.json. This property enables validation and autocomplete in editors with JSON schema support.", + "format": "uri", + "type": "string" + }, + "ariaDescription": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-description][1]; a constant textual description.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-description" + }, + "ariaHidden": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-hidden][1] state; a constant indicating whether the element is exposed to an accessibility API.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-hidden" + }, + "ariaLabel": { + "$ref": "#/definitions/ChannelValue", + "description": "The [aria-label][1]; a channel specifying short textual labels representing the value in the accessibility tree.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-label" + }, + "clip": { + "anyOf": [ + { + "const": "frame", + "type": "string" + }, + { + "const": "sphere", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to clip the mark; one of:\n\n- *frame* or true - clip to the plot’s frame (inner area)\n- *sphere* - clip to the projected sphere (*e.g.*, front hemisphere)\n- null or false - do not clip\n\nThe *sphere* clip option requires a geographic projection." + }, + "config": { + "$ref": "#/definitions/Config", + "description": "Configuration options." + }, + "data": { + "$ref": "#/definitions/Data", + "description": "Dataset definitions." + }, + "dx": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The horizontal offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "dy": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The vertical offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "facet": { + "anyOf": [ + { + "const": "auto", + "type": "string" + }, + { + "const": "include", + "type": "string" + }, + { + "const": "exclude", + "type": "string" + }, + { + "const": "super", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to enable or disable faceting; one of:\n\n- *auto* (default) - automatically determine if this mark should be faceted\n- *include* (or true) - draw the subset of the mark’s data in the current facet\n- *exclude* - draw the subset of the mark’s data *not* in the current facet\n- *super* - draw this mark in a single frame that covers all facets\n- null (or false) - repeat this mark’s data across all facets (*i.e.*, no faceting)\n\nWhen a mark uses *super* faceting, it is not allowed to use position scales (*x*, *y*, *fx*, or *fy*); *super* faceting is intended for decorations, such as labels and legends.\n\nWhen top-level faceting is used, the default *auto* setting is equivalent to *include* when the mark data is strictly equal to the top-level facet data; otherwise it is equivalent to null. When the *include* or *exclude* facet mode is chosen, the mark data must be parallel to the top-level facet data: the data must have the same length and order. If the data are not parallel, then the wrong data may be shown in each facet. The default\n*auto* therefore requires strict equality (`===`) for safety, and using the facet data as mark data is recommended when using the *exclude* facet mode. (To construct parallel data safely, consider using [*array*.map][1] on the facet data.)\n\nWhen mark-level faceting is used, the default *auto* setting is equivalent to *include*: the mark will be faceted if either the **fx** or **fy** channel option (or both) is specified. The null or false option will disable faceting, while *exclude* draws the subset of the mark’s data *not* in the current facet.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map" + }, + "facetAnchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "right", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "const": "left", + "type": "string" + }, + { + "const": "top-left", + "type": "string" + }, + { + "const": "top-right", + "type": "string" + }, + { + "const": "bottom-left", + "type": "string" + }, + { + "const": "bottom-right", + "type": "string" + }, + { + "const": "top-empty", + "type": "string" + }, + { + "const": "right-empty", + "type": "string" + }, + { + "const": "bottom-empty", + "type": "string" + }, + { + "const": "left-empty", + "type": "string" + }, + { + "const": "empty", + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to place the mark with respect to facets; one of:\n\n- null (default for most marks) - display the mark in each non-empty facet\n- *top*, *right*, *bottom*, or *left* - display the mark only in facets on the given side\n- *top-empty*, *right-empty*, *bottom-empty*, or *left-empty* (default for axis marks) - display the mark only in facets that have empty space on the given side: either the margin, or an empty facet\n- *empty* - display the mark in empty facets only" + }, + "fill": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill" + }, + "fillOpacity": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill-opacity][1]; a constant number between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill-opacity" + }, + "filter": { + "$ref": "#/definitions/ChannelValue", + "description": "Applies a transform to filter the mark’s index according to the given channel values; only truthy values are retained.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "fx": { + "$ref": "#/definitions/ChannelValue", + "description": "The horizontal facet position channel, for mark-level faceting, bound to the *fx* scale." + }, + "fy": { + "$ref": "#/definitions/ChannelValue", + "description": "The vertical facet position channel, for mark-level faceting, bound to the\n*fy* scale." + }, + "href": { + "$ref": "#/definitions/ChannelValue", + "description": "The [href][1]; a channel specifying URLs for clickable links. May be used in conjunction with the **target** option to open links in another window.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/href" + }, + "imageFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A CSS [filter][1]; a constant string used to adjust the rendering of images, such as *blur(5px)*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/filter" + }, + "inset": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four insets: **insetTop**,\n**insetRight**, **insetBottom**, and **insetLeft**. All insets typically default to zero, though not always (say when using bin transform). A positive inset reduces effective area, while a negative inset increases it." + }, + "insetBottom": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Insets the bottom edge by the specified number of pixels. A positive value insets towards the top edge (reducing effective area), while a negative value insets away from the top edge (increasing it)." + }, + "insetLeft": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Insets the left edge by the specified number of pixels. A positive value insets towards the right edge (reducing effective area), while a negative value insets away from the right edge (increasing it)." + }, + "insetRight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Insets the right edge by the specified number of pixels. A positive value insets towards the left edge (reducing effective area), while a negative value insets away from the left edge (increasing it)." + }, + "insetTop": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Insets the top edge by the specified number of pixels. A positive value insets towards the bottom edge (reducing effective area), while a negative value insets away from the bottom edge (increasing it)." + }, + "interval": { + "anyOf": [ + { + "$ref": "#/definitions/Interval" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to convert a continuous value (**x** for barX, or **y** for barY) into an interval (**x1** and **x2** for barX, or **y1** and **y2** for barY); one of:\n\n- a named time interval such as *day* (for date intervals)\n- a number (for number intervals), defining intervals at integer multiples of *n*\n\nSetting this option disables the implicit stack transform (stackX for barX, or stackY for barY)." + }, + "margin": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four mark margins: **marginTop**,\n**marginRight**, **marginBottom**, and **marginLeft**; typically defaults to 0, except for axis marks." + }, + "marginBottom": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s bottom margin; the minimum distance in pixels between the bottom edges of the inner and outer plot area." + }, + "marginLeft": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s left margin; the minimum distance in pixels between the left edges of the inner and outer plot area." + }, + "marginRight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s right margin; the minimum distance in pixels between the right edges of the mark’s inner and outer plot area." + }, + "marginTop": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s top margin; the minimum distance in pixels between the top edges of the inner and outer plot area." + }, + "mark": { + "const": "barX", + "description": "A horizontal bar mark. The required *x* values should be quantitative or temporal, and the optional *y* values should be ordinal.\n\nIf neither **x1** nor **x2** nor **interval** is specified, an implicit stackX transform is applied and **x** defaults to the identity function, assuming that *data* = [*x₀*, *x₁*, *x₂*, …]. Otherwise if an **interval** is specified, then **x1** and **x2** are derived from **x**, representing the lower and upper bound of the containing interval, respectively. Otherwise, if only one of **x1** or **x2** is specified, the other defaults to **x**, which defaults to zero.\n\nThe optional **y** ordinal channel specifies the vertical position; it is typically bound to the *y* scale, which must be a *band* scale. If the\n**y** channel is not specified, the bar will span the vertical extent of the plot’s frame.\n\nIf *y* is quantitative, use the rectX mark instead. If *x* is ordinal, use the cell mark instead.", + "type": "string" + }, + "meta": { + "$ref": "#/definitions/Meta", + "description": "Specification metadata." + }, + "mixBlendMode": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [mix-blend-mode][1]; a constant string specifying how to blend content such as *multiply*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode" + }, + "offset": { + "anyOf": [ + { + "$ref": "#/definitions/StackOffset" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "After stacking, an optional **offset** can be applied to translate and scale stacks, say to produce a streamgraph; defaults to null for a zero baseline (**y** = 0 for stackY, and **x** = 0 for stackX). If the *wiggle* offset is used, the default **order** changes to *inside-out*." + }, + "opacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally. For faster rendering, prefer the **strokeOpacity** or **fillOpacity** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/opacity" + }, + "order": { + "anyOf": [ + { + "$ref": "#/definitions/StackOrder" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The order in which stacks are layered; one of:\n\n- null (default) for input order\n- a named stack order method such as *inside-out* or *sum*\n- a field name, for natural order of the corresponding values\n- a function of data, for natural order of the corresponding values\n- an array of explicit **z** values in the desired order\n\nIf the *wiggle* **offset** is used, as for a streamgraph, the default changes to *inside-out*." + }, + "paintOrder": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [paint-order][1]; a constant string specifying the order in which the\n**fill**, **stroke**, and any markers are drawn; defaults to *normal*, which draws the fill, then stroke, then markers; defaults to *stroke* for the text mark to create a “halo” around text to improve legibility.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/paint-order" + }, + "params": { + "$ref": "#/definitions/Params", + "description": "Param and Selection definitions." + }, + "plotDefaults": { + "$ref": "#/definitions/PlotAttributes", + "description": "A default set of attributes to apply to all plot components." + }, + "pointerEvents": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [pointer-events][1] property; a constant string such as *none*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/pointer-events" + }, + "reverse": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Applies a transform to reverse the order of the mark’s index, say for reverse input order." + }, + "rx": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The rounded corner [*x*-radius][1], either in pixels or as a percentage of the rect width. If **rx** is not specified, it defaults to **ry** if present, and otherwise draws square corners.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/rx" + }, + "ry": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The rounded corner [*y*-radius][1], either in pixels or as a percentage of the rect height. If **ry** is not specified, it defaults to **rx** if present, and otherwise draws square corners.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/ry" + }, + "select": { + "$ref": "#/definitions/SelectFilter", + "description": "Applies a filter transform after data is loaded to highlight selected values only. For example, `first` and `last` select the first or last values of series only (using the *z* channel to separate series). Meanwhile, `nearestX` and `nearestY` select the point nearest to the pointer along the *x* or *y* channel dimension. Unlike Mosaic selections, a mark level *select* is internal to the mark only, and does not populate a param or selection value to be shared across clients.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "shapeRendering": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [shape-rendering][1]; a constant string such as *crispEdges*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/shape-rendering" + }, + "sort": { + "anyOf": [ + { + "$ref": "#/definitions/SortOrder" + }, + { + "$ref": "#/definitions/ChannelDomainSort" + } + ], + "description": "Either applies a transform to sort the mark’s index by the specified channel values, or imputes ordinal scale domains from this mark’s channels.\n\nWhen imputing ordinal scale domains from channel values, the **sort** option is an object whose keys are ordinal scale names such as *x* or *fx*, and whose values are channel names such as *y*, *y1*, or *y2*. For example, to impute the *y* scale’s domain from the associated *x* channel values in ascending order:\n\n```js sort: {y: \"x\"} ```\n\nFor different sort options for different scales, replace the channel name with a *value* object and per-scale options:\n\n```js sort: {y: {value: \"-x\"}} ```\n\nWhen sorting the mark’s index, the **sort** option is instead one of:\n\n- a channel value definition for sorting given values in ascending order\n- a {value, order} object for sorting given values\n- a {channel, order} object for sorting the named channel’s values" + }, + "stroke": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke" + }, + "strokeDasharray": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dasharray][1]; a constant number indicating the length in pixels of alternating dashes and gaps, or a constant string of numbers separated by spaces or commas (_e.g._, *10 2* for dashes of 10 pixels separated by gaps of 2 pixels), or *none* (the default) for no dashing\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dasharray" + }, + "strokeDashoffset": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dashoffset][1]; a constant indicating the offset in pixels of the first dash along the stroke; defaults to zero.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dashoffset" + }, + "strokeLinecap": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linecap][1]; a constant specifying how to cap stroked paths, such as *butt*, *round*, or *square*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linecap" + }, + "strokeLinejoin": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linejoin][1]; a constant specifying how to join stroked paths, such as *bevel*, *miter*, *miter-clip*, or *round*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linejoin" + }, + "strokeMiterlimit": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-miterlimit][1]; a constant number specifying how to limit the length of *miter* joins on stroked paths.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-miterlimit" + }, + "strokeOpacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-opacity" + }, + "strokeWidth": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-width][1]; a constant number in pixels, or a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-width" + }, + "target": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [target][1]; a constant string specifying the target window (_e.g._,\n*_blank*) for clickable links; used in conjunction with the **href** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/target" + }, + "tip": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/TipPointer" + }, + { + "properties": { + "anchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The tip anchor specifies how to orient the tip box relative to its anchor position; it refers to the part of the tip box that is attached to the anchor point. For example, the *top-left* anchor places the top-left corner of tip box near the anchor position, hence placing the tip box below and to the right of the anchor position." + }, + "fontFamily": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font-family][1]; a constant; defaults to the plot’s font family, which is typically [*system-ui*][2].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-family [2]: https://drafts.csswg.org/css-fonts-4/#valdef-font-family-system-ui" + }, + "fontSize": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font size][1] in pixels; either a constant or a channel; defaults to the plot’s font size, which is typically 10. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-size" + }, + "fontStyle": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font style][1]; a constant; defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-style" + }, + "fontVariant": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font variant][1]; a constant; if the **text** channel contains numbers or dates, defaults to *tabular-nums* to facilitate comparing numbers; otherwise defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant" + }, + "fontWeight": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font weight][1]; a constant; defaults to the plot’s font weight, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight" + }, + "format": { + "additionalProperties": false, + "description": "How channel values are formatted for display. If a format is a string, it is interpreted as a (UTC) time format for temporal channels, and otherwise a number format.", + "properties": { + "ariaLabel": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fill": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fillOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fontSize": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fx": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fy": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "geometry": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "height": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "href": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "length": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "opacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "path": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "r": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "rotate": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "src": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "stroke": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeWidth": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "symbol": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "text": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "title": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "weight": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "width": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "z": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + } + }, + "type": "object" + }, + "frameAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The frame anchor specifies defaults for **x** and **y** based on the plot’s frame; it may be one of the four sides (*top*, *right*, *bottom*, *left*), one of the four corners (*top-left*, *top-right*, *bottom-right*,\n*bottom-left*), or the *middle* of the frame. For example, for tips distributed horizontally at the top of the frame:\n\n```js Plot.tip(data, {x: \"date\", frameAnchor: \"top\"}) ```" + }, + "lineHeight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line height in ems; defaults to 1. The line height affects the (typically vertical) separation between adjacent baselines of text, as well as the separation between the text and its anchor point." + }, + "lineWidth": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line width in ems (e.g., 10 for about 20 characters); defaults to infinity, disabling wrapping and clipping.\n\nIf **textOverflow** is null, lines will be wrapped at the specified length. If a line is split at a soft hyphen (\\xad), a hyphen (-) will be displayed at the end of the line. If **textOverflow** is not null, lines will be clipped according to the given strategy." + }, + "monospace": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, changes the default **fontFamily** to *monospace*, and uses simplified monospaced text metrics calculations." + }, + "pathFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The image filter for the tip’s box; defaults to a drop shadow." + }, + "pointer": { + "$ref": "#/definitions/TipPointer" + }, + "pointerSize": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The size of the tip’s pointer in pixels; defaults to 12." + }, + "preferredAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If an explicit tip anchor is not specified, an anchor is chosen automatically such that the tip fits within the plot’s frame; if the preferred anchor fits, it is chosen." + }, + "textAnchor": { + "anyOf": [ + { + "const": "start", + "type": "string" + }, + { + "const": "middle", + "type": "string" + }, + { + "const": "end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [text anchor][1] controls how text is aligned (typically horizontally) relative to its anchor point; it is one of *start*, *end*, or *middle*. If the frame anchor is *left*, *top-left*, or *bottom-left*, the default text anchor is *start*; if the frame anchor is *right*, *top-right*, or\n*bottom-right*, the default is *end*; otherwise it is *middle*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/text-anchor" + }, + "textOverflow": { + "anyOf": [ + { + "type": "null" + }, + { + "const": "clip", + "type": "string" + }, + { + "const": "ellipsis", + "type": "string" + }, + { + "const": "clip-start", + "type": "string" + }, + { + "const": "clip-end", + "type": "string" + }, + { + "const": "ellipsis-start", + "type": "string" + }, + { + "const": "ellipsis-middle", + "type": "string" + }, + { + "const": "ellipsis-end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How truncate (or wrap) lines of text longer than the given **lineWidth**; one of:\n\n- null (default) - preserve overflowing characters (and wrap if needed)\n- *clip* or *clip-end* - remove characters from the end\n- *clip-start* - remove characters from the start\n- *ellipsis* or *ellipsis-end* - replace characters from the end with an ellipsis (…)\n- *ellipsis-start* - replace characters from the start with an ellipsis (…)\n- *ellipsis-middle* - replace characters from the middle with an ellipsis (…)\n\nIf no **title** was specified, if text requires truncation, a title containing the non-truncated text will be implicitly added." + }, + "textPadding": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The padding around the text in pixels; defaults to 8." + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + } + }, + "type": "object" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to generate a tooltip for this mark, and any tip options." + }, + "title": { + "$ref": "#/definitions/ChannelValue", + "description": "The title; a channel specifying accessible, short textual descriptions as strings (possibly with newlines). If the tip option is specified, the title will be displayed with an interactive tooltip instead of using the SVG [title element][1].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/title" + }, + "x": { + "$ref": "#/definitions/ChannelValueIntervalSpec", + "description": "The horizontal position (or length/width) channel, typically bound to the\n*x* scale.\n\nIf neither **x1** nor **x2** nor **interval** is specified, an implicit stackX transform is applied and **x** defaults to the identity function, assuming that *data* = [*x₀*, *x₁*, *x₂*, …]. Otherwise if an **interval** is specified, then **x1** and **x2** are derived from **x**, representing the lower and upper bound of the containing interval, respectively. Otherwise, if only one of **x1** or **x2** is specified, the other defaults to **x**, which defaults to zero." + }, + "x1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The required primary (starting, often left) horizontal position channel, typically bound to the *x* scale. Setting this option disables the implicit stackX transform.\n\nIf *x* represents ordinal values, use a cell mark instead." + }, + "x2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The required secondary (ending, often right) horizontal position channel, typically bound to the *x* scale. Setting this option disables the implicit stackX transform.\n\nIf *x* represents ordinal values, use a cell mark instead." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The optional vertical position of the bar; a ordinal channel typically bound to the *y* scale. If not specified, the bar spans the vertical extent of the frame; otherwise the *y* scale must be a *band* scale.\n\nIf *y* represents quantitative or temporal values, use a rectX mark instead." + }, + "z": { + "$ref": "#/definitions/ChannelValue", + "description": "The **z** channel defines the series of each value in the stack. Used when the **order** is *sum*, *appearance*, *inside-out*, or an explicit array of\n**z** values." + } + }, + "required": [ + "data", + "mark" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "$schema": { + "description": "A [JSON schema](http://json-schema.org/) URL for this specification, such as https://uwdata.github.io/mosaic/schema/latest.json. This property enables validation and autocomplete in editors with JSON schema support.", + "format": "uri", + "type": "string" + }, + "ariaDescription": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-description][1]; a constant textual description.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-description" + }, + "ariaHidden": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-hidden][1] state; a constant indicating whether the element is exposed to an accessibility API.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-hidden" + }, + "ariaLabel": { + "$ref": "#/definitions/ChannelValue", + "description": "The [aria-label][1]; a channel specifying short textual labels representing the value in the accessibility tree.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-label" + }, + "clip": { + "anyOf": [ + { + "const": "frame", + "type": "string" + }, + { + "const": "sphere", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to clip the mark; one of:\n\n- *frame* or true - clip to the plot’s frame (inner area)\n- *sphere* - clip to the projected sphere (*e.g.*, front hemisphere)\n- null or false - do not clip\n\nThe *sphere* clip option requires a geographic projection." + }, + "config": { + "$ref": "#/definitions/Config", + "description": "Configuration options." + }, + "data": { + "$ref": "#/definitions/Data", + "description": "Dataset definitions." + }, + "dx": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The horizontal offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "dy": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The vertical offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "facet": { + "anyOf": [ + { + "const": "auto", + "type": "string" + }, + { + "const": "include", + "type": "string" + }, + { + "const": "exclude", + "type": "string" + }, + { + "const": "super", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to enable or disable faceting; one of:\n\n- *auto* (default) - automatically determine if this mark should be faceted\n- *include* (or true) - draw the subset of the mark’s data in the current facet\n- *exclude* - draw the subset of the mark’s data *not* in the current facet\n- *super* - draw this mark in a single frame that covers all facets\n- null (or false) - repeat this mark’s data across all facets (*i.e.*, no faceting)\n\nWhen a mark uses *super* faceting, it is not allowed to use position scales (*x*, *y*, *fx*, or *fy*); *super* faceting is intended for decorations, such as labels and legends.\n\nWhen top-level faceting is used, the default *auto* setting is equivalent to *include* when the mark data is strictly equal to the top-level facet data; otherwise it is equivalent to null. When the *include* or *exclude* facet mode is chosen, the mark data must be parallel to the top-level facet data: the data must have the same length and order. If the data are not parallel, then the wrong data may be shown in each facet. The default\n*auto* therefore requires strict equality (`===`) for safety, and using the facet data as mark data is recommended when using the *exclude* facet mode. (To construct parallel data safely, consider using [*array*.map][1] on the facet data.)\n\nWhen mark-level faceting is used, the default *auto* setting is equivalent to *include*: the mark will be faceted if either the **fx** or **fy** channel option (or both) is specified. The null or false option will disable faceting, while *exclude* draws the subset of the mark’s data *not* in the current facet.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map" + }, + "facetAnchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "right", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "const": "left", + "type": "string" + }, + { + "const": "top-left", + "type": "string" + }, + { + "const": "top-right", + "type": "string" + }, + { + "const": "bottom-left", + "type": "string" + }, + { + "const": "bottom-right", + "type": "string" + }, + { + "const": "top-empty", + "type": "string" + }, + { + "const": "right-empty", + "type": "string" + }, + { + "const": "bottom-empty", + "type": "string" + }, + { + "const": "left-empty", + "type": "string" + }, + { + "const": "empty", + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to place the mark with respect to facets; one of:\n\n- null (default for most marks) - display the mark in each non-empty facet\n- *top*, *right*, *bottom*, or *left* - display the mark only in facets on the given side\n- *top-empty*, *right-empty*, *bottom-empty*, or *left-empty* (default for axis marks) - display the mark only in facets that have empty space on the given side: either the margin, or an empty facet\n- *empty* - display the mark in empty facets only" + }, + "fill": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill" + }, + "fillOpacity": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill-opacity][1]; a constant number between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill-opacity" + }, + "filter": { + "$ref": "#/definitions/ChannelValue", + "description": "Applies a transform to filter the mark’s index according to the given channel values; only truthy values are retained.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "fx": { + "$ref": "#/definitions/ChannelValue", + "description": "The horizontal facet position channel, for mark-level faceting, bound to the *fx* scale." + }, + "fy": { + "$ref": "#/definitions/ChannelValue", + "description": "The vertical facet position channel, for mark-level faceting, bound to the\n*fy* scale." + }, + "href": { + "$ref": "#/definitions/ChannelValue", + "description": "The [href][1]; a channel specifying URLs for clickable links. May be used in conjunction with the **target** option to open links in another window.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/href" + }, + "imageFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A CSS [filter][1]; a constant string used to adjust the rendering of images, such as *blur(5px)*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/filter" + }, + "inset": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four insets: **insetTop**,\n**insetRight**, **insetBottom**, and **insetLeft**. All insets typically default to zero, though not always (say when using bin transform). A positive inset reduces effective area, while a negative inset increases it." + }, + "insetBottom": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Insets the bottom edge by the specified number of pixels. A positive value insets towards the top edge (reducing effective area), while a negative value insets away from the top edge (increasing it)." + }, + "insetLeft": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Insets the left edge by the specified number of pixels. A positive value insets towards the right edge (reducing effective area), while a negative value insets away from the right edge (increasing it)." + }, + "insetRight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Insets the right edge by the specified number of pixels. A positive value insets towards the left edge (reducing effective area), while a negative value insets away from the left edge (increasing it)." + }, + "insetTop": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Insets the top edge by the specified number of pixels. A positive value insets towards the bottom edge (reducing effective area), while a negative value insets away from the bottom edge (increasing it)." + }, + "interval": { + "anyOf": [ + { + "$ref": "#/definitions/Interval" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to convert a continuous value (**x** for barX, or **y** for barY) into an interval (**x1** and **x2** for barX, or **y1** and **y2** for barY); one of:\n\n- a named time interval such as *day* (for date intervals)\n- a number (for number intervals), defining intervals at integer multiples of *n*\n\nSetting this option disables the implicit stack transform (stackX for barX, or stackY for barY)." + }, + "margin": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four mark margins: **marginTop**,\n**marginRight**, **marginBottom**, and **marginLeft**; typically defaults to 0, except for axis marks." + }, + "marginBottom": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s bottom margin; the minimum distance in pixels between the bottom edges of the inner and outer plot area." + }, + "marginLeft": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s left margin; the minimum distance in pixels between the left edges of the inner and outer plot area." + }, + "marginRight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s right margin; the minimum distance in pixels between the right edges of the mark’s inner and outer plot area." + }, + "marginTop": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s top margin; the minimum distance in pixels between the top edges of the inner and outer plot area." + }, + "mark": { + "const": "barY", + "description": "A vertical bar mark. The required *y* values should be quantitative or temporal, and the optional *x* values should be ordinal.\n\nIf neither **y1** nor **y2** nor **interval** is specified, an implicit stackY transform is applied and **y** defaults to the identity function, assuming that *data* = [*y₀*, *y₁*, *y₂*, …]. Otherwise if an **interval** is specified, then **y1** and **y2** are derived from **y**, representing the lower and upper bound of the containing interval, respectively. Otherwise, if only one of **y1** or **y2** is specified, the other defaults to **y**, which defaults to zero.\n\nThe optional **x** ordinal channel specifies the horizontal position; it is typically bound to the *x* scale, which must be a *band* scale. If the\n**x** channel is not specified, the bar will span the horizontal extent of the plot’s frame.\n\nIf *x* is quantitative, use the rectY mark instead. If *y* is ordinal, use the cell mark instead.", + "type": "string" + }, + "meta": { + "$ref": "#/definitions/Meta", + "description": "Specification metadata." + }, + "mixBlendMode": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [mix-blend-mode][1]; a constant string specifying how to blend content such as *multiply*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode" + }, + "offset": { + "anyOf": [ + { + "$ref": "#/definitions/StackOffset" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "After stacking, an optional **offset** can be applied to translate and scale stacks, say to produce a streamgraph; defaults to null for a zero baseline (**y** = 0 for stackY, and **x** = 0 for stackX). If the *wiggle* offset is used, the default **order** changes to *inside-out*." + }, + "opacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally. For faster rendering, prefer the **strokeOpacity** or **fillOpacity** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/opacity" + }, + "order": { + "anyOf": [ + { + "$ref": "#/definitions/StackOrder" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The order in which stacks are layered; one of:\n\n- null (default) for input order\n- a named stack order method such as *inside-out* or *sum*\n- a field name, for natural order of the corresponding values\n- a function of data, for natural order of the corresponding values\n- an array of explicit **z** values in the desired order\n\nIf the *wiggle* **offset** is used, as for a streamgraph, the default changes to *inside-out*." + }, + "paintOrder": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [paint-order][1]; a constant string specifying the order in which the\n**fill**, **stroke**, and any markers are drawn; defaults to *normal*, which draws the fill, then stroke, then markers; defaults to *stroke* for the text mark to create a “halo” around text to improve legibility.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/paint-order" + }, + "params": { + "$ref": "#/definitions/Params", + "description": "Param and Selection definitions." + }, + "plotDefaults": { + "$ref": "#/definitions/PlotAttributes", + "description": "A default set of attributes to apply to all plot components." + }, + "pointerEvents": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [pointer-events][1] property; a constant string such as *none*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/pointer-events" + }, + "reverse": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Applies a transform to reverse the order of the mark’s index, say for reverse input order." + }, + "rx": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The rounded corner [*x*-radius][1], either in pixels or as a percentage of the rect width. If **rx** is not specified, it defaults to **ry** if present, and otherwise draws square corners.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/rx" + }, + "ry": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The rounded corner [*y*-radius][1], either in pixels or as a percentage of the rect height. If **ry** is not specified, it defaults to **rx** if present, and otherwise draws square corners.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/ry" + }, + "select": { + "$ref": "#/definitions/SelectFilter", + "description": "Applies a filter transform after data is loaded to highlight selected values only. For example, `first` and `last` select the first or last values of series only (using the *z* channel to separate series). Meanwhile, `nearestX` and `nearestY` select the point nearest to the pointer along the *x* or *y* channel dimension. Unlike Mosaic selections, a mark level *select* is internal to the mark only, and does not populate a param or selection value to be shared across clients.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "shapeRendering": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [shape-rendering][1]; a constant string such as *crispEdges*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/shape-rendering" + }, + "sort": { + "anyOf": [ + { + "$ref": "#/definitions/SortOrder" + }, + { + "$ref": "#/definitions/ChannelDomainSort" + } + ], + "description": "Either applies a transform to sort the mark’s index by the specified channel values, or imputes ordinal scale domains from this mark’s channels.\n\nWhen imputing ordinal scale domains from channel values, the **sort** option is an object whose keys are ordinal scale names such as *x* or *fx*, and whose values are channel names such as *y*, *y1*, or *y2*. For example, to impute the *y* scale’s domain from the associated *x* channel values in ascending order:\n\n```js sort: {y: \"x\"} ```\n\nFor different sort options for different scales, replace the channel name with a *value* object and per-scale options:\n\n```js sort: {y: {value: \"-x\"}} ```\n\nWhen sorting the mark’s index, the **sort** option is instead one of:\n\n- a channel value definition for sorting given values in ascending order\n- a {value, order} object for sorting given values\n- a {channel, order} object for sorting the named channel’s values" + }, + "stroke": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke" + }, + "strokeDasharray": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dasharray][1]; a constant number indicating the length in pixels of alternating dashes and gaps, or a constant string of numbers separated by spaces or commas (_e.g._, *10 2* for dashes of 10 pixels separated by gaps of 2 pixels), or *none* (the default) for no dashing\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dasharray" + }, + "strokeDashoffset": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dashoffset][1]; a constant indicating the offset in pixels of the first dash along the stroke; defaults to zero.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dashoffset" + }, + "strokeLinecap": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linecap][1]; a constant specifying how to cap stroked paths, such as *butt*, *round*, or *square*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linecap" + }, + "strokeLinejoin": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linejoin][1]; a constant specifying how to join stroked paths, such as *bevel*, *miter*, *miter-clip*, or *round*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linejoin" + }, + "strokeMiterlimit": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-miterlimit][1]; a constant number specifying how to limit the length of *miter* joins on stroked paths.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-miterlimit" + }, + "strokeOpacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-opacity" + }, + "strokeWidth": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-width][1]; a constant number in pixels, or a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-width" + }, + "target": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [target][1]; a constant string specifying the target window (_e.g._,\n*_blank*) for clickable links; used in conjunction with the **href** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/target" + }, + "tip": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/TipPointer" + }, + { + "properties": { + "anchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The tip anchor specifies how to orient the tip box relative to its anchor position; it refers to the part of the tip box that is attached to the anchor point. For example, the *top-left* anchor places the top-left corner of tip box near the anchor position, hence placing the tip box below and to the right of the anchor position." + }, + "fontFamily": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font-family][1]; a constant; defaults to the plot’s font family, which is typically [*system-ui*][2].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-family [2]: https://drafts.csswg.org/css-fonts-4/#valdef-font-family-system-ui" + }, + "fontSize": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font size][1] in pixels; either a constant or a channel; defaults to the plot’s font size, which is typically 10. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-size" + }, + "fontStyle": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font style][1]; a constant; defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-style" + }, + "fontVariant": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font variant][1]; a constant; if the **text** channel contains numbers or dates, defaults to *tabular-nums* to facilitate comparing numbers; otherwise defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant" + }, + "fontWeight": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font weight][1]; a constant; defaults to the plot’s font weight, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight" + }, + "format": { + "additionalProperties": false, + "description": "How channel values are formatted for display. If a format is a string, it is interpreted as a (UTC) time format for temporal channels, and otherwise a number format.", + "properties": { + "ariaLabel": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fill": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fillOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fontSize": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fx": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fy": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "geometry": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "height": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "href": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "length": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "opacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "path": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "r": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "rotate": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "src": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "stroke": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeWidth": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "symbol": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "text": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "title": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "weight": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "width": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "z": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + } + }, + "type": "object" + }, + "frameAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The frame anchor specifies defaults for **x** and **y** based on the plot’s frame; it may be one of the four sides (*top*, *right*, *bottom*, *left*), one of the four corners (*top-left*, *top-right*, *bottom-right*,\n*bottom-left*), or the *middle* of the frame. For example, for tips distributed horizontally at the top of the frame:\n\n```js Plot.tip(data, {x: \"date\", frameAnchor: \"top\"}) ```" + }, + "lineHeight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line height in ems; defaults to 1. The line height affects the (typically vertical) separation between adjacent baselines of text, as well as the separation between the text and its anchor point." + }, + "lineWidth": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line width in ems (e.g., 10 for about 20 characters); defaults to infinity, disabling wrapping and clipping.\n\nIf **textOverflow** is null, lines will be wrapped at the specified length. If a line is split at a soft hyphen (\\xad), a hyphen (-) will be displayed at the end of the line. If **textOverflow** is not null, lines will be clipped according to the given strategy." + }, + "monospace": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, changes the default **fontFamily** to *monospace*, and uses simplified monospaced text metrics calculations." + }, + "pathFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The image filter for the tip’s box; defaults to a drop shadow." + }, + "pointer": { + "$ref": "#/definitions/TipPointer" + }, + "pointerSize": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The size of the tip’s pointer in pixels; defaults to 12." + }, + "preferredAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If an explicit tip anchor is not specified, an anchor is chosen automatically such that the tip fits within the plot’s frame; if the preferred anchor fits, it is chosen." + }, + "textAnchor": { + "anyOf": [ + { + "const": "start", + "type": "string" + }, + { + "const": "middle", + "type": "string" + }, + { + "const": "end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [text anchor][1] controls how text is aligned (typically horizontally) relative to its anchor point; it is one of *start*, *end*, or *middle*. If the frame anchor is *left*, *top-left*, or *bottom-left*, the default text anchor is *start*; if the frame anchor is *right*, *top-right*, or\n*bottom-right*, the default is *end*; otherwise it is *middle*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/text-anchor" + }, + "textOverflow": { + "anyOf": [ + { + "type": "null" + }, + { + "const": "clip", + "type": "string" + }, + { + "const": "ellipsis", + "type": "string" + }, + { + "const": "clip-start", + "type": "string" + }, + { + "const": "clip-end", + "type": "string" + }, + { + "const": "ellipsis-start", + "type": "string" + }, + { + "const": "ellipsis-middle", + "type": "string" + }, + { + "const": "ellipsis-end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How truncate (or wrap) lines of text longer than the given **lineWidth**; one of:\n\n- null (default) - preserve overflowing characters (and wrap if needed)\n- *clip* or *clip-end* - remove characters from the end\n- *clip-start* - remove characters from the start\n- *ellipsis* or *ellipsis-end* - replace characters from the end with an ellipsis (…)\n- *ellipsis-start* - replace characters from the start with an ellipsis (…)\n- *ellipsis-middle* - replace characters from the middle with an ellipsis (…)\n\nIf no **title** was specified, if text requires truncation, a title containing the non-truncated text will be implicitly added." + }, + "textPadding": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The padding around the text in pixels; defaults to 8." + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + } + }, + "type": "object" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to generate a tooltip for this mark, and any tip options." + }, + "title": { + "$ref": "#/definitions/ChannelValue", + "description": "The title; a channel specifying accessible, short textual descriptions as strings (possibly with newlines). If the tip option is specified, the title will be displayed with an interactive tooltip instead of using the SVG [title element][1].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/title" + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The optional horizontal position of the bar; a ordinal channel typically bound to the *x* scale. If not specified, the bar spans the horizontal extent of the frame; otherwise the *x* scale must be a *band* scale.\n\nIf *x* represents quantitative or temporal values, use a rectY mark instead." + }, + "y": { + "$ref": "#/definitions/ChannelValueIntervalSpec", + "description": "The vertical position (or length/height) channel, typically bound to the\n*y* scale.\n\nIf neither **y1** nor **y2** nor **interval** is specified, an implicit stackY transform is applied and **y** defaults to the identity function, assuming that *data* = [*y₀*, *y₁*, *y₂*, …]. Otherwise if an **interval** is specified, then **y1** and **y2** are derived from **y**, representing the lower and upper bound of the containing interval, respectively. Otherwise, if only one of **y1** or **y2** is specified, the other defaults to **y**, which defaults to zero." + }, + "y1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The required primary (starting, often bottom) vertical position channel, typically bound to the *y* scale. Setting this option disables the implicit stackY transform.\n\nIf *y* represents ordinal values, use a cell mark instead." + }, + "y2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The required secondary (ending, often top) horizontal position channel, typically bound to the *y* scale. Setting this option disables the implicit stackY transform.\n\nIf *y* represents ordinal values, use a cell mark instead." + }, + "z": { + "$ref": "#/definitions/ChannelValue", + "description": "The **z** channel defines the series of each value in the stack. Used when the **order** is *sum*, *appearance*, *inside-out*, or an explicit array of\n**z** values." + } + }, + "required": [ + "data", + "mark" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "$schema": { + "description": "A [JSON schema](http://json-schema.org/) URL for this specification, such as https://uwdata.github.io/mosaic/schema/latest.json. This property enables validation and autocomplete in editors with JSON schema support.", + "format": "uri", + "type": "string" + }, + "ariaDescription": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-description][1]; a constant textual description.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-description" + }, + "ariaHidden": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-hidden][1] state; a constant indicating whether the element is exposed to an accessibility API.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-hidden" + }, + "ariaLabel": { + "$ref": "#/definitions/ChannelValue", + "description": "The [aria-label][1]; a channel specifying short textual labels representing the value in the accessibility tree.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-label" + }, + "clip": { + "anyOf": [ + { + "const": "frame", + "type": "string" + }, + { + "const": "sphere", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to clip the mark; one of:\n\n- *frame* or true - clip to the plot’s frame (inner area)\n- *sphere* - clip to the projected sphere (*e.g.*, front hemisphere)\n- null or false - do not clip\n\nThe *sphere* clip option requires a geographic projection." + }, + "config": { + "$ref": "#/definitions/Config", + "description": "Configuration options." + }, + "data": { + "$ref": "#/definitions/Data", + "description": "Dataset definitions." + }, + "dx": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The horizontal offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "dy": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The vertical offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "facet": { + "anyOf": [ + { + "const": "auto", + "type": "string" + }, + { + "const": "include", + "type": "string" + }, + { + "const": "exclude", + "type": "string" + }, + { + "const": "super", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to enable or disable faceting; one of:\n\n- *auto* (default) - automatically determine if this mark should be faceted\n- *include* (or true) - draw the subset of the mark’s data in the current facet\n- *exclude* - draw the subset of the mark’s data *not* in the current facet\n- *super* - draw this mark in a single frame that covers all facets\n- null (or false) - repeat this mark’s data across all facets (*i.e.*, no faceting)\n\nWhen a mark uses *super* faceting, it is not allowed to use position scales (*x*, *y*, *fx*, or *fy*); *super* faceting is intended for decorations, such as labels and legends.\n\nWhen top-level faceting is used, the default *auto* setting is equivalent to *include* when the mark data is strictly equal to the top-level facet data; otherwise it is equivalent to null. When the *include* or *exclude* facet mode is chosen, the mark data must be parallel to the top-level facet data: the data must have the same length and order. If the data are not parallel, then the wrong data may be shown in each facet. The default\n*auto* therefore requires strict equality (`===`) for safety, and using the facet data as mark data is recommended when using the *exclude* facet mode. (To construct parallel data safely, consider using [*array*.map][1] on the facet data.)\n\nWhen mark-level faceting is used, the default *auto* setting is equivalent to *include*: the mark will be faceted if either the **fx** or **fy** channel option (or both) is specified. The null or false option will disable faceting, while *exclude* draws the subset of the mark’s data *not* in the current facet.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map" + }, + "facetAnchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "right", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "const": "left", + "type": "string" + }, + { + "const": "top-left", + "type": "string" + }, + { + "const": "top-right", + "type": "string" + }, + { + "const": "bottom-left", + "type": "string" + }, + { + "const": "bottom-right", + "type": "string" + }, + { + "const": "top-empty", + "type": "string" + }, + { + "const": "right-empty", + "type": "string" + }, + { + "const": "bottom-empty", + "type": "string" + }, + { + "const": "left-empty", + "type": "string" + }, + { + "const": "empty", + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to place the mark with respect to facets; one of:\n\n- null (default for most marks) - display the mark in each non-empty facet\n- *top*, *right*, *bottom*, or *left* - display the mark only in facets on the given side\n- *top-empty*, *right-empty*, *bottom-empty*, or *left-empty* (default for axis marks) - display the mark only in facets that have empty space on the given side: either the margin, or an empty facet\n- *empty* - display the mark in empty facets only" + }, + "fill": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill" + }, + "fillOpacity": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill-opacity][1]; a constant number between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill-opacity" + }, + "filter": { + "$ref": "#/definitions/ChannelValue", + "description": "Applies a transform to filter the mark’s index according to the given channel values; only truthy values are retained.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "fx": { + "$ref": "#/definitions/ChannelValue", + "description": "The horizontal facet position channel, for mark-level faceting, bound to the *fx* scale." + }, + "fy": { + "$ref": "#/definitions/ChannelValue", + "description": "The vertical facet position channel, for mark-level faceting, bound to the\n*fy* scale." + }, + "href": { + "$ref": "#/definitions/ChannelValue", + "description": "The [href][1]; a channel specifying URLs for clickable links. May be used in conjunction with the **target** option to open links in another window.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/href" + }, + "imageFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A CSS [filter][1]; a constant string used to adjust the rendering of images, such as *blur(5px)*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/filter" + }, + "inset": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four insets: **insetTop**,\n**insetRight**, **insetBottom**, and **insetLeft**. All insets typically default to zero, though not always (say when using bin transform). A positive inset reduces effective area, while a negative inset increases it." + }, + "insetBottom": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Insets the bottom edge by the specified number of pixels. A positive value insets towards the top edge (reducing effective area), while a negative value insets away from the top edge (increasing it)." + }, + "insetLeft": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Insets the left edge by the specified number of pixels. A positive value insets towards the right edge (reducing effective area), while a negative value insets away from the right edge (increasing it)." + }, + "insetRight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Insets the right edge by the specified number of pixels. A positive value insets towards the left edge (reducing effective area), while a negative value insets away from the left edge (increasing it)." + }, + "insetTop": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Insets the top edge by the specified number of pixels. A positive value insets towards the bottom edge (reducing effective area), while a negative value insets away from the bottom edge (increasing it)." + }, + "margin": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four mark margins: **marginTop**,\n**marginRight**, **marginBottom**, and **marginLeft**; typically defaults to 0, except for axis marks." + }, + "marginBottom": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s bottom margin; the minimum distance in pixels between the bottom edges of the inner and outer plot area." + }, + "marginLeft": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s left margin; the minimum distance in pixels between the left edges of the inner and outer plot area." + }, + "marginRight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s right margin; the minimum distance in pixels between the right edges of the mark’s inner and outer plot area." + }, + "marginTop": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s top margin; the minimum distance in pixels between the top edges of the inner and outer plot area." + }, + "mark": { + "const": "cell", + "description": "A rectangular cell mark. Along with **x** and/or **y**, a **fill** channel is typically specified to encode value as color.\n\nIf neither **x** nor **y** are specified, *data* is assumed to be an array of pairs [[*x₀*, *y₀*], [*x₁*, *y₁*], [*x₂*, *y₂*], …] such that **x** = [*x₀*,\n*x₁*, *x₂*, …] and **y** = [*y₀*, *y₁*, *y₂*, …].\n\nBoth **x** and **y** should be ordinal; if only **x** is quantitative (or temporal), use a barX mark; if only **y** is quantitative, use a barY mark; if both are quantitative, use a rect mark.", + "type": "string" + }, + "meta": { + "$ref": "#/definitions/Meta", + "description": "Specification metadata." + }, + "mixBlendMode": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [mix-blend-mode][1]; a constant string specifying how to blend content such as *multiply*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode" + }, + "opacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally. For faster rendering, prefer the **strokeOpacity** or **fillOpacity** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/opacity" + }, + "paintOrder": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [paint-order][1]; a constant string specifying the order in which the\n**fill**, **stroke**, and any markers are drawn; defaults to *normal*, which draws the fill, then stroke, then markers; defaults to *stroke* for the text mark to create a “halo” around text to improve legibility.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/paint-order" + }, + "params": { + "$ref": "#/definitions/Params", + "description": "Param and Selection definitions." + }, + "plotDefaults": { + "$ref": "#/definitions/PlotAttributes", + "description": "A default set of attributes to apply to all plot components." + }, + "pointerEvents": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [pointer-events][1] property; a constant string such as *none*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/pointer-events" + }, + "reverse": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Applies a transform to reverse the order of the mark’s index, say for reverse input order." + }, + "rx": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The rounded corner [*x*-radius][1], either in pixels or as a percentage of the rect width. If **rx** is not specified, it defaults to **ry** if present, and otherwise draws square corners.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/rx" + }, + "ry": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The rounded corner [*y*-radius][1], either in pixels or as a percentage of the rect height. If **ry** is not specified, it defaults to **rx** if present, and otherwise draws square corners.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/ry" + }, + "select": { + "$ref": "#/definitions/SelectFilter", + "description": "Applies a filter transform after data is loaded to highlight selected values only. For example, `first` and `last` select the first or last values of series only (using the *z* channel to separate series). Meanwhile, `nearestX` and `nearestY` select the point nearest to the pointer along the *x* or *y* channel dimension. Unlike Mosaic selections, a mark level *select* is internal to the mark only, and does not populate a param or selection value to be shared across clients.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "shapeRendering": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [shape-rendering][1]; a constant string such as *crispEdges*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/shape-rendering" + }, + "sort": { + "anyOf": [ + { + "$ref": "#/definitions/SortOrder" + }, + { + "$ref": "#/definitions/ChannelDomainSort" + } + ], + "description": "Either applies a transform to sort the mark’s index by the specified channel values, or imputes ordinal scale domains from this mark’s channels.\n\nWhen imputing ordinal scale domains from channel values, the **sort** option is an object whose keys are ordinal scale names such as *x* or *fx*, and whose values are channel names such as *y*, *y1*, or *y2*. For example, to impute the *y* scale’s domain from the associated *x* channel values in ascending order:\n\n```js sort: {y: \"x\"} ```\n\nFor different sort options for different scales, replace the channel name with a *value* object and per-scale options:\n\n```js sort: {y: {value: \"-x\"}} ```\n\nWhen sorting the mark’s index, the **sort** option is instead one of:\n\n- a channel value definition for sorting given values in ascending order\n- a {value, order} object for sorting given values\n- a {channel, order} object for sorting the named channel’s values" + }, + "stroke": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke" + }, + "strokeDasharray": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dasharray][1]; a constant number indicating the length in pixels of alternating dashes and gaps, or a constant string of numbers separated by spaces or commas (_e.g._, *10 2* for dashes of 10 pixels separated by gaps of 2 pixels), or *none* (the default) for no dashing\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dasharray" + }, + "strokeDashoffset": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dashoffset][1]; a constant indicating the offset in pixels of the first dash along the stroke; defaults to zero.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dashoffset" + }, + "strokeLinecap": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linecap][1]; a constant specifying how to cap stroked paths, such as *butt*, *round*, or *square*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linecap" + }, + "strokeLinejoin": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linejoin][1]; a constant specifying how to join stroked paths, such as *bevel*, *miter*, *miter-clip*, or *round*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linejoin" + }, + "strokeMiterlimit": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-miterlimit][1]; a constant number specifying how to limit the length of *miter* joins on stroked paths.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-miterlimit" + }, + "strokeOpacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-opacity" + }, + "strokeWidth": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-width][1]; a constant number in pixels, or a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-width" + }, + "target": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [target][1]; a constant string specifying the target window (_e.g._,\n*_blank*) for clickable links; used in conjunction with the **href** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/target" + }, + "tip": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/TipPointer" + }, + { + "properties": { + "anchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The tip anchor specifies how to orient the tip box relative to its anchor position; it refers to the part of the tip box that is attached to the anchor point. For example, the *top-left* anchor places the top-left corner of tip box near the anchor position, hence placing the tip box below and to the right of the anchor position." + }, + "fontFamily": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font-family][1]; a constant; defaults to the plot’s font family, which is typically [*system-ui*][2].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-family [2]: https://drafts.csswg.org/css-fonts-4/#valdef-font-family-system-ui" + }, + "fontSize": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font size][1] in pixels; either a constant or a channel; defaults to the plot’s font size, which is typically 10. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-size" + }, + "fontStyle": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font style][1]; a constant; defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-style" + }, + "fontVariant": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font variant][1]; a constant; if the **text** channel contains numbers or dates, defaults to *tabular-nums* to facilitate comparing numbers; otherwise defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant" + }, + "fontWeight": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font weight][1]; a constant; defaults to the plot’s font weight, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight" + }, + "format": { + "additionalProperties": false, + "description": "How channel values are formatted for display. If a format is a string, it is interpreted as a (UTC) time format for temporal channels, and otherwise a number format.", + "properties": { + "ariaLabel": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fill": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fillOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fontSize": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fx": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fy": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "geometry": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "height": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "href": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "length": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "opacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "path": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "r": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "rotate": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "src": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "stroke": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeWidth": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "symbol": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "text": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "title": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "weight": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "width": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "z": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + } + }, + "type": "object" + }, + "frameAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The frame anchor specifies defaults for **x** and **y** based on the plot’s frame; it may be one of the four sides (*top*, *right*, *bottom*, *left*), one of the four corners (*top-left*, *top-right*, *bottom-right*,\n*bottom-left*), or the *middle* of the frame. For example, for tips distributed horizontally at the top of the frame:\n\n```js Plot.tip(data, {x: \"date\", frameAnchor: \"top\"}) ```" + }, + "lineHeight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line height in ems; defaults to 1. The line height affects the (typically vertical) separation between adjacent baselines of text, as well as the separation between the text and its anchor point." + }, + "lineWidth": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line width in ems (e.g., 10 for about 20 characters); defaults to infinity, disabling wrapping and clipping.\n\nIf **textOverflow** is null, lines will be wrapped at the specified length. If a line is split at a soft hyphen (\\xad), a hyphen (-) will be displayed at the end of the line. If **textOverflow** is not null, lines will be clipped according to the given strategy." + }, + "monospace": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, changes the default **fontFamily** to *monospace*, and uses simplified monospaced text metrics calculations." + }, + "pathFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The image filter for the tip’s box; defaults to a drop shadow." + }, + "pointer": { + "$ref": "#/definitions/TipPointer" + }, + "pointerSize": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The size of the tip’s pointer in pixels; defaults to 12." + }, + "preferredAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If an explicit tip anchor is not specified, an anchor is chosen automatically such that the tip fits within the plot’s frame; if the preferred anchor fits, it is chosen." + }, + "textAnchor": { + "anyOf": [ + { + "const": "start", + "type": "string" + }, + { + "const": "middle", + "type": "string" + }, + { + "const": "end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [text anchor][1] controls how text is aligned (typically horizontally) relative to its anchor point; it is one of *start*, *end*, or *middle*. If the frame anchor is *left*, *top-left*, or *bottom-left*, the default text anchor is *start*; if the frame anchor is *right*, *top-right*, or\n*bottom-right*, the default is *end*; otherwise it is *middle*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/text-anchor" + }, + "textOverflow": { + "anyOf": [ + { + "type": "null" + }, + { + "const": "clip", + "type": "string" + }, + { + "const": "ellipsis", + "type": "string" + }, + { + "const": "clip-start", + "type": "string" + }, + { + "const": "clip-end", + "type": "string" + }, + { + "const": "ellipsis-start", + "type": "string" + }, + { + "const": "ellipsis-middle", + "type": "string" + }, + { + "const": "ellipsis-end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How truncate (or wrap) lines of text longer than the given **lineWidth**; one of:\n\n- null (default) - preserve overflowing characters (and wrap if needed)\n- *clip* or *clip-end* - remove characters from the end\n- *clip-start* - remove characters from the start\n- *ellipsis* or *ellipsis-end* - replace characters from the end with an ellipsis (…)\n- *ellipsis-start* - replace characters from the start with an ellipsis (…)\n- *ellipsis-middle* - replace characters from the middle with an ellipsis (…)\n\nIf no **title** was specified, if text requires truncation, a title containing the non-truncated text will be implicitly added." + }, + "textPadding": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The padding around the text in pixels; defaults to 8." + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + } + }, + "type": "object" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to generate a tooltip for this mark, and any tip options." + }, + "title": { + "$ref": "#/definitions/ChannelValue", + "description": "The title; a channel specifying accessible, short textual descriptions as strings (possibly with newlines). If the tip option is specified, the title will be displayed with an interactive tooltip instead of using the SVG [title element][1].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/title" + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position of the cell; an optional ordinal channel typically bound to the *x* scale. If not specified, the cell spans the horizontal extent of the frame; otherwise the *x* scale must be a *band* scale.\n\nIf *x* represents quantitative or temporal values, use a barX mark instead; if *y* is also quantitative or temporal, use a rect mark." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position of the cell; an optional ordinal channel typically bound to the *y* scale. If not specified, the cell spans the vertical extent of the frame; otherwise the *y* scale must be a *band* scale.\n\nIf *y* represents quantitative or temporal values, use a barY mark instead; if *x* is also quantitative or temporal, use a rect mark." + } + }, + "required": [ + "data", + "mark" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "$schema": { + "description": "A [JSON schema](http://json-schema.org/) URL for this specification, such as https://uwdata.github.io/mosaic/schema/latest.json. This property enables validation and autocomplete in editors with JSON schema support.", + "format": "uri", + "type": "string" + }, + "ariaDescription": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-description][1]; a constant textual description.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-description" + }, + "ariaHidden": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-hidden][1] state; a constant indicating whether the element is exposed to an accessibility API.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-hidden" + }, + "ariaLabel": { + "$ref": "#/definitions/ChannelValue", + "description": "The [aria-label][1]; a channel specifying short textual labels representing the value in the accessibility tree.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-label" + }, + "clip": { + "anyOf": [ + { + "const": "frame", + "type": "string" + }, + { + "const": "sphere", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to clip the mark; one of:\n\n- *frame* or true - clip to the plot’s frame (inner area)\n- *sphere* - clip to the projected sphere (*e.g.*, front hemisphere)\n- null or false - do not clip\n\nThe *sphere* clip option requires a geographic projection." + }, + "config": { + "$ref": "#/definitions/Config", + "description": "Configuration options." + }, + "data": { + "$ref": "#/definitions/Data", + "description": "Dataset definitions." + }, + "dx": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The horizontal offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "dy": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The vertical offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "facet": { + "anyOf": [ + { + "const": "auto", + "type": "string" + }, + { + "const": "include", + "type": "string" + }, + { + "const": "exclude", + "type": "string" + }, + { + "const": "super", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to enable or disable faceting; one of:\n\n- *auto* (default) - automatically determine if this mark should be faceted\n- *include* (or true) - draw the subset of the mark’s data in the current facet\n- *exclude* - draw the subset of the mark’s data *not* in the current facet\n- *super* - draw this mark in a single frame that covers all facets\n- null (or false) - repeat this mark’s data across all facets (*i.e.*, no faceting)\n\nWhen a mark uses *super* faceting, it is not allowed to use position scales (*x*, *y*, *fx*, or *fy*); *super* faceting is intended for decorations, such as labels and legends.\n\nWhen top-level faceting is used, the default *auto* setting is equivalent to *include* when the mark data is strictly equal to the top-level facet data; otherwise it is equivalent to null. When the *include* or *exclude* facet mode is chosen, the mark data must be parallel to the top-level facet data: the data must have the same length and order. If the data are not parallel, then the wrong data may be shown in each facet. The default\n*auto* therefore requires strict equality (`===`) for safety, and using the facet data as mark data is recommended when using the *exclude* facet mode. (To construct parallel data safely, consider using [*array*.map][1] on the facet data.)\n\nWhen mark-level faceting is used, the default *auto* setting is equivalent to *include*: the mark will be faceted if either the **fx** or **fy** channel option (or both) is specified. The null or false option will disable faceting, while *exclude* draws the subset of the mark’s data *not* in the current facet.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map" + }, + "facetAnchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "right", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "const": "left", + "type": "string" + }, + { + "const": "top-left", + "type": "string" + }, + { + "const": "top-right", + "type": "string" + }, + { + "const": "bottom-left", + "type": "string" + }, + { + "const": "bottom-right", + "type": "string" + }, + { + "const": "top-empty", + "type": "string" + }, + { + "const": "right-empty", + "type": "string" + }, + { + "const": "bottom-empty", + "type": "string" + }, + { + "const": "left-empty", + "type": "string" + }, + { + "const": "empty", + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to place the mark with respect to facets; one of:\n\n- null (default for most marks) - display the mark in each non-empty facet\n- *top*, *right*, *bottom*, or *left* - display the mark only in facets on the given side\n- *top-empty*, *right-empty*, *bottom-empty*, or *left-empty* (default for axis marks) - display the mark only in facets that have empty space on the given side: either the margin, or an empty facet\n- *empty* - display the mark in empty facets only" + }, + "fill": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill" + }, + "fillOpacity": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill-opacity][1]; a constant number between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill-opacity" + }, + "filter": { + "$ref": "#/definitions/ChannelValue", + "description": "Applies a transform to filter the mark’s index according to the given channel values; only truthy values are retained.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "fx": { + "$ref": "#/definitions/ChannelValue", + "description": "The horizontal facet position channel, for mark-level faceting, bound to the *fx* scale." + }, + "fy": { + "$ref": "#/definitions/ChannelValue", + "description": "The vertical facet position channel, for mark-level faceting, bound to the\n*fy* scale." + }, + "href": { + "$ref": "#/definitions/ChannelValue", + "description": "The [href][1]; a channel specifying URLs for clickable links. May be used in conjunction with the **target** option to open links in another window.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/href" + }, + "imageFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A CSS [filter][1]; a constant string used to adjust the rendering of images, such as *blur(5px)*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/filter" + }, + "inset": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four insets: **insetTop**,\n**insetRight**, **insetBottom**, and **insetLeft**. All insets typically default to zero, though not always (say when using bin transform). A positive inset reduces effective area, while a negative inset increases it." + }, + "insetBottom": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Insets the bottom edge by the specified number of pixels. A positive value insets towards the top edge (reducing effective area), while a negative value insets away from the top edge (increasing it)." + }, + "insetLeft": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Insets the left edge by the specified number of pixels. A positive value insets towards the right edge (reducing effective area), while a negative value insets away from the right edge (increasing it)." + }, + "insetRight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Insets the right edge by the specified number of pixels. A positive value insets towards the left edge (reducing effective area), while a negative value insets away from the left edge (increasing it)." + }, + "insetTop": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Insets the top edge by the specified number of pixels. A positive value insets towards the bottom edge (reducing effective area), while a negative value insets away from the bottom edge (increasing it)." + }, + "margin": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four mark margins: **marginTop**,\n**marginRight**, **marginBottom**, and **marginLeft**; typically defaults to 0, except for axis marks." + }, + "marginBottom": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s bottom margin; the minimum distance in pixels between the bottom edges of the inner and outer plot area." + }, + "marginLeft": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s left margin; the minimum distance in pixels between the left edges of the inner and outer plot area." + }, + "marginRight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s right margin; the minimum distance in pixels between the right edges of the mark’s inner and outer plot area." + }, + "marginTop": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s top margin; the minimum distance in pixels between the top edges of the inner and outer plot area." + }, + "mark": { + "const": "cellX", + "description": "Like cell, but **x** defaults to the zero-based index [0, 1, 2, …], and if\n**stroke** is not a channel, **fill** defaults to the identity function, assuming that *data* = [*x₀*, *x₁*, *x₂*, …].", + "type": "string" + }, + "meta": { + "$ref": "#/definitions/Meta", + "description": "Specification metadata." + }, + "mixBlendMode": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [mix-blend-mode][1]; a constant string specifying how to blend content such as *multiply*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode" + }, + "opacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally. For faster rendering, prefer the **strokeOpacity** or **fillOpacity** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/opacity" + }, + "paintOrder": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [paint-order][1]; a constant string specifying the order in which the\n**fill**, **stroke**, and any markers are drawn; defaults to *normal*, which draws the fill, then stroke, then markers; defaults to *stroke* for the text mark to create a “halo” around text to improve legibility.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/paint-order" + }, + "params": { + "$ref": "#/definitions/Params", + "description": "Param and Selection definitions." + }, + "plotDefaults": { + "$ref": "#/definitions/PlotAttributes", + "description": "A default set of attributes to apply to all plot components." + }, + "pointerEvents": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [pointer-events][1] property; a constant string such as *none*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/pointer-events" + }, + "reverse": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Applies a transform to reverse the order of the mark’s index, say for reverse input order." + }, + "rx": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The rounded corner [*x*-radius][1], either in pixels or as a percentage of the rect width. If **rx** is not specified, it defaults to **ry** if present, and otherwise draws square corners.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/rx" + }, + "ry": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The rounded corner [*y*-radius][1], either in pixels or as a percentage of the rect height. If **ry** is not specified, it defaults to **rx** if present, and otherwise draws square corners.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/ry" + }, + "select": { + "$ref": "#/definitions/SelectFilter", + "description": "Applies a filter transform after data is loaded to highlight selected values only. For example, `first` and `last` select the first or last values of series only (using the *z* channel to separate series). Meanwhile, `nearestX` and `nearestY` select the point nearest to the pointer along the *x* or *y* channel dimension. Unlike Mosaic selections, a mark level *select* is internal to the mark only, and does not populate a param or selection value to be shared across clients.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "shapeRendering": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [shape-rendering][1]; a constant string such as *crispEdges*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/shape-rendering" + }, + "sort": { + "anyOf": [ + { + "$ref": "#/definitions/SortOrder" + }, + { + "$ref": "#/definitions/ChannelDomainSort" + } + ], + "description": "Either applies a transform to sort the mark’s index by the specified channel values, or imputes ordinal scale domains from this mark’s channels.\n\nWhen imputing ordinal scale domains from channel values, the **sort** option is an object whose keys are ordinal scale names such as *x* or *fx*, and whose values are channel names such as *y*, *y1*, or *y2*. For example, to impute the *y* scale’s domain from the associated *x* channel values in ascending order:\n\n```js sort: {y: \"x\"} ```\n\nFor different sort options for different scales, replace the channel name with a *value* object and per-scale options:\n\n```js sort: {y: {value: \"-x\"}} ```\n\nWhen sorting the mark’s index, the **sort** option is instead one of:\n\n- a channel value definition for sorting given values in ascending order\n- a {value, order} object for sorting given values\n- a {channel, order} object for sorting the named channel’s values" + }, + "stroke": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke" + }, + "strokeDasharray": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dasharray][1]; a constant number indicating the length in pixels of alternating dashes and gaps, or a constant string of numbers separated by spaces or commas (_e.g._, *10 2* for dashes of 10 pixels separated by gaps of 2 pixels), or *none* (the default) for no dashing\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dasharray" + }, + "strokeDashoffset": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dashoffset][1]; a constant indicating the offset in pixels of the first dash along the stroke; defaults to zero.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dashoffset" + }, + "strokeLinecap": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linecap][1]; a constant specifying how to cap stroked paths, such as *butt*, *round*, or *square*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linecap" + }, + "strokeLinejoin": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linejoin][1]; a constant specifying how to join stroked paths, such as *bevel*, *miter*, *miter-clip*, or *round*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linejoin" + }, + "strokeMiterlimit": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-miterlimit][1]; a constant number specifying how to limit the length of *miter* joins on stroked paths.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-miterlimit" + }, + "strokeOpacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-opacity" + }, + "strokeWidth": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-width][1]; a constant number in pixels, or a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-width" + }, + "target": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [target][1]; a constant string specifying the target window (_e.g._,\n*_blank*) for clickable links; used in conjunction with the **href** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/target" + }, + "tip": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/TipPointer" + }, + { + "properties": { + "anchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The tip anchor specifies how to orient the tip box relative to its anchor position; it refers to the part of the tip box that is attached to the anchor point. For example, the *top-left* anchor places the top-left corner of tip box near the anchor position, hence placing the tip box below and to the right of the anchor position." + }, + "fontFamily": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font-family][1]; a constant; defaults to the plot’s font family, which is typically [*system-ui*][2].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-family [2]: https://drafts.csswg.org/css-fonts-4/#valdef-font-family-system-ui" + }, + "fontSize": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font size][1] in pixels; either a constant or a channel; defaults to the plot’s font size, which is typically 10. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-size" + }, + "fontStyle": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font style][1]; a constant; defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-style" + }, + "fontVariant": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font variant][1]; a constant; if the **text** channel contains numbers or dates, defaults to *tabular-nums* to facilitate comparing numbers; otherwise defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant" + }, + "fontWeight": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font weight][1]; a constant; defaults to the plot’s font weight, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight" + }, + "format": { + "additionalProperties": false, + "description": "How channel values are formatted for display. If a format is a string, it is interpreted as a (UTC) time format for temporal channels, and otherwise a number format.", + "properties": { + "ariaLabel": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fill": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fillOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fontSize": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fx": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fy": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "geometry": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "height": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "href": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "length": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "opacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "path": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "r": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "rotate": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "src": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "stroke": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeWidth": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "symbol": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "text": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "title": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "weight": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "width": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "z": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + } + }, + "type": "object" + }, + "frameAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The frame anchor specifies defaults for **x** and **y** based on the plot’s frame; it may be one of the four sides (*top*, *right*, *bottom*, *left*), one of the four corners (*top-left*, *top-right*, *bottom-right*,\n*bottom-left*), or the *middle* of the frame. For example, for tips distributed horizontally at the top of the frame:\n\n```js Plot.tip(data, {x: \"date\", frameAnchor: \"top\"}) ```" + }, + "lineHeight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line height in ems; defaults to 1. The line height affects the (typically vertical) separation between adjacent baselines of text, as well as the separation between the text and its anchor point." + }, + "lineWidth": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line width in ems (e.g., 10 for about 20 characters); defaults to infinity, disabling wrapping and clipping.\n\nIf **textOverflow** is null, lines will be wrapped at the specified length. If a line is split at a soft hyphen (\\xad), a hyphen (-) will be displayed at the end of the line. If **textOverflow** is not null, lines will be clipped according to the given strategy." + }, + "monospace": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, changes the default **fontFamily** to *monospace*, and uses simplified monospaced text metrics calculations." + }, + "pathFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The image filter for the tip’s box; defaults to a drop shadow." + }, + "pointer": { + "$ref": "#/definitions/TipPointer" + }, + "pointerSize": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The size of the tip’s pointer in pixels; defaults to 12." + }, + "preferredAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If an explicit tip anchor is not specified, an anchor is chosen automatically such that the tip fits within the plot’s frame; if the preferred anchor fits, it is chosen." + }, + "textAnchor": { + "anyOf": [ + { + "const": "start", + "type": "string" + }, + { + "const": "middle", + "type": "string" + }, + { + "const": "end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [text anchor][1] controls how text is aligned (typically horizontally) relative to its anchor point; it is one of *start*, *end*, or *middle*. If the frame anchor is *left*, *top-left*, or *bottom-left*, the default text anchor is *start*; if the frame anchor is *right*, *top-right*, or\n*bottom-right*, the default is *end*; otherwise it is *middle*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/text-anchor" + }, + "textOverflow": { + "anyOf": [ + { + "type": "null" + }, + { + "const": "clip", + "type": "string" + }, + { + "const": "ellipsis", + "type": "string" + }, + { + "const": "clip-start", + "type": "string" + }, + { + "const": "clip-end", + "type": "string" + }, + { + "const": "ellipsis-start", + "type": "string" + }, + { + "const": "ellipsis-middle", + "type": "string" + }, + { + "const": "ellipsis-end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How truncate (or wrap) lines of text longer than the given **lineWidth**; one of:\n\n- null (default) - preserve overflowing characters (and wrap if needed)\n- *clip* or *clip-end* - remove characters from the end\n- *clip-start* - remove characters from the start\n- *ellipsis* or *ellipsis-end* - replace characters from the end with an ellipsis (…)\n- *ellipsis-start* - replace characters from the start with an ellipsis (…)\n- *ellipsis-middle* - replace characters from the middle with an ellipsis (…)\n\nIf no **title** was specified, if text requires truncation, a title containing the non-truncated text will be implicitly added." + }, + "textPadding": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The padding around the text in pixels; defaults to 8." + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + } + }, + "type": "object" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to generate a tooltip for this mark, and any tip options." + }, + "title": { + "$ref": "#/definitions/ChannelValue", + "description": "The title; a channel specifying accessible, short textual descriptions as strings (possibly with newlines). If the tip option is specified, the title will be displayed with an interactive tooltip instead of using the SVG [title element][1].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/title" + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position of the cell; an optional ordinal channel typically bound to the *x* scale. If not specified, the cell spans the horizontal extent of the frame; otherwise the *x* scale must be a *band* scale.\n\nIf *x* represents quantitative or temporal values, use a barX mark instead; if *y* is also quantitative or temporal, use a rect mark." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position of the cell; an optional ordinal channel typically bound to the *y* scale. If not specified, the cell spans the vertical extent of the frame; otherwise the *y* scale must be a *band* scale.\n\nIf *y* represents quantitative or temporal values, use a barY mark instead; if *x* is also quantitative or temporal, use a rect mark." + } + }, + "required": [ + "data", + "mark" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "$schema": { + "description": "A [JSON schema](http://json-schema.org/) URL for this specification, such as https://uwdata.github.io/mosaic/schema/latest.json. This property enables validation and autocomplete in editors with JSON schema support.", + "format": "uri", + "type": "string" + }, + "ariaDescription": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-description][1]; a constant textual description.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-description" + }, + "ariaHidden": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-hidden][1] state; a constant indicating whether the element is exposed to an accessibility API.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-hidden" + }, + "ariaLabel": { + "$ref": "#/definitions/ChannelValue", + "description": "The [aria-label][1]; a channel specifying short textual labels representing the value in the accessibility tree.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-label" + }, + "clip": { + "anyOf": [ + { + "const": "frame", + "type": "string" + }, + { + "const": "sphere", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to clip the mark; one of:\n\n- *frame* or true - clip to the plot’s frame (inner area)\n- *sphere* - clip to the projected sphere (*e.g.*, front hemisphere)\n- null or false - do not clip\n\nThe *sphere* clip option requires a geographic projection." + }, + "config": { + "$ref": "#/definitions/Config", + "description": "Configuration options." + }, + "data": { + "$ref": "#/definitions/Data", + "description": "Dataset definitions." + }, + "dx": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The horizontal offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "dy": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The vertical offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "facet": { + "anyOf": [ + { + "const": "auto", + "type": "string" + }, + { + "const": "include", + "type": "string" + }, + { + "const": "exclude", + "type": "string" + }, + { + "const": "super", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to enable or disable faceting; one of:\n\n- *auto* (default) - automatically determine if this mark should be faceted\n- *include* (or true) - draw the subset of the mark’s data in the current facet\n- *exclude* - draw the subset of the mark’s data *not* in the current facet\n- *super* - draw this mark in a single frame that covers all facets\n- null (or false) - repeat this mark’s data across all facets (*i.e.*, no faceting)\n\nWhen a mark uses *super* faceting, it is not allowed to use position scales (*x*, *y*, *fx*, or *fy*); *super* faceting is intended for decorations, such as labels and legends.\n\nWhen top-level faceting is used, the default *auto* setting is equivalent to *include* when the mark data is strictly equal to the top-level facet data; otherwise it is equivalent to null. When the *include* or *exclude* facet mode is chosen, the mark data must be parallel to the top-level facet data: the data must have the same length and order. If the data are not parallel, then the wrong data may be shown in each facet. The default\n*auto* therefore requires strict equality (`===`) for safety, and using the facet data as mark data is recommended when using the *exclude* facet mode. (To construct parallel data safely, consider using [*array*.map][1] on the facet data.)\n\nWhen mark-level faceting is used, the default *auto* setting is equivalent to *include*: the mark will be faceted if either the **fx** or **fy** channel option (or both) is specified. The null or false option will disable faceting, while *exclude* draws the subset of the mark’s data *not* in the current facet.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map" + }, + "facetAnchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "right", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "const": "left", + "type": "string" + }, + { + "const": "top-left", + "type": "string" + }, + { + "const": "top-right", + "type": "string" + }, + { + "const": "bottom-left", + "type": "string" + }, + { + "const": "bottom-right", + "type": "string" + }, + { + "const": "top-empty", + "type": "string" + }, + { + "const": "right-empty", + "type": "string" + }, + { + "const": "bottom-empty", + "type": "string" + }, + { + "const": "left-empty", + "type": "string" + }, + { + "const": "empty", + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to place the mark with respect to facets; one of:\n\n- null (default for most marks) - display the mark in each non-empty facet\n- *top*, *right*, *bottom*, or *left* - display the mark only in facets on the given side\n- *top-empty*, *right-empty*, *bottom-empty*, or *left-empty* (default for axis marks) - display the mark only in facets that have empty space on the given side: either the margin, or an empty facet\n- *empty* - display the mark in empty facets only" + }, + "fill": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill" + }, + "fillOpacity": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill-opacity][1]; a constant number between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill-opacity" + }, + "filter": { + "$ref": "#/definitions/ChannelValue", + "description": "Applies a transform to filter the mark’s index according to the given channel values; only truthy values are retained.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "fx": { + "$ref": "#/definitions/ChannelValue", + "description": "The horizontal facet position channel, for mark-level faceting, bound to the *fx* scale." + }, + "fy": { + "$ref": "#/definitions/ChannelValue", + "description": "The vertical facet position channel, for mark-level faceting, bound to the\n*fy* scale." + }, + "href": { + "$ref": "#/definitions/ChannelValue", + "description": "The [href][1]; a channel specifying URLs for clickable links. May be used in conjunction with the **target** option to open links in another window.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/href" + }, + "imageFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A CSS [filter][1]; a constant string used to adjust the rendering of images, such as *blur(5px)*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/filter" + }, + "inset": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four insets: **insetTop**,\n**insetRight**, **insetBottom**, and **insetLeft**. All insets typically default to zero, though not always (say when using bin transform). A positive inset reduces effective area, while a negative inset increases it." + }, + "insetBottom": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Insets the bottom edge by the specified number of pixels. A positive value insets towards the top edge (reducing effective area), while a negative value insets away from the top edge (increasing it)." + }, + "insetLeft": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Insets the left edge by the specified number of pixels. A positive value insets towards the right edge (reducing effective area), while a negative value insets away from the right edge (increasing it)." + }, + "insetRight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Insets the right edge by the specified number of pixels. A positive value insets towards the left edge (reducing effective area), while a negative value insets away from the left edge (increasing it)." + }, + "insetTop": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Insets the top edge by the specified number of pixels. A positive value insets towards the bottom edge (reducing effective area), while a negative value insets away from the bottom edge (increasing it)." + }, + "margin": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four mark margins: **marginTop**,\n**marginRight**, **marginBottom**, and **marginLeft**; typically defaults to 0, except for axis marks." + }, + "marginBottom": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s bottom margin; the minimum distance in pixels between the bottom edges of the inner and outer plot area." + }, + "marginLeft": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s left margin; the minimum distance in pixels between the left edges of the inner and outer plot area." + }, + "marginRight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s right margin; the minimum distance in pixels between the right edges of the mark’s inner and outer plot area." + }, + "marginTop": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s top margin; the minimum distance in pixels between the top edges of the inner and outer plot area." + }, + "mark": { + "const": "cellY", + "description": "Like cell, but **y** defaults to the zero-based index [0, 1, 2, …], and if\n**stroke** is not a channel, **fill** defaults to the identity function, assuming that *data* = [*y₀*, *y₁*, *y₂*, …].", + "type": "string" + }, + "meta": { + "$ref": "#/definitions/Meta", + "description": "Specification metadata." + }, + "mixBlendMode": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [mix-blend-mode][1]; a constant string specifying how to blend content such as *multiply*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode" + }, + "opacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally. For faster rendering, prefer the **strokeOpacity** or **fillOpacity** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/opacity" + }, + "paintOrder": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [paint-order][1]; a constant string specifying the order in which the\n**fill**, **stroke**, and any markers are drawn; defaults to *normal*, which draws the fill, then stroke, then markers; defaults to *stroke* for the text mark to create a “halo” around text to improve legibility.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/paint-order" + }, + "params": { + "$ref": "#/definitions/Params", + "description": "Param and Selection definitions." + }, + "plotDefaults": { + "$ref": "#/definitions/PlotAttributes", + "description": "A default set of attributes to apply to all plot components." + }, + "pointerEvents": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [pointer-events][1] property; a constant string such as *none*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/pointer-events" + }, + "reverse": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Applies a transform to reverse the order of the mark’s index, say for reverse input order." + }, + "rx": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The rounded corner [*x*-radius][1], either in pixels or as a percentage of the rect width. If **rx** is not specified, it defaults to **ry** if present, and otherwise draws square corners.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/rx" + }, + "ry": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The rounded corner [*y*-radius][1], either in pixels or as a percentage of the rect height. If **ry** is not specified, it defaults to **rx** if present, and otherwise draws square corners.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/ry" + }, + "select": { + "$ref": "#/definitions/SelectFilter", + "description": "Applies a filter transform after data is loaded to highlight selected values only. For example, `first` and `last` select the first or last values of series only (using the *z* channel to separate series). Meanwhile, `nearestX` and `nearestY` select the point nearest to the pointer along the *x* or *y* channel dimension. Unlike Mosaic selections, a mark level *select* is internal to the mark only, and does not populate a param or selection value to be shared across clients.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "shapeRendering": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [shape-rendering][1]; a constant string such as *crispEdges*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/shape-rendering" + }, + "sort": { + "anyOf": [ + { + "$ref": "#/definitions/SortOrder" + }, + { + "$ref": "#/definitions/ChannelDomainSort" + } + ], + "description": "Either applies a transform to sort the mark’s index by the specified channel values, or imputes ordinal scale domains from this mark’s channels.\n\nWhen imputing ordinal scale domains from channel values, the **sort** option is an object whose keys are ordinal scale names such as *x* or *fx*, and whose values are channel names such as *y*, *y1*, or *y2*. For example, to impute the *y* scale’s domain from the associated *x* channel values in ascending order:\n\n```js sort: {y: \"x\"} ```\n\nFor different sort options for different scales, replace the channel name with a *value* object and per-scale options:\n\n```js sort: {y: {value: \"-x\"}} ```\n\nWhen sorting the mark’s index, the **sort** option is instead one of:\n\n- a channel value definition for sorting given values in ascending order\n- a {value, order} object for sorting given values\n- a {channel, order} object for sorting the named channel’s values" + }, + "stroke": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke" + }, + "strokeDasharray": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dasharray][1]; a constant number indicating the length in pixels of alternating dashes and gaps, or a constant string of numbers separated by spaces or commas (_e.g._, *10 2* for dashes of 10 pixels separated by gaps of 2 pixels), or *none* (the default) for no dashing\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dasharray" + }, + "strokeDashoffset": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dashoffset][1]; a constant indicating the offset in pixels of the first dash along the stroke; defaults to zero.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dashoffset" + }, + "strokeLinecap": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linecap][1]; a constant specifying how to cap stroked paths, such as *butt*, *round*, or *square*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linecap" + }, + "strokeLinejoin": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linejoin][1]; a constant specifying how to join stroked paths, such as *bevel*, *miter*, *miter-clip*, or *round*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linejoin" + }, + "strokeMiterlimit": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-miterlimit][1]; a constant number specifying how to limit the length of *miter* joins on stroked paths.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-miterlimit" + }, + "strokeOpacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-opacity" + }, + "strokeWidth": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-width][1]; a constant number in pixels, or a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-width" + }, + "target": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [target][1]; a constant string specifying the target window (_e.g._,\n*_blank*) for clickable links; used in conjunction with the **href** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/target" + }, + "tip": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/TipPointer" + }, + { + "properties": { + "anchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The tip anchor specifies how to orient the tip box relative to its anchor position; it refers to the part of the tip box that is attached to the anchor point. For example, the *top-left* anchor places the top-left corner of tip box near the anchor position, hence placing the tip box below and to the right of the anchor position." + }, + "fontFamily": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font-family][1]; a constant; defaults to the plot’s font family, which is typically [*system-ui*][2].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-family [2]: https://drafts.csswg.org/css-fonts-4/#valdef-font-family-system-ui" + }, + "fontSize": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font size][1] in pixels; either a constant or a channel; defaults to the plot’s font size, which is typically 10. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-size" + }, + "fontStyle": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font style][1]; a constant; defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-style" + }, + "fontVariant": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font variant][1]; a constant; if the **text** channel contains numbers or dates, defaults to *tabular-nums* to facilitate comparing numbers; otherwise defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant" + }, + "fontWeight": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font weight][1]; a constant; defaults to the plot’s font weight, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight" + }, + "format": { + "additionalProperties": false, + "description": "How channel values are formatted for display. If a format is a string, it is interpreted as a (UTC) time format for temporal channels, and otherwise a number format.", + "properties": { + "ariaLabel": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fill": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fillOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fontSize": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fx": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fy": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "geometry": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "height": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "href": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "length": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "opacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "path": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "r": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "rotate": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "src": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "stroke": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeWidth": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "symbol": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "text": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "title": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "weight": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "width": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "z": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + } + }, + "type": "object" + }, + "frameAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The frame anchor specifies defaults for **x** and **y** based on the plot’s frame; it may be one of the four sides (*top*, *right*, *bottom*, *left*), one of the four corners (*top-left*, *top-right*, *bottom-right*,\n*bottom-left*), or the *middle* of the frame. For example, for tips distributed horizontally at the top of the frame:\n\n```js Plot.tip(data, {x: \"date\", frameAnchor: \"top\"}) ```" + }, + "lineHeight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line height in ems; defaults to 1. The line height affects the (typically vertical) separation between adjacent baselines of text, as well as the separation between the text and its anchor point." + }, + "lineWidth": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line width in ems (e.g., 10 for about 20 characters); defaults to infinity, disabling wrapping and clipping.\n\nIf **textOverflow** is null, lines will be wrapped at the specified length. If a line is split at a soft hyphen (\\xad), a hyphen (-) will be displayed at the end of the line. If **textOverflow** is not null, lines will be clipped according to the given strategy." + }, + "monospace": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, changes the default **fontFamily** to *monospace*, and uses simplified monospaced text metrics calculations." + }, + "pathFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The image filter for the tip’s box; defaults to a drop shadow." + }, + "pointer": { + "$ref": "#/definitions/TipPointer" + }, + "pointerSize": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The size of the tip’s pointer in pixels; defaults to 12." + }, + "preferredAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If an explicit tip anchor is not specified, an anchor is chosen automatically such that the tip fits within the plot’s frame; if the preferred anchor fits, it is chosen." + }, + "textAnchor": { + "anyOf": [ + { + "const": "start", + "type": "string" + }, + { + "const": "middle", + "type": "string" + }, + { + "const": "end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [text anchor][1] controls how text is aligned (typically horizontally) relative to its anchor point; it is one of *start*, *end*, or *middle*. If the frame anchor is *left*, *top-left*, or *bottom-left*, the default text anchor is *start*; if the frame anchor is *right*, *top-right*, or\n*bottom-right*, the default is *end*; otherwise it is *middle*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/text-anchor" + }, + "textOverflow": { + "anyOf": [ + { + "type": "null" + }, + { + "const": "clip", + "type": "string" + }, + { + "const": "ellipsis", + "type": "string" + }, + { + "const": "clip-start", + "type": "string" + }, + { + "const": "clip-end", + "type": "string" + }, + { + "const": "ellipsis-start", + "type": "string" + }, + { + "const": "ellipsis-middle", + "type": "string" + }, + { + "const": "ellipsis-end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How truncate (or wrap) lines of text longer than the given **lineWidth**; one of:\n\n- null (default) - preserve overflowing characters (and wrap if needed)\n- *clip* or *clip-end* - remove characters from the end\n- *clip-start* - remove characters from the start\n- *ellipsis* or *ellipsis-end* - replace characters from the end with an ellipsis (…)\n- *ellipsis-start* - replace characters from the start with an ellipsis (…)\n- *ellipsis-middle* - replace characters from the middle with an ellipsis (…)\n\nIf no **title** was specified, if text requires truncation, a title containing the non-truncated text will be implicitly added." + }, + "textPadding": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The padding around the text in pixels; defaults to 8." + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + } + }, + "type": "object" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to generate a tooltip for this mark, and any tip options." + }, + "title": { + "$ref": "#/definitions/ChannelValue", + "description": "The title; a channel specifying accessible, short textual descriptions as strings (possibly with newlines). If the tip option is specified, the title will be displayed with an interactive tooltip instead of using the SVG [title element][1].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/title" + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position of the cell; an optional ordinal channel typically bound to the *x* scale. If not specified, the cell spans the horizontal extent of the frame; otherwise the *x* scale must be a *band* scale.\n\nIf *x* represents quantitative or temporal values, use a barX mark instead; if *y* is also quantitative or temporal, use a rect mark." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position of the cell; an optional ordinal channel typically bound to the *y* scale. If not specified, the cell spans the vertical extent of the frame; otherwise the *y* scale must be a *band* scale.\n\nIf *y* represents quantitative or temporal values, use a barY mark instead; if *x* is also quantitative or temporal, use a rect mark." + } + }, + "required": [ + "data", + "mark" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "$schema": { + "description": "A [JSON schema](http://json-schema.org/) URL for this specification, such as https://uwdata.github.io/mosaic/schema/latest.json. This property enables validation and autocomplete in editors with JSON schema support.", + "format": "uri", + "type": "string" + }, + "ariaDescription": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-description][1]; a constant textual description.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-description" + }, + "ariaHidden": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-hidden][1] state; a constant indicating whether the element is exposed to an accessibility API.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-hidden" + }, + "ariaLabel": { + "$ref": "#/definitions/ChannelValue", + "description": "The [aria-label][1]; a channel specifying short textual labels representing the value in the accessibility tree.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-label" + }, + "bandwidth": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The kernel density bandwidth for smoothing, in pixels." + }, + "clip": { + "anyOf": [ + { + "const": "frame", + "type": "string" + }, + { + "const": "sphere", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to clip the mark; one of:\n\n- *frame* or true - clip to the plot’s frame (inner area)\n- *sphere* - clip to the projected sphere (*e.g.*, front hemisphere)\n- null or false - do not clip\n\nThe *sphere* clip option requires a geographic projection." + }, + "config": { + "$ref": "#/definitions/Config", + "description": "Configuration options." + }, + "data": { + "$ref": "#/definitions/Data", + "description": "Dataset definitions." + }, + "dx": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The horizontal offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "dy": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The vertical offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "facet": { + "anyOf": [ + { + "const": "auto", + "type": "string" + }, + { + "const": "include", + "type": "string" + }, + { + "const": "exclude", + "type": "string" + }, + { + "const": "super", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to enable or disable faceting; one of:\n\n- *auto* (default) - automatically determine if this mark should be faceted\n- *include* (or true) - draw the subset of the mark’s data in the current facet\n- *exclude* - draw the subset of the mark’s data *not* in the current facet\n- *super* - draw this mark in a single frame that covers all facets\n- null (or false) - repeat this mark’s data across all facets (*i.e.*, no faceting)\n\nWhen a mark uses *super* faceting, it is not allowed to use position scales (*x*, *y*, *fx*, or *fy*); *super* faceting is intended for decorations, such as labels and legends.\n\nWhen top-level faceting is used, the default *auto* setting is equivalent to *include* when the mark data is strictly equal to the top-level facet data; otherwise it is equivalent to null. When the *include* or *exclude* facet mode is chosen, the mark data must be parallel to the top-level facet data: the data must have the same length and order. If the data are not parallel, then the wrong data may be shown in each facet. The default\n*auto* therefore requires strict equality (`===`) for safety, and using the facet data as mark data is recommended when using the *exclude* facet mode. (To construct parallel data safely, consider using [*array*.map][1] on the facet data.)\n\nWhen mark-level faceting is used, the default *auto* setting is equivalent to *include*: the mark will be faceted if either the **fx** or **fy** channel option (or both) is specified. The null or false option will disable faceting, while *exclude* draws the subset of the mark’s data *not* in the current facet.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map" + }, + "facetAnchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "right", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "const": "left", + "type": "string" + }, + { + "const": "top-left", + "type": "string" + }, + { + "const": "top-right", + "type": "string" + }, + { + "const": "bottom-left", + "type": "string" + }, + { + "const": "bottom-right", + "type": "string" + }, + { + "const": "top-empty", + "type": "string" + }, + { + "const": "right-empty", + "type": "string" + }, + { + "const": "bottom-empty", + "type": "string" + }, + { + "const": "left-empty", + "type": "string" + }, + { + "const": "empty", + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to place the mark with respect to facets; one of:\n\n- null (default for most marks) - display the mark in each non-empty facet\n- *top*, *right*, *bottom*, or *left* - display the mark only in facets on the given side\n- *top-empty*, *right-empty*, *bottom-empty*, or *left-empty* (default for axis marks) - display the mark only in facets that have empty space on the given side: either the margin, or an empty facet\n- *empty* - display the mark in empty facets only" + }, + "fill": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill" + }, + "fillOpacity": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill-opacity][1]; a constant number between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill-opacity" + }, + "filter": { + "$ref": "#/definitions/ChannelValue", + "description": "Applies a transform to filter the mark’s index according to the given channel values; only truthy values are retained.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "fx": { + "$ref": "#/definitions/ChannelValue", + "description": "The horizontal facet position channel, for mark-level faceting, bound to the *fx* scale." + }, + "fy": { + "$ref": "#/definitions/ChannelValue", + "description": "The vertical facet position channel, for mark-level faceting, bound to the\n*fy* scale." + }, + "height": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The height (number of rows) of the grid, in actual pixels." + }, + "href": { + "$ref": "#/definitions/ChannelValue", + "description": "The [href][1]; a channel specifying URLs for clickable links. May be used in conjunction with the **target** option to open links in another window.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/href" + }, + "imageFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A CSS [filter][1]; a constant string used to adjust the rendering of images, such as *blur(5px)*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/filter" + }, + "interpolate": { + "anyOf": [ + { + "$ref": "#/definitions/GridInterpolate" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The spatial interpolation method; one of:\n\n- *none* - do not perform interpolation (the default), maps samples to single bins\n- *linear* - apply proportional linear interpolation across adjacent bins\n- *nearest* - assign each pixel to the closest sample’s value (Voronoi diagram)\n- *barycentric* - apply barycentric interpolation over the Delaunay triangulation\n- *random-walk* - apply a random walk from each pixel, stopping when near a sample" + }, + "margin": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four mark margins: **marginTop**,\n**marginRight**, **marginBottom**, and **marginLeft**; typically defaults to 0, except for axis marks." + }, + "marginBottom": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s bottom margin; the minimum distance in pixels between the bottom edges of the inner and outer plot area." + }, + "marginLeft": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s left margin; the minimum distance in pixels between the left edges of the inner and outer plot area." + }, + "marginRight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s right margin; the minimum distance in pixels between the right edges of the mark’s inner and outer plot area." + }, + "marginTop": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s top margin; the minimum distance in pixels between the top edges of the inner and outer plot area." + }, + "mark": { + "const": "contour", + "description": "A contour mark that draws isolines to delineate regions above and below a particular continuous value. It is often used to convey densities as a height field. The special column name \"density\" can be used to map density values to the fill or stroke options.", + "type": "string" + }, + "meta": { + "$ref": "#/definitions/Meta", + "description": "Specification metadata." + }, + "mixBlendMode": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [mix-blend-mode][1]; a constant string specifying how to blend content such as *multiply*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode" + }, + "opacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally. For faster rendering, prefer the **strokeOpacity** or **fillOpacity** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/opacity" + }, + "pad": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The bin padding, one of 1 (default) to include extra padding for the final bin, or 0 to make the bins flush with the maximum domain value." + }, + "paintOrder": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [paint-order][1]; a constant string specifying the order in which the\n**fill**, **stroke**, and any markers are drawn; defaults to *normal*, which draws the fill, then stroke, then markers; defaults to *stroke* for the text mark to create a “halo” around text to improve legibility.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/paint-order" + }, + "params": { + "$ref": "#/definitions/Params", + "description": "Param and Selection definitions." + }, + "pixelSize": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The effective screen size of a raster pixel, used to determine the height and width of the raster from the frame’s dimensions; defaults to 1." + }, + "plotDefaults": { + "$ref": "#/definitions/PlotAttributes", + "description": "A default set of attributes to apply to all plot components." + }, + "pointerEvents": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [pointer-events][1] property; a constant string such as *none*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/pointer-events" + }, + "reverse": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Applies a transform to reverse the order of the mark’s index, say for reverse input order." + }, + "select": { + "$ref": "#/definitions/SelectFilter", + "description": "Applies a filter transform after data is loaded to highlight selected values only. For example, `first` and `last` select the first or last values of series only (using the *z* channel to separate series). Meanwhile, `nearestX` and `nearestY` select the point nearest to the pointer along the *x* or *y* channel dimension. Unlike Mosaic selections, a mark level *select* is internal to the mark only, and does not populate a param or selection value to be shared across clients.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "shapeRendering": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [shape-rendering][1]; a constant string such as *crispEdges*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/shape-rendering" + }, + "sort": { + "anyOf": [ + { + "$ref": "#/definitions/SortOrder" + }, + { + "$ref": "#/definitions/ChannelDomainSort" + } + ], + "description": "Either applies a transform to sort the mark’s index by the specified channel values, or imputes ordinal scale domains from this mark’s channels.\n\nWhen imputing ordinal scale domains from channel values, the **sort** option is an object whose keys are ordinal scale names such as *x* or *fx*, and whose values are channel names such as *y*, *y1*, or *y2*. For example, to impute the *y* scale’s domain from the associated *x* channel values in ascending order:\n\n```js sort: {y: \"x\"} ```\n\nFor different sort options for different scales, replace the channel name with a *value* object and per-scale options:\n\n```js sort: {y: {value: \"-x\"}} ```\n\nWhen sorting the mark’s index, the **sort** option is instead one of:\n\n- a channel value definition for sorting given values in ascending order\n- a {value, order} object for sorting given values\n- a {channel, order} object for sorting the named channel’s values" + }, + "stroke": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke" + }, + "strokeDasharray": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dasharray][1]; a constant number indicating the length in pixels of alternating dashes and gaps, or a constant string of numbers separated by spaces or commas (_e.g._, *10 2* for dashes of 10 pixels separated by gaps of 2 pixels), or *none* (the default) for no dashing\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dasharray" + }, + "strokeDashoffset": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dashoffset][1]; a constant indicating the offset in pixels of the first dash along the stroke; defaults to zero.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dashoffset" + }, + "strokeLinecap": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linecap][1]; a constant specifying how to cap stroked paths, such as *butt*, *round*, or *square*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linecap" + }, + "strokeLinejoin": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linejoin][1]; a constant specifying how to join stroked paths, such as *bevel*, *miter*, *miter-clip*, or *round*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linejoin" + }, + "strokeMiterlimit": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-miterlimit][1]; a constant number specifying how to limit the length of *miter* joins on stroked paths.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-miterlimit" + }, + "strokeOpacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-opacity" + }, + "strokeWidth": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-width][1]; a constant number in pixels, or a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-width" + }, + "target": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [target][1]; a constant string specifying the target window (_e.g._,\n*_blank*) for clickable links; used in conjunction with the **href** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/target" + }, + "thresholds": { + "anyOf": [ + { + "type": "number" + }, + { + "items": { + "type": "number" + }, + "type": "array" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The number of contour thresholds to subdivide the domain into discrete level sets; defaults to 10. One of:\n\n- a count representing the desired number of bins\n- an array of *n* threshold values for *n* - 1 bins" + }, + "tip": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/TipPointer" + }, + { + "properties": { + "anchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The tip anchor specifies how to orient the tip box relative to its anchor position; it refers to the part of the tip box that is attached to the anchor point. For example, the *top-left* anchor places the top-left corner of tip box near the anchor position, hence placing the tip box below and to the right of the anchor position." + }, + "fontFamily": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font-family][1]; a constant; defaults to the plot’s font family, which is typically [*system-ui*][2].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-family [2]: https://drafts.csswg.org/css-fonts-4/#valdef-font-family-system-ui" + }, + "fontSize": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font size][1] in pixels; either a constant or a channel; defaults to the plot’s font size, which is typically 10. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-size" + }, + "fontStyle": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font style][1]; a constant; defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-style" + }, + "fontVariant": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font variant][1]; a constant; if the **text** channel contains numbers or dates, defaults to *tabular-nums* to facilitate comparing numbers; otherwise defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant" + }, + "fontWeight": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font weight][1]; a constant; defaults to the plot’s font weight, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight" + }, + "format": { + "additionalProperties": false, + "description": "How channel values are formatted for display. If a format is a string, it is interpreted as a (UTC) time format for temporal channels, and otherwise a number format.", + "properties": { + "ariaLabel": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fill": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fillOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fontSize": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fx": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fy": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "geometry": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "height": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "href": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "length": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "opacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "path": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "r": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "rotate": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "src": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "stroke": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeWidth": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "symbol": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "text": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "title": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "weight": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "width": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "z": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + } + }, + "type": "object" + }, + "frameAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The frame anchor specifies defaults for **x** and **y** based on the plot’s frame; it may be one of the four sides (*top*, *right*, *bottom*, *left*), one of the four corners (*top-left*, *top-right*, *bottom-right*,\n*bottom-left*), or the *middle* of the frame. For example, for tips distributed horizontally at the top of the frame:\n\n```js Plot.tip(data, {x: \"date\", frameAnchor: \"top\"}) ```" + }, + "lineHeight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line height in ems; defaults to 1. The line height affects the (typically vertical) separation between adjacent baselines of text, as well as the separation between the text and its anchor point." + }, + "lineWidth": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line width in ems (e.g., 10 for about 20 characters); defaults to infinity, disabling wrapping and clipping.\n\nIf **textOverflow** is null, lines will be wrapped at the specified length. If a line is split at a soft hyphen (\\xad), a hyphen (-) will be displayed at the end of the line. If **textOverflow** is not null, lines will be clipped according to the given strategy." + }, + "monospace": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, changes the default **fontFamily** to *monospace*, and uses simplified monospaced text metrics calculations." + }, + "pathFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The image filter for the tip’s box; defaults to a drop shadow." + }, + "pointer": { + "$ref": "#/definitions/TipPointer" + }, + "pointerSize": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The size of the tip’s pointer in pixels; defaults to 12." + }, + "preferredAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If an explicit tip anchor is not specified, an anchor is chosen automatically such that the tip fits within the plot’s frame; if the preferred anchor fits, it is chosen." + }, + "textAnchor": { + "anyOf": [ + { + "const": "start", + "type": "string" + }, + { + "const": "middle", + "type": "string" + }, + { + "const": "end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [text anchor][1] controls how text is aligned (typically horizontally) relative to its anchor point; it is one of *start*, *end*, or *middle*. If the frame anchor is *left*, *top-left*, or *bottom-left*, the default text anchor is *start*; if the frame anchor is *right*, *top-right*, or\n*bottom-right*, the default is *end*; otherwise it is *middle*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/text-anchor" + }, + "textOverflow": { + "anyOf": [ + { + "type": "null" + }, + { + "const": "clip", + "type": "string" + }, + { + "const": "ellipsis", + "type": "string" + }, + { + "const": "clip-start", + "type": "string" + }, + { + "const": "clip-end", + "type": "string" + }, + { + "const": "ellipsis-start", + "type": "string" + }, + { + "const": "ellipsis-middle", + "type": "string" + }, + { + "const": "ellipsis-end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How truncate (or wrap) lines of text longer than the given **lineWidth**; one of:\n\n- null (default) - preserve overflowing characters (and wrap if needed)\n- *clip* or *clip-end* - remove characters from the end\n- *clip-start* - remove characters from the start\n- *ellipsis* or *ellipsis-end* - replace characters from the end with an ellipsis (…)\n- *ellipsis-start* - replace characters from the start with an ellipsis (…)\n- *ellipsis-middle* - replace characters from the middle with an ellipsis (…)\n\nIf no **title** was specified, if text requires truncation, a title containing the non-truncated text will be implicitly added." + }, + "textPadding": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The padding around the text in pixels; defaults to 8." + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + } + }, + "type": "object" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to generate a tooltip for this mark, and any tip options." + }, + "title": { + "$ref": "#/definitions/ChannelValue", + "description": "The title; a channel specifying accessible, short textual descriptions as strings (possibly with newlines). If the tip option is specified, the title will be displayed with an interactive tooltip instead of using the SVG [title element][1].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/title" + }, + "width": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The width (number of columns) of the grid, in actual pixels." + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel, typically bound to the *x* scale. Domain values are binned into a grid with *width* horizontal bins." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel, typically bound to the *y* scale. Domain values are binned into a grid with *height* vertical bins." + } + }, + "required": [ + "data", + "mark" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "$schema": { + "description": "A [JSON schema](http://json-schema.org/) URL for this specification, such as https://uwdata.github.io/mosaic/schema/latest.json. This property enables validation and autocomplete in editors with JSON schema support.", + "format": "uri", + "type": "string" + }, + "ariaDescription": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-description][1]; a constant textual description.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-description" + }, + "ariaHidden": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-hidden][1] state; a constant indicating whether the element is exposed to an accessibility API.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-hidden" + }, + "ariaLabel": { + "$ref": "#/definitions/ChannelValue", + "description": "The [aria-label][1]; a channel specifying short textual labels representing the value in the accessibility tree.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-label" + }, + "clip": { + "anyOf": [ + { + "const": "frame", + "type": "string" + }, + { + "const": "sphere", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to clip the mark; one of:\n\n- *frame* or true - clip to the plot’s frame (inner area)\n- *sphere* - clip to the projected sphere (*e.g.*, front hemisphere)\n- null or false - do not clip\n\nThe *sphere* clip option requires a geographic projection." + }, + "config": { + "$ref": "#/definitions/Config", + "description": "Configuration options." + }, + "curve": { + "anyOf": [ + { + "$ref": "#/definitions/Curve" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The curve (interpolation) method for connecting adjacent points. One of:\n\n- *basis* - a cubic basis spline (repeating the end points)\n- *basis-open* - an open cubic basis spline\n- *basis-closed* - a closed cubic basis spline\n- *bump-x* - a Bézier curve with horizontal tangents\n- *bump-y* - a Bézier curve with vertical tangents\n- *bundle* - a straightened cubic basis spline (suitable for lines only, not areas)\n- *cardinal* - a cubic cardinal spline (with one-sided differences at the ends)\n- *cardinal-open* - an open cubic cardinal spline\n- *cardinal-closed* - an closed cubic cardinal spline\n- *catmull-rom* - a cubic Catmull–Rom spline (with one-sided differences at the ends)\n- *catmull-rom-open* - an open cubic Catmull–Rom spline\n- *catmull-rom-closed* - a closed cubic Catmull–Rom spline\n- *linear* - a piecewise linear curve (*i.e.*, straight line segments)\n- *linear-closed* - a closed piecewise linear curve (*i.e.*, straight line segments)\n- *monotone-x* - a cubic spline that preserves monotonicity in *x*\n- *monotone-y* - a cubic spline that preserves monotonicity in *y*\n- *natural* - a natural cubic spline\n- *step* - a piecewise constant function where *y* changes at the midpoint of *x*\n- *step-after* - a piecewise constant function where *y* changes after *x*\n- *step-before* - a piecewise constant function where *x* changes after *y*" + }, + "data": { + "$ref": "#/definitions/Data", + "description": "Dataset definitions." + }, + "dx": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The horizontal offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "dy": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The vertical offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "facet": { + "anyOf": [ + { + "const": "auto", + "type": "string" + }, + { + "const": "include", + "type": "string" + }, + { + "const": "exclude", + "type": "string" + }, + { + "const": "super", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to enable or disable faceting; one of:\n\n- *auto* (default) - automatically determine if this mark should be faceted\n- *include* (or true) - draw the subset of the mark’s data in the current facet\n- *exclude* - draw the subset of the mark’s data *not* in the current facet\n- *super* - draw this mark in a single frame that covers all facets\n- null (or false) - repeat this mark’s data across all facets (*i.e.*, no faceting)\n\nWhen a mark uses *super* faceting, it is not allowed to use position scales (*x*, *y*, *fx*, or *fy*); *super* faceting is intended for decorations, such as labels and legends.\n\nWhen top-level faceting is used, the default *auto* setting is equivalent to *include* when the mark data is strictly equal to the top-level facet data; otherwise it is equivalent to null. When the *include* or *exclude* facet mode is chosen, the mark data must be parallel to the top-level facet data: the data must have the same length and order. If the data are not parallel, then the wrong data may be shown in each facet. The default\n*auto* therefore requires strict equality (`===`) for safety, and using the facet data as mark data is recommended when using the *exclude* facet mode. (To construct parallel data safely, consider using [*array*.map][1] on the facet data.)\n\nWhen mark-level faceting is used, the default *auto* setting is equivalent to *include*: the mark will be faceted if either the **fx** or **fy** channel option (or both) is specified. The null or false option will disable faceting, while *exclude* draws the subset of the mark’s data *not* in the current facet.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map" + }, + "facetAnchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "right", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "const": "left", + "type": "string" + }, + { + "const": "top-left", + "type": "string" + }, + { + "const": "top-right", + "type": "string" + }, + { + "const": "bottom-left", + "type": "string" + }, + { + "const": "bottom-right", + "type": "string" + }, + { + "const": "top-empty", + "type": "string" + }, + { + "const": "right-empty", + "type": "string" + }, + { + "const": "bottom-empty", + "type": "string" + }, + { + "const": "left-empty", + "type": "string" + }, + { + "const": "empty", + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to place the mark with respect to facets; one of:\n\n- null (default for most marks) - display the mark in each non-empty facet\n- *top*, *right*, *bottom*, or *left* - display the mark only in facets on the given side\n- *top-empty*, *right-empty*, *bottom-empty*, or *left-empty* (default for axis marks) - display the mark only in facets that have empty space on the given side: either the margin, or an empty facet\n- *empty* - display the mark in empty facets only" + }, + "fill": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill" + }, + "fillOpacity": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill-opacity][1]; a constant number between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill-opacity" + }, + "filter": { + "$ref": "#/definitions/ChannelValue", + "description": "Applies a transform to filter the mark’s index according to the given channel values; only truthy values are retained.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "fx": { + "$ref": "#/definitions/ChannelValue", + "description": "The horizontal facet position channel, for mark-level faceting, bound to the *fx* scale." + }, + "fy": { + "$ref": "#/definitions/ChannelValue", + "description": "The vertical facet position channel, for mark-level faceting, bound to the\n*fy* scale." + }, + "href": { + "$ref": "#/definitions/ChannelValue", + "description": "The [href][1]; a channel specifying URLs for clickable links. May be used in conjunction with the **target** option to open links in another window.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/href" + }, + "imageFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A CSS [filter][1]; a constant string used to adjust the rendering of images, such as *blur(5px)*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/filter" + }, + "margin": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four mark margins: **marginTop**,\n**marginRight**, **marginBottom**, and **marginLeft**; typically defaults to 0, except for axis marks." + }, + "marginBottom": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s bottom margin; the minimum distance in pixels between the bottom edges of the inner and outer plot area." + }, + "marginLeft": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s left margin; the minimum distance in pixels between the left edges of the inner and outer plot area." + }, + "marginRight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s right margin; the minimum distance in pixels between the right edges of the mark’s inner and outer plot area." + }, + "marginTop": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s top margin; the minimum distance in pixels between the top edges of the inner and outer plot area." + }, + "mark": { + "const": "delaunayLink", + "description": "A mark that draws links for each edge of the Delaunay triangulation of points given by the **x** and **y** channels. Like the link mark, except that **x1**, **y1**, **x2**, and **y2** are derived automatically from **x** and **y**. When an aesthetic channel is specified (such as\n**stroke** or **strokeWidth**), the link inherits the corresponding channel value from one of its two endpoints arbitrarily.\n\nIf **z** is specified, the input points are grouped by *z*, producing a separate Delaunay triangulation for each group.", + "type": "string" + }, + "marker": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for markerStart, markerMid, and markerEnd; one of:\n\n- a marker name such as *arrow* or *circle*\n- *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*" + }, + "markerEnd": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The marker for the ending point of a line segment; one of:\n\n- a marker name such as *arrow* or *circle*\n* *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*" + }, + "markerMid": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The marker for any middle (interior) points of a line segment. If the line segment only has a start and end point, this option has no effect. One of:\n\n- a marker name such as *arrow* or *circle*\n* *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*\n* a function - a custom marker function; see below" + }, + "markerStart": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The marker for the starting point of a line segment; one of:\n\n- a marker name such as *arrow* or *circle*\n* *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*" + }, + "meta": { + "$ref": "#/definitions/Meta", + "description": "Specification metadata." + }, + "mixBlendMode": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [mix-blend-mode][1]; a constant string specifying how to blend content such as *multiply*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode" + }, + "opacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally. For faster rendering, prefer the **strokeOpacity** or **fillOpacity** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/opacity" + }, + "paintOrder": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [paint-order][1]; a constant string specifying the order in which the\n**fill**, **stroke**, and any markers are drawn; defaults to *normal*, which draws the fill, then stroke, then markers; defaults to *stroke* for the text mark to create a “halo” around text to improve legibility.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/paint-order" + }, + "params": { + "$ref": "#/definitions/Params", + "description": "Param and Selection definitions." + }, + "plotDefaults": { + "$ref": "#/definitions/PlotAttributes", + "description": "A default set of attributes to apply to all plot components." + }, + "pointerEvents": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [pointer-events][1] property; a constant string such as *none*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/pointer-events" + }, + "reverse": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Applies a transform to reverse the order of the mark’s index, say for reverse input order." + }, + "select": { + "$ref": "#/definitions/SelectFilter", + "description": "Applies a filter transform after data is loaded to highlight selected values only. For example, `first` and `last` select the first or last values of series only (using the *z* channel to separate series). Meanwhile, `nearestX` and `nearestY` select the point nearest to the pointer along the *x* or *y* channel dimension. Unlike Mosaic selections, a mark level *select* is internal to the mark only, and does not populate a param or selection value to be shared across clients.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "shapeRendering": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [shape-rendering][1]; a constant string such as *crispEdges*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/shape-rendering" + }, + "sort": { + "anyOf": [ + { + "$ref": "#/definitions/SortOrder" + }, + { + "$ref": "#/definitions/ChannelDomainSort" + } + ], + "description": "Either applies a transform to sort the mark’s index by the specified channel values, or imputes ordinal scale domains from this mark’s channels.\n\nWhen imputing ordinal scale domains from channel values, the **sort** option is an object whose keys are ordinal scale names such as *x* or *fx*, and whose values are channel names such as *y*, *y1*, or *y2*. For example, to impute the *y* scale’s domain from the associated *x* channel values in ascending order:\n\n```js sort: {y: \"x\"} ```\n\nFor different sort options for different scales, replace the channel name with a *value* object and per-scale options:\n\n```js sort: {y: {value: \"-x\"}} ```\n\nWhen sorting the mark’s index, the **sort** option is instead one of:\n\n- a channel value definition for sorting given values in ascending order\n- a {value, order} object for sorting given values\n- a {channel, order} object for sorting the named channel’s values" + }, + "stroke": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke" + }, + "strokeDasharray": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dasharray][1]; a constant number indicating the length in pixels of alternating dashes and gaps, or a constant string of numbers separated by spaces or commas (_e.g._, *10 2* for dashes of 10 pixels separated by gaps of 2 pixels), or *none* (the default) for no dashing\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dasharray" + }, + "strokeDashoffset": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dashoffset][1]; a constant indicating the offset in pixels of the first dash along the stroke; defaults to zero.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dashoffset" + }, + "strokeLinecap": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linecap][1]; a constant specifying how to cap stroked paths, such as *butt*, *round*, or *square*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linecap" + }, + "strokeLinejoin": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linejoin][1]; a constant specifying how to join stroked paths, such as *bevel*, *miter*, *miter-clip*, or *round*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linejoin" + }, + "strokeMiterlimit": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-miterlimit][1]; a constant number specifying how to limit the length of *miter* joins on stroked paths.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-miterlimit" + }, + "strokeOpacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-opacity" + }, + "strokeWidth": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-width][1]; a constant number in pixels, or a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-width" + }, + "target": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [target][1]; a constant string specifying the target window (_e.g._,\n*_blank*) for clickable links; used in conjunction with the **href** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/target" + }, + "tension": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The tension option only has an effect on bundle, cardinal and Catmull–Rom splines (*bundle*, *cardinal*, *cardinal-open*, *cardinal-closed*,\n*catmull-rom*, *catmull-rom-open*, and *catmull-rom-closed*). For bundle splines, it corresponds to [beta][1]; for cardinal splines, [tension][2]; for Catmull–Rom splines, [alpha][3].\n\n[1]: https://d3js.org/d3-shape/curve#curveBundle_beta [2]: https://d3js.org/d3-shape/curve#curveCardinal_tension [3]: https://d3js.org/d3-shape/curve#curveCatmullRom_alpha" + }, + "tip": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/TipPointer" + }, + { + "properties": { + "anchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The tip anchor specifies how to orient the tip box relative to its anchor position; it refers to the part of the tip box that is attached to the anchor point. For example, the *top-left* anchor places the top-left corner of tip box near the anchor position, hence placing the tip box below and to the right of the anchor position." + }, + "fontFamily": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font-family][1]; a constant; defaults to the plot’s font family, which is typically [*system-ui*][2].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-family [2]: https://drafts.csswg.org/css-fonts-4/#valdef-font-family-system-ui" + }, + "fontSize": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font size][1] in pixels; either a constant or a channel; defaults to the plot’s font size, which is typically 10. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-size" + }, + "fontStyle": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font style][1]; a constant; defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-style" + }, + "fontVariant": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font variant][1]; a constant; if the **text** channel contains numbers or dates, defaults to *tabular-nums* to facilitate comparing numbers; otherwise defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant" + }, + "fontWeight": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font weight][1]; a constant; defaults to the plot’s font weight, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight" + }, + "format": { + "additionalProperties": false, + "description": "How channel values are formatted for display. If a format is a string, it is interpreted as a (UTC) time format for temporal channels, and otherwise a number format.", + "properties": { + "ariaLabel": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fill": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fillOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fontSize": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fx": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fy": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "geometry": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "height": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "href": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "length": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "opacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "path": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "r": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "rotate": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "src": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "stroke": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeWidth": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "symbol": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "text": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "title": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "weight": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "width": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "z": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + } + }, + "type": "object" + }, + "frameAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The frame anchor specifies defaults for **x** and **y** based on the plot’s frame; it may be one of the four sides (*top*, *right*, *bottom*, *left*), one of the four corners (*top-left*, *top-right*, *bottom-right*,\n*bottom-left*), or the *middle* of the frame. For example, for tips distributed horizontally at the top of the frame:\n\n```js Plot.tip(data, {x: \"date\", frameAnchor: \"top\"}) ```" + }, + "lineHeight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line height in ems; defaults to 1. The line height affects the (typically vertical) separation between adjacent baselines of text, as well as the separation between the text and its anchor point." + }, + "lineWidth": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line width in ems (e.g., 10 for about 20 characters); defaults to infinity, disabling wrapping and clipping.\n\nIf **textOverflow** is null, lines will be wrapped at the specified length. If a line is split at a soft hyphen (\\xad), a hyphen (-) will be displayed at the end of the line. If **textOverflow** is not null, lines will be clipped according to the given strategy." + }, + "monospace": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, changes the default **fontFamily** to *monospace*, and uses simplified monospaced text metrics calculations." + }, + "pathFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The image filter for the tip’s box; defaults to a drop shadow." + }, + "pointer": { + "$ref": "#/definitions/TipPointer" + }, + "pointerSize": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The size of the tip’s pointer in pixels; defaults to 12." + }, + "preferredAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If an explicit tip anchor is not specified, an anchor is chosen automatically such that the tip fits within the plot’s frame; if the preferred anchor fits, it is chosen." + }, + "textAnchor": { + "anyOf": [ + { + "const": "start", + "type": "string" + }, + { + "const": "middle", + "type": "string" + }, + { + "const": "end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [text anchor][1] controls how text is aligned (typically horizontally) relative to its anchor point; it is one of *start*, *end*, or *middle*. If the frame anchor is *left*, *top-left*, or *bottom-left*, the default text anchor is *start*; if the frame anchor is *right*, *top-right*, or\n*bottom-right*, the default is *end*; otherwise it is *middle*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/text-anchor" + }, + "textOverflow": { + "anyOf": [ + { + "type": "null" + }, + { + "const": "clip", + "type": "string" + }, + { + "const": "ellipsis", + "type": "string" + }, + { + "const": "clip-start", + "type": "string" + }, + { + "const": "clip-end", + "type": "string" + }, + { + "const": "ellipsis-start", + "type": "string" + }, + { + "const": "ellipsis-middle", + "type": "string" + }, + { + "const": "ellipsis-end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How truncate (or wrap) lines of text longer than the given **lineWidth**; one of:\n\n- null (default) - preserve overflowing characters (and wrap if needed)\n- *clip* or *clip-end* - remove characters from the end\n- *clip-start* - remove characters from the start\n- *ellipsis* or *ellipsis-end* - replace characters from the end with an ellipsis (…)\n- *ellipsis-start* - replace characters from the start with an ellipsis (…)\n- *ellipsis-middle* - replace characters from the middle with an ellipsis (…)\n\nIf no **title** was specified, if text requires truncation, a title containing the non-truncated text will be implicitly added." + }, + "textPadding": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The padding around the text in pixels; defaults to 8." + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + } + }, + "type": "object" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to generate a tooltip for this mark, and any tip options." + }, + "title": { + "$ref": "#/definitions/ChannelValue", + "description": "The title; a channel specifying accessible, short textual descriptions as strings (possibly with newlines). If the tip option is specified, the title will be displayed with an interactive tooltip instead of using the SVG [title element][1].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/title" + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel, typically bound to the *x* scale." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel, typically bound to the *y* scale." + }, + "z": { + "$ref": "#/definitions/ChannelValue", + "description": "An optional ordinal channel for grouping to produce multiple (possibly overlapping) triangulations." + } + }, + "required": [ + "data", + "mark" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "$schema": { + "description": "A [JSON schema](http://json-schema.org/) URL for this specification, such as https://uwdata.github.io/mosaic/schema/latest.json. This property enables validation and autocomplete in editors with JSON schema support.", + "format": "uri", + "type": "string" + }, + "ariaDescription": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-description][1]; a constant textual description.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-description" + }, + "ariaHidden": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-hidden][1] state; a constant indicating whether the element is exposed to an accessibility API.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-hidden" + }, + "ariaLabel": { + "$ref": "#/definitions/ChannelValue", + "description": "The [aria-label][1]; a channel specifying short textual labels representing the value in the accessibility tree.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-label" + }, + "clip": { + "anyOf": [ + { + "const": "frame", + "type": "string" + }, + { + "const": "sphere", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to clip the mark; one of:\n\n- *frame* or true - clip to the plot’s frame (inner area)\n- *sphere* - clip to the projected sphere (*e.g.*, front hemisphere)\n- null or false - do not clip\n\nThe *sphere* clip option requires a geographic projection." + }, + "config": { + "$ref": "#/definitions/Config", + "description": "Configuration options." + }, + "curve": { + "anyOf": [ + { + "$ref": "#/definitions/Curve" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The curve (interpolation) method for connecting adjacent points. One of:\n\n- *basis* - a cubic basis spline (repeating the end points)\n- *basis-open* - an open cubic basis spline\n- *basis-closed* - a closed cubic basis spline\n- *bump-x* - a Bézier curve with horizontal tangents\n- *bump-y* - a Bézier curve with vertical tangents\n- *bundle* - a straightened cubic basis spline (suitable for lines only, not areas)\n- *cardinal* - a cubic cardinal spline (with one-sided differences at the ends)\n- *cardinal-open* - an open cubic cardinal spline\n- *cardinal-closed* - an closed cubic cardinal spline\n- *catmull-rom* - a cubic Catmull–Rom spline (with one-sided differences at the ends)\n- *catmull-rom-open* - an open cubic Catmull–Rom spline\n- *catmull-rom-closed* - a closed cubic Catmull–Rom spline\n- *linear* - a piecewise linear curve (*i.e.*, straight line segments)\n- *linear-closed* - a closed piecewise linear curve (*i.e.*, straight line segments)\n- *monotone-x* - a cubic spline that preserves monotonicity in *x*\n- *monotone-y* - a cubic spline that preserves monotonicity in *y*\n- *natural* - a natural cubic spline\n- *step* - a piecewise constant function where *y* changes at the midpoint of *x*\n- *step-after* - a piecewise constant function where *y* changes after *x*\n- *step-before* - a piecewise constant function where *x* changes after *y*" + }, + "data": { + "$ref": "#/definitions/Data", + "description": "Dataset definitions." + }, + "dx": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The horizontal offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "dy": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The vertical offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "facet": { + "anyOf": [ + { + "const": "auto", + "type": "string" + }, + { + "const": "include", + "type": "string" + }, + { + "const": "exclude", + "type": "string" + }, + { + "const": "super", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to enable or disable faceting; one of:\n\n- *auto* (default) - automatically determine if this mark should be faceted\n- *include* (or true) - draw the subset of the mark’s data in the current facet\n- *exclude* - draw the subset of the mark’s data *not* in the current facet\n- *super* - draw this mark in a single frame that covers all facets\n- null (or false) - repeat this mark’s data across all facets (*i.e.*, no faceting)\n\nWhen a mark uses *super* faceting, it is not allowed to use position scales (*x*, *y*, *fx*, or *fy*); *super* faceting is intended for decorations, such as labels and legends.\n\nWhen top-level faceting is used, the default *auto* setting is equivalent to *include* when the mark data is strictly equal to the top-level facet data; otherwise it is equivalent to null. When the *include* or *exclude* facet mode is chosen, the mark data must be parallel to the top-level facet data: the data must have the same length and order. If the data are not parallel, then the wrong data may be shown in each facet. The default\n*auto* therefore requires strict equality (`===`) for safety, and using the facet data as mark data is recommended when using the *exclude* facet mode. (To construct parallel data safely, consider using [*array*.map][1] on the facet data.)\n\nWhen mark-level faceting is used, the default *auto* setting is equivalent to *include*: the mark will be faceted if either the **fx** or **fy** channel option (or both) is specified. The null or false option will disable faceting, while *exclude* draws the subset of the mark’s data *not* in the current facet.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map" + }, + "facetAnchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "right", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "const": "left", + "type": "string" + }, + { + "const": "top-left", + "type": "string" + }, + { + "const": "top-right", + "type": "string" + }, + { + "const": "bottom-left", + "type": "string" + }, + { + "const": "bottom-right", + "type": "string" + }, + { + "const": "top-empty", + "type": "string" + }, + { + "const": "right-empty", + "type": "string" + }, + { + "const": "bottom-empty", + "type": "string" + }, + { + "const": "left-empty", + "type": "string" + }, + { + "const": "empty", + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to place the mark with respect to facets; one of:\n\n- null (default for most marks) - display the mark in each non-empty facet\n- *top*, *right*, *bottom*, or *left* - display the mark only in facets on the given side\n- *top-empty*, *right-empty*, *bottom-empty*, or *left-empty* (default for axis marks) - display the mark only in facets that have empty space on the given side: either the margin, or an empty facet\n- *empty* - display the mark in empty facets only" + }, + "fill": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill" + }, + "fillOpacity": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill-opacity][1]; a constant number between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill-opacity" + }, + "filter": { + "$ref": "#/definitions/ChannelValue", + "description": "Applies a transform to filter the mark’s index according to the given channel values; only truthy values are retained.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "fx": { + "$ref": "#/definitions/ChannelValue", + "description": "The horizontal facet position channel, for mark-level faceting, bound to the *fx* scale." + }, + "fy": { + "$ref": "#/definitions/ChannelValue", + "description": "The vertical facet position channel, for mark-level faceting, bound to the\n*fy* scale." + }, + "href": { + "$ref": "#/definitions/ChannelValue", + "description": "The [href][1]; a channel specifying URLs for clickable links. May be used in conjunction with the **target** option to open links in another window.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/href" + }, + "imageFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A CSS [filter][1]; a constant string used to adjust the rendering of images, such as *blur(5px)*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/filter" + }, + "margin": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four mark margins: **marginTop**,\n**marginRight**, **marginBottom**, and **marginLeft**; typically defaults to 0, except for axis marks." + }, + "marginBottom": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s bottom margin; the minimum distance in pixels between the bottom edges of the inner and outer plot area." + }, + "marginLeft": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s left margin; the minimum distance in pixels between the left edges of the inner and outer plot area." + }, + "marginRight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s right margin; the minimum distance in pixels between the right edges of the mark’s inner and outer plot area." + }, + "marginTop": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s top margin; the minimum distance in pixels between the top edges of the inner and outer plot area." + }, + "mark": { + "const": "delaunayMesh", + "description": "A mark that draws a mesh of the Delaunay triangulation of the points given by the **x** and **y** channels. The **stroke** option defaults to _currentColor_, and the **strokeOpacity** defaults to 0.2; the **fill** option is not supported. When an aesthetic channel is specified (such as\n**stroke** or **strokeWidth**), the mesh inherits the corresponding channel value from one of its constituent points arbitrarily.\n\nIf **z** is specified, the input points are grouped by *z*, producing a separate Delaunay triangulation for each group.", + "type": "string" + }, + "marker": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for markerStart, markerMid, and markerEnd; one of:\n\n- a marker name such as *arrow* or *circle*\n- *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*" + }, + "markerEnd": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The marker for the ending point of a line segment; one of:\n\n- a marker name such as *arrow* or *circle*\n* *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*" + }, + "markerMid": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The marker for any middle (interior) points of a line segment. If the line segment only has a start and end point, this option has no effect. One of:\n\n- a marker name such as *arrow* or *circle*\n* *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*\n* a function - a custom marker function; see below" + }, + "markerStart": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The marker for the starting point of a line segment; one of:\n\n- a marker name such as *arrow* or *circle*\n* *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*" + }, + "meta": { + "$ref": "#/definitions/Meta", + "description": "Specification metadata." + }, + "mixBlendMode": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [mix-blend-mode][1]; a constant string specifying how to blend content such as *multiply*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode" + }, + "opacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally. For faster rendering, prefer the **strokeOpacity** or **fillOpacity** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/opacity" + }, + "paintOrder": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [paint-order][1]; a constant string specifying the order in which the\n**fill**, **stroke**, and any markers are drawn; defaults to *normal*, which draws the fill, then stroke, then markers; defaults to *stroke* for the text mark to create a “halo” around text to improve legibility.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/paint-order" + }, + "params": { + "$ref": "#/definitions/Params", + "description": "Param and Selection definitions." + }, + "plotDefaults": { + "$ref": "#/definitions/PlotAttributes", + "description": "A default set of attributes to apply to all plot components." + }, + "pointerEvents": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [pointer-events][1] property; a constant string such as *none*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/pointer-events" + }, + "reverse": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Applies a transform to reverse the order of the mark’s index, say for reverse input order." + }, + "select": { + "$ref": "#/definitions/SelectFilter", + "description": "Applies a filter transform after data is loaded to highlight selected values only. For example, `first` and `last` select the first or last values of series only (using the *z* channel to separate series). Meanwhile, `nearestX` and `nearestY` select the point nearest to the pointer along the *x* or *y* channel dimension. Unlike Mosaic selections, a mark level *select* is internal to the mark only, and does not populate a param or selection value to be shared across clients.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "shapeRendering": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [shape-rendering][1]; a constant string such as *crispEdges*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/shape-rendering" + }, + "sort": { + "anyOf": [ + { + "$ref": "#/definitions/SortOrder" + }, + { + "$ref": "#/definitions/ChannelDomainSort" + } + ], + "description": "Either applies a transform to sort the mark’s index by the specified channel values, or imputes ordinal scale domains from this mark’s channels.\n\nWhen imputing ordinal scale domains from channel values, the **sort** option is an object whose keys are ordinal scale names such as *x* or *fx*, and whose values are channel names such as *y*, *y1*, or *y2*. For example, to impute the *y* scale’s domain from the associated *x* channel values in ascending order:\n\n```js sort: {y: \"x\"} ```\n\nFor different sort options for different scales, replace the channel name with a *value* object and per-scale options:\n\n```js sort: {y: {value: \"-x\"}} ```\n\nWhen sorting the mark’s index, the **sort** option is instead one of:\n\n- a channel value definition for sorting given values in ascending order\n- a {value, order} object for sorting given values\n- a {channel, order} object for sorting the named channel’s values" + }, + "stroke": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke" + }, + "strokeDasharray": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dasharray][1]; a constant number indicating the length in pixels of alternating dashes and gaps, or a constant string of numbers separated by spaces or commas (_e.g._, *10 2* for dashes of 10 pixels separated by gaps of 2 pixels), or *none* (the default) for no dashing\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dasharray" + }, + "strokeDashoffset": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dashoffset][1]; a constant indicating the offset in pixels of the first dash along the stroke; defaults to zero.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dashoffset" + }, + "strokeLinecap": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linecap][1]; a constant specifying how to cap stroked paths, such as *butt*, *round*, or *square*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linecap" + }, + "strokeLinejoin": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linejoin][1]; a constant specifying how to join stroked paths, such as *bevel*, *miter*, *miter-clip*, or *round*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linejoin" + }, + "strokeMiterlimit": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-miterlimit][1]; a constant number specifying how to limit the length of *miter* joins on stroked paths.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-miterlimit" + }, + "strokeOpacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-opacity" + }, + "strokeWidth": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-width][1]; a constant number in pixels, or a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-width" + }, + "target": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [target][1]; a constant string specifying the target window (_e.g._,\n*_blank*) for clickable links; used in conjunction with the **href** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/target" + }, + "tension": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The tension option only has an effect on bundle, cardinal and Catmull–Rom splines (*bundle*, *cardinal*, *cardinal-open*, *cardinal-closed*,\n*catmull-rom*, *catmull-rom-open*, and *catmull-rom-closed*). For bundle splines, it corresponds to [beta][1]; for cardinal splines, [tension][2]; for Catmull–Rom splines, [alpha][3].\n\n[1]: https://d3js.org/d3-shape/curve#curveBundle_beta [2]: https://d3js.org/d3-shape/curve#curveCardinal_tension [3]: https://d3js.org/d3-shape/curve#curveCatmullRom_alpha" + }, + "tip": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/TipPointer" + }, + { + "properties": { + "anchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The tip anchor specifies how to orient the tip box relative to its anchor position; it refers to the part of the tip box that is attached to the anchor point. For example, the *top-left* anchor places the top-left corner of tip box near the anchor position, hence placing the tip box below and to the right of the anchor position." + }, + "fontFamily": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font-family][1]; a constant; defaults to the plot’s font family, which is typically [*system-ui*][2].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-family [2]: https://drafts.csswg.org/css-fonts-4/#valdef-font-family-system-ui" + }, + "fontSize": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font size][1] in pixels; either a constant or a channel; defaults to the plot’s font size, which is typically 10. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-size" + }, + "fontStyle": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font style][1]; a constant; defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-style" + }, + "fontVariant": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font variant][1]; a constant; if the **text** channel contains numbers or dates, defaults to *tabular-nums* to facilitate comparing numbers; otherwise defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant" + }, + "fontWeight": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font weight][1]; a constant; defaults to the plot’s font weight, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight" + }, + "format": { + "additionalProperties": false, + "description": "How channel values are formatted for display. If a format is a string, it is interpreted as a (UTC) time format for temporal channels, and otherwise a number format.", + "properties": { + "ariaLabel": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fill": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fillOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fontSize": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fx": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fy": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "geometry": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "height": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "href": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "length": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "opacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "path": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "r": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "rotate": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "src": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "stroke": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeWidth": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "symbol": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "text": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "title": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "weight": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "width": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "z": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + } + }, + "type": "object" + }, + "frameAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The frame anchor specifies defaults for **x** and **y** based on the plot’s frame; it may be one of the four sides (*top*, *right*, *bottom*, *left*), one of the four corners (*top-left*, *top-right*, *bottom-right*,\n*bottom-left*), or the *middle* of the frame. For example, for tips distributed horizontally at the top of the frame:\n\n```js Plot.tip(data, {x: \"date\", frameAnchor: \"top\"}) ```" + }, + "lineHeight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line height in ems; defaults to 1. The line height affects the (typically vertical) separation between adjacent baselines of text, as well as the separation between the text and its anchor point." + }, + "lineWidth": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line width in ems (e.g., 10 for about 20 characters); defaults to infinity, disabling wrapping and clipping.\n\nIf **textOverflow** is null, lines will be wrapped at the specified length. If a line is split at a soft hyphen (\\xad), a hyphen (-) will be displayed at the end of the line. If **textOverflow** is not null, lines will be clipped according to the given strategy." + }, + "monospace": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, changes the default **fontFamily** to *monospace*, and uses simplified monospaced text metrics calculations." + }, + "pathFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The image filter for the tip’s box; defaults to a drop shadow." + }, + "pointer": { + "$ref": "#/definitions/TipPointer" + }, + "pointerSize": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The size of the tip’s pointer in pixels; defaults to 12." + }, + "preferredAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If an explicit tip anchor is not specified, an anchor is chosen automatically such that the tip fits within the plot’s frame; if the preferred anchor fits, it is chosen." + }, + "textAnchor": { + "anyOf": [ + { + "const": "start", + "type": "string" + }, + { + "const": "middle", + "type": "string" + }, + { + "const": "end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [text anchor][1] controls how text is aligned (typically horizontally) relative to its anchor point; it is one of *start*, *end*, or *middle*. If the frame anchor is *left*, *top-left*, or *bottom-left*, the default text anchor is *start*; if the frame anchor is *right*, *top-right*, or\n*bottom-right*, the default is *end*; otherwise it is *middle*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/text-anchor" + }, + "textOverflow": { + "anyOf": [ + { + "type": "null" + }, + { + "const": "clip", + "type": "string" + }, + { + "const": "ellipsis", + "type": "string" + }, + { + "const": "clip-start", + "type": "string" + }, + { + "const": "clip-end", + "type": "string" + }, + { + "const": "ellipsis-start", + "type": "string" + }, + { + "const": "ellipsis-middle", + "type": "string" + }, + { + "const": "ellipsis-end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How truncate (or wrap) lines of text longer than the given **lineWidth**; one of:\n\n- null (default) - preserve overflowing characters (and wrap if needed)\n- *clip* or *clip-end* - remove characters from the end\n- *clip-start* - remove characters from the start\n- *ellipsis* or *ellipsis-end* - replace characters from the end with an ellipsis (…)\n- *ellipsis-start* - replace characters from the start with an ellipsis (…)\n- *ellipsis-middle* - replace characters from the middle with an ellipsis (…)\n\nIf no **title** was specified, if text requires truncation, a title containing the non-truncated text will be implicitly added." + }, + "textPadding": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The padding around the text in pixels; defaults to 8." + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + } + }, + "type": "object" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to generate a tooltip for this mark, and any tip options." + }, + "title": { + "$ref": "#/definitions/ChannelValue", + "description": "The title; a channel specifying accessible, short textual descriptions as strings (possibly with newlines). If the tip option is specified, the title will be displayed with an interactive tooltip instead of using the SVG [title element][1].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/title" + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel, typically bound to the *x* scale." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel, typically bound to the *y* scale." + }, + "z": { + "$ref": "#/definitions/ChannelValue", + "description": "An optional ordinal channel for grouping to produce multiple (possibly overlapping) triangulations." + } + }, + "required": [ + "data", + "mark" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "$schema": { + "description": "A [JSON schema](http://json-schema.org/) URL for this specification, such as https://uwdata.github.io/mosaic/schema/latest.json. This property enables validation and autocomplete in editors with JSON schema support.", + "format": "uri", + "type": "string" + }, + "ariaDescription": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-description][1]; a constant textual description.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-description" + }, + "ariaHidden": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-hidden][1] state; a constant indicating whether the element is exposed to an accessibility API.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-hidden" + }, + "ariaLabel": { + "$ref": "#/definitions/ChannelValue", + "description": "The [aria-label][1]; a channel specifying short textual labels representing the value in the accessibility tree.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-label" + }, + "clip": { + "anyOf": [ + { + "const": "frame", + "type": "string" + }, + { + "const": "sphere", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to clip the mark; one of:\n\n- *frame* or true - clip to the plot’s frame (inner area)\n- *sphere* - clip to the projected sphere (*e.g.*, front hemisphere)\n- null or false - do not clip\n\nThe *sphere* clip option requires a geographic projection." + }, + "config": { + "$ref": "#/definitions/Config", + "description": "Configuration options." + }, + "curve": { + "anyOf": [ + { + "$ref": "#/definitions/Curve" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The curve (interpolation) method for connecting adjacent points. One of:\n\n- *basis* - a cubic basis spline (repeating the end points)\n- *basis-open* - an open cubic basis spline\n- *basis-closed* - a closed cubic basis spline\n- *bump-x* - a Bézier curve with horizontal tangents\n- *bump-y* - a Bézier curve with vertical tangents\n- *bundle* - a straightened cubic basis spline (suitable for lines only, not areas)\n- *cardinal* - a cubic cardinal spline (with one-sided differences at the ends)\n- *cardinal-open* - an open cubic cardinal spline\n- *cardinal-closed* - an closed cubic cardinal spline\n- *catmull-rom* - a cubic Catmull–Rom spline (with one-sided differences at the ends)\n- *catmull-rom-open* - an open cubic Catmull–Rom spline\n- *catmull-rom-closed* - a closed cubic Catmull–Rom spline\n- *linear* - a piecewise linear curve (*i.e.*, straight line segments)\n- *linear-closed* - a closed piecewise linear curve (*i.e.*, straight line segments)\n- *monotone-x* - a cubic spline that preserves monotonicity in *x*\n- *monotone-y* - a cubic spline that preserves monotonicity in *y*\n- *natural* - a natural cubic spline\n- *step* - a piecewise constant function where *y* changes at the midpoint of *x*\n- *step-after* - a piecewise constant function where *y* changes after *x*\n- *step-before* - a piecewise constant function where *x* changes after *y*" + }, + "data": { + "$ref": "#/definitions/Data", + "description": "Dataset definitions." + }, + "dx": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The horizontal offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "dy": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The vertical offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "facet": { + "anyOf": [ + { + "const": "auto", + "type": "string" + }, + { + "const": "include", + "type": "string" + }, + { + "const": "exclude", + "type": "string" + }, + { + "const": "super", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to enable or disable faceting; one of:\n\n- *auto* (default) - automatically determine if this mark should be faceted\n- *include* (or true) - draw the subset of the mark’s data in the current facet\n- *exclude* - draw the subset of the mark’s data *not* in the current facet\n- *super* - draw this mark in a single frame that covers all facets\n- null (or false) - repeat this mark’s data across all facets (*i.e.*, no faceting)\n\nWhen a mark uses *super* faceting, it is not allowed to use position scales (*x*, *y*, *fx*, or *fy*); *super* faceting is intended for decorations, such as labels and legends.\n\nWhen top-level faceting is used, the default *auto* setting is equivalent to *include* when the mark data is strictly equal to the top-level facet data; otherwise it is equivalent to null. When the *include* or *exclude* facet mode is chosen, the mark data must be parallel to the top-level facet data: the data must have the same length and order. If the data are not parallel, then the wrong data may be shown in each facet. The default\n*auto* therefore requires strict equality (`===`) for safety, and using the facet data as mark data is recommended when using the *exclude* facet mode. (To construct parallel data safely, consider using [*array*.map][1] on the facet data.)\n\nWhen mark-level faceting is used, the default *auto* setting is equivalent to *include*: the mark will be faceted if either the **fx** or **fy** channel option (or both) is specified. The null or false option will disable faceting, while *exclude* draws the subset of the mark’s data *not* in the current facet.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map" + }, + "facetAnchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "right", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "const": "left", + "type": "string" + }, + { + "const": "top-left", + "type": "string" + }, + { + "const": "top-right", + "type": "string" + }, + { + "const": "bottom-left", + "type": "string" + }, + { + "const": "bottom-right", + "type": "string" + }, + { + "const": "top-empty", + "type": "string" + }, + { + "const": "right-empty", + "type": "string" + }, + { + "const": "bottom-empty", + "type": "string" + }, + { + "const": "left-empty", + "type": "string" + }, + { + "const": "empty", + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to place the mark with respect to facets; one of:\n\n- null (default for most marks) - display the mark in each non-empty facet\n- *top*, *right*, *bottom*, or *left* - display the mark only in facets on the given side\n- *top-empty*, *right-empty*, *bottom-empty*, or *left-empty* (default for axis marks) - display the mark only in facets that have empty space on the given side: either the margin, or an empty facet\n- *empty* - display the mark in empty facets only" + }, + "fill": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill" + }, + "fillOpacity": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill-opacity][1]; a constant number between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill-opacity" + }, + "filter": { + "$ref": "#/definitions/ChannelValue", + "description": "Applies a transform to filter the mark’s index according to the given channel values; only truthy values are retained.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "fx": { + "$ref": "#/definitions/ChannelValue", + "description": "The horizontal facet position channel, for mark-level faceting, bound to the *fx* scale." + }, + "fy": { + "$ref": "#/definitions/ChannelValue", + "description": "The vertical facet position channel, for mark-level faceting, bound to the\n*fy* scale." + }, + "href": { + "$ref": "#/definitions/ChannelValue", + "description": "The [href][1]; a channel specifying URLs for clickable links. May be used in conjunction with the **target** option to open links in another window.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/href" + }, + "imageFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A CSS [filter][1]; a constant string used to adjust the rendering of images, such as *blur(5px)*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/filter" + }, + "margin": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four mark margins: **marginTop**,\n**marginRight**, **marginBottom**, and **marginLeft**; typically defaults to 0, except for axis marks." + }, + "marginBottom": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s bottom margin; the minimum distance in pixels between the bottom edges of the inner and outer plot area." + }, + "marginLeft": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s left margin; the minimum distance in pixels between the left edges of the inner and outer plot area." + }, + "marginRight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s right margin; the minimum distance in pixels between the right edges of the mark’s inner and outer plot area." + }, + "marginTop": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s top margin; the minimum distance in pixels between the top edges of the inner and outer plot area." + }, + "mark": { + "const": "hull", + "description": "A mark that draws a convex hull around the points given by the **x** and\n**y** channels. The **stroke** option defaults to _currentColor_ and the\n**fill** option defaults to _none_. When an aesthetic channel is specified (such as **stroke** or **strokeWidth**), the hull inherits the corresponding channel value from one of its constituent points arbitrarily.\n\nIf **z** is specified, the input points are grouped by *z*, producing a separate hull for each group. If **z** is not specified, it defaults to the **fill** channel, if any, or the **stroke** channel, if any.", + "type": "string" + }, + "marker": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for markerStart, markerMid, and markerEnd; one of:\n\n- a marker name such as *arrow* or *circle*\n- *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*" + }, + "markerEnd": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The marker for the ending point of a line segment; one of:\n\n- a marker name such as *arrow* or *circle*\n* *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*" + }, + "markerMid": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The marker for any middle (interior) points of a line segment. If the line segment only has a start and end point, this option has no effect. One of:\n\n- a marker name such as *arrow* or *circle*\n* *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*\n* a function - a custom marker function; see below" + }, + "markerStart": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The marker for the starting point of a line segment; one of:\n\n- a marker name such as *arrow* or *circle*\n* *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*" + }, + "meta": { + "$ref": "#/definitions/Meta", + "description": "Specification metadata." + }, + "mixBlendMode": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [mix-blend-mode][1]; a constant string specifying how to blend content such as *multiply*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode" + }, + "opacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally. For faster rendering, prefer the **strokeOpacity** or **fillOpacity** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/opacity" + }, + "paintOrder": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [paint-order][1]; a constant string specifying the order in which the\n**fill**, **stroke**, and any markers are drawn; defaults to *normal*, which draws the fill, then stroke, then markers; defaults to *stroke* for the text mark to create a “halo” around text to improve legibility.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/paint-order" + }, + "params": { + "$ref": "#/definitions/Params", + "description": "Param and Selection definitions." + }, + "plotDefaults": { + "$ref": "#/definitions/PlotAttributes", + "description": "A default set of attributes to apply to all plot components." + }, + "pointerEvents": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [pointer-events][1] property; a constant string such as *none*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/pointer-events" + }, + "reverse": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Applies a transform to reverse the order of the mark’s index, say for reverse input order." + }, + "select": { + "$ref": "#/definitions/SelectFilter", + "description": "Applies a filter transform after data is loaded to highlight selected values only. For example, `first` and `last` select the first or last values of series only (using the *z* channel to separate series). Meanwhile, `nearestX` and `nearestY` select the point nearest to the pointer along the *x* or *y* channel dimension. Unlike Mosaic selections, a mark level *select* is internal to the mark only, and does not populate a param or selection value to be shared across clients.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "shapeRendering": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [shape-rendering][1]; a constant string such as *crispEdges*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/shape-rendering" + }, + "sort": { + "anyOf": [ + { + "$ref": "#/definitions/SortOrder" + }, + { + "$ref": "#/definitions/ChannelDomainSort" + } + ], + "description": "Either applies a transform to sort the mark’s index by the specified channel values, or imputes ordinal scale domains from this mark’s channels.\n\nWhen imputing ordinal scale domains from channel values, the **sort** option is an object whose keys are ordinal scale names such as *x* or *fx*, and whose values are channel names such as *y*, *y1*, or *y2*. For example, to impute the *y* scale’s domain from the associated *x* channel values in ascending order:\n\n```js sort: {y: \"x\"} ```\n\nFor different sort options for different scales, replace the channel name with a *value* object and per-scale options:\n\n```js sort: {y: {value: \"-x\"}} ```\n\nWhen sorting the mark’s index, the **sort** option is instead one of:\n\n- a channel value definition for sorting given values in ascending order\n- a {value, order} object for sorting given values\n- a {channel, order} object for sorting the named channel’s values" + }, + "stroke": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke" + }, + "strokeDasharray": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dasharray][1]; a constant number indicating the length in pixels of alternating dashes and gaps, or a constant string of numbers separated by spaces or commas (_e.g._, *10 2* for dashes of 10 pixels separated by gaps of 2 pixels), or *none* (the default) for no dashing\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dasharray" + }, + "strokeDashoffset": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dashoffset][1]; a constant indicating the offset in pixels of the first dash along the stroke; defaults to zero.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dashoffset" + }, + "strokeLinecap": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linecap][1]; a constant specifying how to cap stroked paths, such as *butt*, *round*, or *square*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linecap" + }, + "strokeLinejoin": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linejoin][1]; a constant specifying how to join stroked paths, such as *bevel*, *miter*, *miter-clip*, or *round*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linejoin" + }, + "strokeMiterlimit": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-miterlimit][1]; a constant number specifying how to limit the length of *miter* joins on stroked paths.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-miterlimit" + }, + "strokeOpacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-opacity" + }, + "strokeWidth": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-width][1]; a constant number in pixels, or a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-width" + }, + "target": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [target][1]; a constant string specifying the target window (_e.g._,\n*_blank*) for clickable links; used in conjunction with the **href** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/target" + }, + "tension": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The tension option only has an effect on bundle, cardinal and Catmull–Rom splines (*bundle*, *cardinal*, *cardinal-open*, *cardinal-closed*,\n*catmull-rom*, *catmull-rom-open*, and *catmull-rom-closed*). For bundle splines, it corresponds to [beta][1]; for cardinal splines, [tension][2]; for Catmull–Rom splines, [alpha][3].\n\n[1]: https://d3js.org/d3-shape/curve#curveBundle_beta [2]: https://d3js.org/d3-shape/curve#curveCardinal_tension [3]: https://d3js.org/d3-shape/curve#curveCatmullRom_alpha" + }, + "tip": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/TipPointer" + }, + { + "properties": { + "anchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The tip anchor specifies how to orient the tip box relative to its anchor position; it refers to the part of the tip box that is attached to the anchor point. For example, the *top-left* anchor places the top-left corner of tip box near the anchor position, hence placing the tip box below and to the right of the anchor position." + }, + "fontFamily": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font-family][1]; a constant; defaults to the plot’s font family, which is typically [*system-ui*][2].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-family [2]: https://drafts.csswg.org/css-fonts-4/#valdef-font-family-system-ui" + }, + "fontSize": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font size][1] in pixels; either a constant or a channel; defaults to the plot’s font size, which is typically 10. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-size" + }, + "fontStyle": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font style][1]; a constant; defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-style" + }, + "fontVariant": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font variant][1]; a constant; if the **text** channel contains numbers or dates, defaults to *tabular-nums* to facilitate comparing numbers; otherwise defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant" + }, + "fontWeight": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font weight][1]; a constant; defaults to the plot’s font weight, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight" + }, + "format": { + "additionalProperties": false, + "description": "How channel values are formatted for display. If a format is a string, it is interpreted as a (UTC) time format for temporal channels, and otherwise a number format.", + "properties": { + "ariaLabel": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fill": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fillOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fontSize": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fx": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fy": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "geometry": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "height": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "href": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "length": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "opacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "path": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "r": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "rotate": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "src": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "stroke": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeWidth": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "symbol": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "text": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "title": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "weight": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "width": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "z": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + } + }, + "type": "object" + }, + "frameAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The frame anchor specifies defaults for **x** and **y** based on the plot’s frame; it may be one of the four sides (*top*, *right*, *bottom*, *left*), one of the four corners (*top-left*, *top-right*, *bottom-right*,\n*bottom-left*), or the *middle* of the frame. For example, for tips distributed horizontally at the top of the frame:\n\n```js Plot.tip(data, {x: \"date\", frameAnchor: \"top\"}) ```" + }, + "lineHeight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line height in ems; defaults to 1. The line height affects the (typically vertical) separation between adjacent baselines of text, as well as the separation between the text and its anchor point." + }, + "lineWidth": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line width in ems (e.g., 10 for about 20 characters); defaults to infinity, disabling wrapping and clipping.\n\nIf **textOverflow** is null, lines will be wrapped at the specified length. If a line is split at a soft hyphen (\\xad), a hyphen (-) will be displayed at the end of the line. If **textOverflow** is not null, lines will be clipped according to the given strategy." + }, + "monospace": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, changes the default **fontFamily** to *monospace*, and uses simplified monospaced text metrics calculations." + }, + "pathFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The image filter for the tip’s box; defaults to a drop shadow." + }, + "pointer": { + "$ref": "#/definitions/TipPointer" + }, + "pointerSize": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The size of the tip’s pointer in pixels; defaults to 12." + }, + "preferredAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If an explicit tip anchor is not specified, an anchor is chosen automatically such that the tip fits within the plot’s frame; if the preferred anchor fits, it is chosen." + }, + "textAnchor": { + "anyOf": [ + { + "const": "start", + "type": "string" + }, + { + "const": "middle", + "type": "string" + }, + { + "const": "end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [text anchor][1] controls how text is aligned (typically horizontally) relative to its anchor point; it is one of *start*, *end*, or *middle*. If the frame anchor is *left*, *top-left*, or *bottom-left*, the default text anchor is *start*; if the frame anchor is *right*, *top-right*, or\n*bottom-right*, the default is *end*; otherwise it is *middle*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/text-anchor" + }, + "textOverflow": { + "anyOf": [ + { + "type": "null" + }, + { + "const": "clip", + "type": "string" + }, + { + "const": "ellipsis", + "type": "string" + }, + { + "const": "clip-start", + "type": "string" + }, + { + "const": "clip-end", + "type": "string" + }, + { + "const": "ellipsis-start", + "type": "string" + }, + { + "const": "ellipsis-middle", + "type": "string" + }, + { + "const": "ellipsis-end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How truncate (or wrap) lines of text longer than the given **lineWidth**; one of:\n\n- null (default) - preserve overflowing characters (and wrap if needed)\n- *clip* or *clip-end* - remove characters from the end\n- *clip-start* - remove characters from the start\n- *ellipsis* or *ellipsis-end* - replace characters from the end with an ellipsis (…)\n- *ellipsis-start* - replace characters from the start with an ellipsis (…)\n- *ellipsis-middle* - replace characters from the middle with an ellipsis (…)\n\nIf no **title** was specified, if text requires truncation, a title containing the non-truncated text will be implicitly added." + }, + "textPadding": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The padding around the text in pixels; defaults to 8." + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + } + }, + "type": "object" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to generate a tooltip for this mark, and any tip options." + }, + "title": { + "$ref": "#/definitions/ChannelValue", + "description": "The title; a channel specifying accessible, short textual descriptions as strings (possibly with newlines). If the tip option is specified, the title will be displayed with an interactive tooltip instead of using the SVG [title element][1].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/title" + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel, typically bound to the *x* scale." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel, typically bound to the *y* scale." + }, + "z": { + "$ref": "#/definitions/ChannelValue", + "description": "An optional ordinal channel for grouping to produce multiple (possibly overlapping) triangulations." + } + }, + "required": [ + "data", + "mark" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "$schema": { + "description": "A [JSON schema](http://json-schema.org/) URL for this specification, such as https://uwdata.github.io/mosaic/schema/latest.json. This property enables validation and autocomplete in editors with JSON schema support.", + "format": "uri", + "type": "string" + }, + "ariaDescription": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-description][1]; a constant textual description.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-description" + }, + "ariaHidden": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-hidden][1] state; a constant indicating whether the element is exposed to an accessibility API.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-hidden" + }, + "ariaLabel": { + "$ref": "#/definitions/ChannelValue", + "description": "The [aria-label][1]; a channel specifying short textual labels representing the value in the accessibility tree.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-label" + }, + "clip": { + "anyOf": [ + { + "const": "frame", + "type": "string" + }, + { + "const": "sphere", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to clip the mark; one of:\n\n- *frame* or true - clip to the plot’s frame (inner area)\n- *sphere* - clip to the projected sphere (*e.g.*, front hemisphere)\n- null or false - do not clip\n\nThe *sphere* clip option requires a geographic projection." + }, + "config": { + "$ref": "#/definitions/Config", + "description": "Configuration options." + }, + "curve": { + "anyOf": [ + { + "$ref": "#/definitions/Curve" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The curve (interpolation) method for connecting adjacent points. One of:\n\n- *basis* - a cubic basis spline (repeating the end points)\n- *basis-open* - an open cubic basis spline\n- *basis-closed* - a closed cubic basis spline\n- *bump-x* - a Bézier curve with horizontal tangents\n- *bump-y* - a Bézier curve with vertical tangents\n- *bundle* - a straightened cubic basis spline (suitable for lines only, not areas)\n- *cardinal* - a cubic cardinal spline (with one-sided differences at the ends)\n- *cardinal-open* - an open cubic cardinal spline\n- *cardinal-closed* - an closed cubic cardinal spline\n- *catmull-rom* - a cubic Catmull–Rom spline (with one-sided differences at the ends)\n- *catmull-rom-open* - an open cubic Catmull–Rom spline\n- *catmull-rom-closed* - a closed cubic Catmull–Rom spline\n- *linear* - a piecewise linear curve (*i.e.*, straight line segments)\n- *linear-closed* - a closed piecewise linear curve (*i.e.*, straight line segments)\n- *monotone-x* - a cubic spline that preserves monotonicity in *x*\n- *monotone-y* - a cubic spline that preserves monotonicity in *y*\n- *natural* - a natural cubic spline\n- *step* - a piecewise constant function where *y* changes at the midpoint of *x*\n- *step-after* - a piecewise constant function where *y* changes after *x*\n- *step-before* - a piecewise constant function where *x* changes after *y*" + }, + "data": { + "$ref": "#/definitions/Data", + "description": "Dataset definitions." + }, + "dx": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The horizontal offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "dy": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The vertical offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "facet": { + "anyOf": [ + { + "const": "auto", + "type": "string" + }, + { + "const": "include", + "type": "string" + }, + { + "const": "exclude", + "type": "string" + }, + { + "const": "super", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to enable or disable faceting; one of:\n\n- *auto* (default) - automatically determine if this mark should be faceted\n- *include* (or true) - draw the subset of the mark’s data in the current facet\n- *exclude* - draw the subset of the mark’s data *not* in the current facet\n- *super* - draw this mark in a single frame that covers all facets\n- null (or false) - repeat this mark’s data across all facets (*i.e.*, no faceting)\n\nWhen a mark uses *super* faceting, it is not allowed to use position scales (*x*, *y*, *fx*, or *fy*); *super* faceting is intended for decorations, such as labels and legends.\n\nWhen top-level faceting is used, the default *auto* setting is equivalent to *include* when the mark data is strictly equal to the top-level facet data; otherwise it is equivalent to null. When the *include* or *exclude* facet mode is chosen, the mark data must be parallel to the top-level facet data: the data must have the same length and order. If the data are not parallel, then the wrong data may be shown in each facet. The default\n*auto* therefore requires strict equality (`===`) for safety, and using the facet data as mark data is recommended when using the *exclude* facet mode. (To construct parallel data safely, consider using [*array*.map][1] on the facet data.)\n\nWhen mark-level faceting is used, the default *auto* setting is equivalent to *include*: the mark will be faceted if either the **fx** or **fy** channel option (or both) is specified. The null or false option will disable faceting, while *exclude* draws the subset of the mark’s data *not* in the current facet.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map" + }, + "facetAnchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "right", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "const": "left", + "type": "string" + }, + { + "const": "top-left", + "type": "string" + }, + { + "const": "top-right", + "type": "string" + }, + { + "const": "bottom-left", + "type": "string" + }, + { + "const": "bottom-right", + "type": "string" + }, + { + "const": "top-empty", + "type": "string" + }, + { + "const": "right-empty", + "type": "string" + }, + { + "const": "bottom-empty", + "type": "string" + }, + { + "const": "left-empty", + "type": "string" + }, + { + "const": "empty", + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to place the mark with respect to facets; one of:\n\n- null (default for most marks) - display the mark in each non-empty facet\n- *top*, *right*, *bottom*, or *left* - display the mark only in facets on the given side\n- *top-empty*, *right-empty*, *bottom-empty*, or *left-empty* (default for axis marks) - display the mark only in facets that have empty space on the given side: either the margin, or an empty facet\n- *empty* - display the mark in empty facets only" + }, + "fill": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill" + }, + "fillOpacity": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill-opacity][1]; a constant number between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill-opacity" + }, + "filter": { + "$ref": "#/definitions/ChannelValue", + "description": "Applies a transform to filter the mark’s index according to the given channel values; only truthy values are retained.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "fx": { + "$ref": "#/definitions/ChannelValue", + "description": "The horizontal facet position channel, for mark-level faceting, bound to the *fx* scale." + }, + "fy": { + "$ref": "#/definitions/ChannelValue", + "description": "The vertical facet position channel, for mark-level faceting, bound to the\n*fy* scale." + }, + "href": { + "$ref": "#/definitions/ChannelValue", + "description": "The [href][1]; a channel specifying URLs for clickable links. May be used in conjunction with the **target** option to open links in another window.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/href" + }, + "imageFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A CSS [filter][1]; a constant string used to adjust the rendering of images, such as *blur(5px)*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/filter" + }, + "margin": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four mark margins: **marginTop**,\n**marginRight**, **marginBottom**, and **marginLeft**; typically defaults to 0, except for axis marks." + }, + "marginBottom": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s bottom margin; the minimum distance in pixels between the bottom edges of the inner and outer plot area." + }, + "marginLeft": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s left margin; the minimum distance in pixels between the left edges of the inner and outer plot area." + }, + "marginRight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s right margin; the minimum distance in pixels between the right edges of the mark’s inner and outer plot area." + }, + "marginTop": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s top margin; the minimum distance in pixels between the top edges of the inner and outer plot area." + }, + "mark": { + "const": "voronoi", + "description": "A mark that draws polygons for each cell of the Voronoi tesselation of the points given by the **x** and **y** channels.\n\nIf **z** is specified, the input points are grouped by *z*, producing a separate Voronoi tesselation for each group.", + "type": "string" + }, + "marker": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for markerStart, markerMid, and markerEnd; one of:\n\n- a marker name such as *arrow* or *circle*\n- *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*" + }, + "markerEnd": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The marker for the ending point of a line segment; one of:\n\n- a marker name such as *arrow* or *circle*\n* *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*" + }, + "markerMid": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The marker for any middle (interior) points of a line segment. If the line segment only has a start and end point, this option has no effect. One of:\n\n- a marker name such as *arrow* or *circle*\n* *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*\n* a function - a custom marker function; see below" + }, + "markerStart": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The marker for the starting point of a line segment; one of:\n\n- a marker name such as *arrow* or *circle*\n* *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*" + }, + "meta": { + "$ref": "#/definitions/Meta", + "description": "Specification metadata." + }, + "mixBlendMode": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [mix-blend-mode][1]; a constant string specifying how to blend content such as *multiply*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode" + }, + "opacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally. For faster rendering, prefer the **strokeOpacity** or **fillOpacity** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/opacity" + }, + "paintOrder": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [paint-order][1]; a constant string specifying the order in which the\n**fill**, **stroke**, and any markers are drawn; defaults to *normal*, which draws the fill, then stroke, then markers; defaults to *stroke* for the text mark to create a “halo” around text to improve legibility.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/paint-order" + }, + "params": { + "$ref": "#/definitions/Params", + "description": "Param and Selection definitions." + }, + "plotDefaults": { + "$ref": "#/definitions/PlotAttributes", + "description": "A default set of attributes to apply to all plot components." + }, + "pointerEvents": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [pointer-events][1] property; a constant string such as *none*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/pointer-events" + }, + "reverse": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Applies a transform to reverse the order of the mark’s index, say for reverse input order." + }, + "select": { + "$ref": "#/definitions/SelectFilter", + "description": "Applies a filter transform after data is loaded to highlight selected values only. For example, `first` and `last` select the first or last values of series only (using the *z* channel to separate series). Meanwhile, `nearestX` and `nearestY` select the point nearest to the pointer along the *x* or *y* channel dimension. Unlike Mosaic selections, a mark level *select* is internal to the mark only, and does not populate a param or selection value to be shared across clients.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "shapeRendering": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [shape-rendering][1]; a constant string such as *crispEdges*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/shape-rendering" + }, + "sort": { + "anyOf": [ + { + "$ref": "#/definitions/SortOrder" + }, + { + "$ref": "#/definitions/ChannelDomainSort" + } + ], + "description": "Either applies a transform to sort the mark’s index by the specified channel values, or imputes ordinal scale domains from this mark’s channels.\n\nWhen imputing ordinal scale domains from channel values, the **sort** option is an object whose keys are ordinal scale names such as *x* or *fx*, and whose values are channel names such as *y*, *y1*, or *y2*. For example, to impute the *y* scale’s domain from the associated *x* channel values in ascending order:\n\n```js sort: {y: \"x\"} ```\n\nFor different sort options for different scales, replace the channel name with a *value* object and per-scale options:\n\n```js sort: {y: {value: \"-x\"}} ```\n\nWhen sorting the mark’s index, the **sort** option is instead one of:\n\n- a channel value definition for sorting given values in ascending order\n- a {value, order} object for sorting given values\n- a {channel, order} object for sorting the named channel’s values" + }, + "stroke": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke" + }, + "strokeDasharray": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dasharray][1]; a constant number indicating the length in pixels of alternating dashes and gaps, or a constant string of numbers separated by spaces or commas (_e.g._, *10 2* for dashes of 10 pixels separated by gaps of 2 pixels), or *none* (the default) for no dashing\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dasharray" + }, + "strokeDashoffset": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dashoffset][1]; a constant indicating the offset in pixels of the first dash along the stroke; defaults to zero.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dashoffset" + }, + "strokeLinecap": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linecap][1]; a constant specifying how to cap stroked paths, such as *butt*, *round*, or *square*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linecap" + }, + "strokeLinejoin": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linejoin][1]; a constant specifying how to join stroked paths, such as *bevel*, *miter*, *miter-clip*, or *round*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linejoin" + }, + "strokeMiterlimit": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-miterlimit][1]; a constant number specifying how to limit the length of *miter* joins on stroked paths.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-miterlimit" + }, + "strokeOpacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-opacity" + }, + "strokeWidth": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-width][1]; a constant number in pixels, or a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-width" + }, + "target": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [target][1]; a constant string specifying the target window (_e.g._,\n*_blank*) for clickable links; used in conjunction with the **href** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/target" + }, + "tension": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The tension option only has an effect on bundle, cardinal and Catmull–Rom splines (*bundle*, *cardinal*, *cardinal-open*, *cardinal-closed*,\n*catmull-rom*, *catmull-rom-open*, and *catmull-rom-closed*). For bundle splines, it corresponds to [beta][1]; for cardinal splines, [tension][2]; for Catmull–Rom splines, [alpha][3].\n\n[1]: https://d3js.org/d3-shape/curve#curveBundle_beta [2]: https://d3js.org/d3-shape/curve#curveCardinal_tension [3]: https://d3js.org/d3-shape/curve#curveCatmullRom_alpha" + }, + "tip": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/TipPointer" + }, + { + "properties": { + "anchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The tip anchor specifies how to orient the tip box relative to its anchor position; it refers to the part of the tip box that is attached to the anchor point. For example, the *top-left* anchor places the top-left corner of tip box near the anchor position, hence placing the tip box below and to the right of the anchor position." + }, + "fontFamily": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font-family][1]; a constant; defaults to the plot’s font family, which is typically [*system-ui*][2].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-family [2]: https://drafts.csswg.org/css-fonts-4/#valdef-font-family-system-ui" + }, + "fontSize": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font size][1] in pixels; either a constant or a channel; defaults to the plot’s font size, which is typically 10. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-size" + }, + "fontStyle": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font style][1]; a constant; defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-style" + }, + "fontVariant": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font variant][1]; a constant; if the **text** channel contains numbers or dates, defaults to *tabular-nums* to facilitate comparing numbers; otherwise defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant" + }, + "fontWeight": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font weight][1]; a constant; defaults to the plot’s font weight, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight" + }, + "format": { + "additionalProperties": false, + "description": "How channel values are formatted for display. If a format is a string, it is interpreted as a (UTC) time format for temporal channels, and otherwise a number format.", + "properties": { + "ariaLabel": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fill": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fillOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fontSize": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fx": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fy": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "geometry": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "height": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "href": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "length": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "opacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "path": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "r": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "rotate": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "src": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "stroke": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeWidth": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "symbol": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "text": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "title": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "weight": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "width": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "z": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + } + }, + "type": "object" + }, + "frameAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The frame anchor specifies defaults for **x** and **y** based on the plot’s frame; it may be one of the four sides (*top*, *right*, *bottom*, *left*), one of the four corners (*top-left*, *top-right*, *bottom-right*,\n*bottom-left*), or the *middle* of the frame. For example, for tips distributed horizontally at the top of the frame:\n\n```js Plot.tip(data, {x: \"date\", frameAnchor: \"top\"}) ```" + }, + "lineHeight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line height in ems; defaults to 1. The line height affects the (typically vertical) separation between adjacent baselines of text, as well as the separation between the text and its anchor point." + }, + "lineWidth": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line width in ems (e.g., 10 for about 20 characters); defaults to infinity, disabling wrapping and clipping.\n\nIf **textOverflow** is null, lines will be wrapped at the specified length. If a line is split at a soft hyphen (\\xad), a hyphen (-) will be displayed at the end of the line. If **textOverflow** is not null, lines will be clipped according to the given strategy." + }, + "monospace": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, changes the default **fontFamily** to *monospace*, and uses simplified monospaced text metrics calculations." + }, + "pathFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The image filter for the tip’s box; defaults to a drop shadow." + }, + "pointer": { + "$ref": "#/definitions/TipPointer" + }, + "pointerSize": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The size of the tip’s pointer in pixels; defaults to 12." + }, + "preferredAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If an explicit tip anchor is not specified, an anchor is chosen automatically such that the tip fits within the plot’s frame; if the preferred anchor fits, it is chosen." + }, + "textAnchor": { + "anyOf": [ + { + "const": "start", + "type": "string" + }, + { + "const": "middle", + "type": "string" + }, + { + "const": "end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [text anchor][1] controls how text is aligned (typically horizontally) relative to its anchor point; it is one of *start*, *end*, or *middle*. If the frame anchor is *left*, *top-left*, or *bottom-left*, the default text anchor is *start*; if the frame anchor is *right*, *top-right*, or\n*bottom-right*, the default is *end*; otherwise it is *middle*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/text-anchor" + }, + "textOverflow": { + "anyOf": [ + { + "type": "null" + }, + { + "const": "clip", + "type": "string" + }, + { + "const": "ellipsis", + "type": "string" + }, + { + "const": "clip-start", + "type": "string" + }, + { + "const": "clip-end", + "type": "string" + }, + { + "const": "ellipsis-start", + "type": "string" + }, + { + "const": "ellipsis-middle", + "type": "string" + }, + { + "const": "ellipsis-end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How truncate (or wrap) lines of text longer than the given **lineWidth**; one of:\n\n- null (default) - preserve overflowing characters (and wrap if needed)\n- *clip* or *clip-end* - remove characters from the end\n- *clip-start* - remove characters from the start\n- *ellipsis* or *ellipsis-end* - replace characters from the end with an ellipsis (…)\n- *ellipsis-start* - replace characters from the start with an ellipsis (…)\n- *ellipsis-middle* - replace characters from the middle with an ellipsis (…)\n\nIf no **title** was specified, if text requires truncation, a title containing the non-truncated text will be implicitly added." + }, + "textPadding": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The padding around the text in pixels; defaults to 8." + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + } + }, + "type": "object" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to generate a tooltip for this mark, and any tip options." + }, + "title": { + "$ref": "#/definitions/ChannelValue", + "description": "The title; a channel specifying accessible, short textual descriptions as strings (possibly with newlines). If the tip option is specified, the title will be displayed with an interactive tooltip instead of using the SVG [title element][1].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/title" + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel, typically bound to the *x* scale." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel, typically bound to the *y* scale." + }, + "z": { + "$ref": "#/definitions/ChannelValue", + "description": "An optional ordinal channel for grouping to produce multiple (possibly overlapping) triangulations." + } + }, + "required": [ + "data", + "mark" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "$schema": { + "description": "A [JSON schema](http://json-schema.org/) URL for this specification, such as https://uwdata.github.io/mosaic/schema/latest.json. This property enables validation and autocomplete in editors with JSON schema support.", + "format": "uri", + "type": "string" + }, + "ariaDescription": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-description][1]; a constant textual description.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-description" + }, + "ariaHidden": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-hidden][1] state; a constant indicating whether the element is exposed to an accessibility API.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-hidden" + }, + "ariaLabel": { + "$ref": "#/definitions/ChannelValue", + "description": "The [aria-label][1]; a channel specifying short textual labels representing the value in the accessibility tree.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-label" + }, + "clip": { + "anyOf": [ + { + "const": "frame", + "type": "string" + }, + { + "const": "sphere", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to clip the mark; one of:\n\n- *frame* or true - clip to the plot’s frame (inner area)\n- *sphere* - clip to the projected sphere (*e.g.*, front hemisphere)\n- null or false - do not clip\n\nThe *sphere* clip option requires a geographic projection." + }, + "config": { + "$ref": "#/definitions/Config", + "description": "Configuration options." + }, + "curve": { + "anyOf": [ + { + "$ref": "#/definitions/Curve" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The curve (interpolation) method for connecting adjacent points. One of:\n\n- *basis* - a cubic basis spline (repeating the end points)\n- *basis-open* - an open cubic basis spline\n- *basis-closed* - a closed cubic basis spline\n- *bump-x* - a Bézier curve with horizontal tangents\n- *bump-y* - a Bézier curve with vertical tangents\n- *bundle* - a straightened cubic basis spline (suitable for lines only, not areas)\n- *cardinal* - a cubic cardinal spline (with one-sided differences at the ends)\n- *cardinal-open* - an open cubic cardinal spline\n- *cardinal-closed* - an closed cubic cardinal spline\n- *catmull-rom* - a cubic Catmull–Rom spline (with one-sided differences at the ends)\n- *catmull-rom-open* - an open cubic Catmull–Rom spline\n- *catmull-rom-closed* - a closed cubic Catmull–Rom spline\n- *linear* - a piecewise linear curve (*i.e.*, straight line segments)\n- *linear-closed* - a closed piecewise linear curve (*i.e.*, straight line segments)\n- *monotone-x* - a cubic spline that preserves monotonicity in *x*\n- *monotone-y* - a cubic spline that preserves monotonicity in *y*\n- *natural* - a natural cubic spline\n- *step* - a piecewise constant function where *y* changes at the midpoint of *x*\n- *step-after* - a piecewise constant function where *y* changes after *x*\n- *step-before* - a piecewise constant function where *x* changes after *y*" + }, + "data": { + "$ref": "#/definitions/Data", + "description": "Dataset definitions." + }, + "dx": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The horizontal offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "dy": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The vertical offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "facet": { + "anyOf": [ + { + "const": "auto", + "type": "string" + }, + { + "const": "include", + "type": "string" + }, + { + "const": "exclude", + "type": "string" + }, + { + "const": "super", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to enable or disable faceting; one of:\n\n- *auto* (default) - automatically determine if this mark should be faceted\n- *include* (or true) - draw the subset of the mark’s data in the current facet\n- *exclude* - draw the subset of the mark’s data *not* in the current facet\n- *super* - draw this mark in a single frame that covers all facets\n- null (or false) - repeat this mark’s data across all facets (*i.e.*, no faceting)\n\nWhen a mark uses *super* faceting, it is not allowed to use position scales (*x*, *y*, *fx*, or *fy*); *super* faceting is intended for decorations, such as labels and legends.\n\nWhen top-level faceting is used, the default *auto* setting is equivalent to *include* when the mark data is strictly equal to the top-level facet data; otherwise it is equivalent to null. When the *include* or *exclude* facet mode is chosen, the mark data must be parallel to the top-level facet data: the data must have the same length and order. If the data are not parallel, then the wrong data may be shown in each facet. The default\n*auto* therefore requires strict equality (`===`) for safety, and using the facet data as mark data is recommended when using the *exclude* facet mode. (To construct parallel data safely, consider using [*array*.map][1] on the facet data.)\n\nWhen mark-level faceting is used, the default *auto* setting is equivalent to *include*: the mark will be faceted if either the **fx** or **fy** channel option (or both) is specified. The null or false option will disable faceting, while *exclude* draws the subset of the mark’s data *not* in the current facet.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map" + }, + "facetAnchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "right", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "const": "left", + "type": "string" + }, + { + "const": "top-left", + "type": "string" + }, + { + "const": "top-right", + "type": "string" + }, + { + "const": "bottom-left", + "type": "string" + }, + { + "const": "bottom-right", + "type": "string" + }, + { + "const": "top-empty", + "type": "string" + }, + { + "const": "right-empty", + "type": "string" + }, + { + "const": "bottom-empty", + "type": "string" + }, + { + "const": "left-empty", + "type": "string" + }, + { + "const": "empty", + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to place the mark with respect to facets; one of:\n\n- null (default for most marks) - display the mark in each non-empty facet\n- *top*, *right*, *bottom*, or *left* - display the mark only in facets on the given side\n- *top-empty*, *right-empty*, *bottom-empty*, or *left-empty* (default for axis marks) - display the mark only in facets that have empty space on the given side: either the margin, or an empty facet\n- *empty* - display the mark in empty facets only" + }, + "fill": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill" + }, + "fillOpacity": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill-opacity][1]; a constant number between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill-opacity" + }, + "filter": { + "$ref": "#/definitions/ChannelValue", + "description": "Applies a transform to filter the mark’s index according to the given channel values; only truthy values are retained.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "fx": { + "$ref": "#/definitions/ChannelValue", + "description": "The horizontal facet position channel, for mark-level faceting, bound to the *fx* scale." + }, + "fy": { + "$ref": "#/definitions/ChannelValue", + "description": "The vertical facet position channel, for mark-level faceting, bound to the\n*fy* scale." + }, + "href": { + "$ref": "#/definitions/ChannelValue", + "description": "The [href][1]; a channel specifying URLs for clickable links. May be used in conjunction with the **target** option to open links in another window.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/href" + }, + "imageFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A CSS [filter][1]; a constant string used to adjust the rendering of images, such as *blur(5px)*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/filter" + }, + "margin": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four mark margins: **marginTop**,\n**marginRight**, **marginBottom**, and **marginLeft**; typically defaults to 0, except for axis marks." + }, + "marginBottom": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s bottom margin; the minimum distance in pixels between the bottom edges of the inner and outer plot area." + }, + "marginLeft": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s left margin; the minimum distance in pixels between the left edges of the inner and outer plot area." + }, + "marginRight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s right margin; the minimum distance in pixels between the right edges of the mark’s inner and outer plot area." + }, + "marginTop": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s top margin; the minimum distance in pixels between the top edges of the inner and outer plot area." + }, + "mark": { + "const": "voronoiMesh", + "description": "A mark that draws a mesh for the cell boundaries of the Voronoi tesselation of the points given by the **x** and **y** channels. The\n**stroke** option defaults to _currentColor_, and the **strokeOpacity** defaults to 0.2. The **fill** option is not supported. When an aesthetic channel is specified (such as **stroke** or **strokeWidth**), the mesh inherits the corresponding channel value from one of its constituent points arbitrarily.\n\nIf **z** is specified, the input points are grouped by *z*, producing a separate Voronoi tesselation for each group.", + "type": "string" + }, + "marker": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for markerStart, markerMid, and markerEnd; one of:\n\n- a marker name such as *arrow* or *circle*\n- *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*" + }, + "markerEnd": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The marker for the ending point of a line segment; one of:\n\n- a marker name such as *arrow* or *circle*\n* *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*" + }, + "markerMid": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The marker for any middle (interior) points of a line segment. If the line segment only has a start and end point, this option has no effect. One of:\n\n- a marker name such as *arrow* or *circle*\n* *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*\n* a function - a custom marker function; see below" + }, + "markerStart": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The marker for the starting point of a line segment; one of:\n\n- a marker name such as *arrow* or *circle*\n* *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*" + }, + "meta": { + "$ref": "#/definitions/Meta", + "description": "Specification metadata." + }, + "mixBlendMode": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [mix-blend-mode][1]; a constant string specifying how to blend content such as *multiply*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode" + }, + "opacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally. For faster rendering, prefer the **strokeOpacity** or **fillOpacity** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/opacity" + }, + "paintOrder": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [paint-order][1]; a constant string specifying the order in which the\n**fill**, **stroke**, and any markers are drawn; defaults to *normal*, which draws the fill, then stroke, then markers; defaults to *stroke* for the text mark to create a “halo” around text to improve legibility.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/paint-order" + }, + "params": { + "$ref": "#/definitions/Params", + "description": "Param and Selection definitions." + }, + "plotDefaults": { + "$ref": "#/definitions/PlotAttributes", + "description": "A default set of attributes to apply to all plot components." + }, + "pointerEvents": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [pointer-events][1] property; a constant string such as *none*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/pointer-events" + }, + "reverse": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Applies a transform to reverse the order of the mark’s index, say for reverse input order." + }, + "select": { + "$ref": "#/definitions/SelectFilter", + "description": "Applies a filter transform after data is loaded to highlight selected values only. For example, `first` and `last` select the first or last values of series only (using the *z* channel to separate series). Meanwhile, `nearestX` and `nearestY` select the point nearest to the pointer along the *x* or *y* channel dimension. Unlike Mosaic selections, a mark level *select* is internal to the mark only, and does not populate a param or selection value to be shared across clients.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "shapeRendering": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [shape-rendering][1]; a constant string such as *crispEdges*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/shape-rendering" + }, + "sort": { + "anyOf": [ + { + "$ref": "#/definitions/SortOrder" + }, + { + "$ref": "#/definitions/ChannelDomainSort" + } + ], + "description": "Either applies a transform to sort the mark’s index by the specified channel values, or imputes ordinal scale domains from this mark’s channels.\n\nWhen imputing ordinal scale domains from channel values, the **sort** option is an object whose keys are ordinal scale names such as *x* or *fx*, and whose values are channel names such as *y*, *y1*, or *y2*. For example, to impute the *y* scale’s domain from the associated *x* channel values in ascending order:\n\n```js sort: {y: \"x\"} ```\n\nFor different sort options for different scales, replace the channel name with a *value* object and per-scale options:\n\n```js sort: {y: {value: \"-x\"}} ```\n\nWhen sorting the mark’s index, the **sort** option is instead one of:\n\n- a channel value definition for sorting given values in ascending order\n- a {value, order} object for sorting given values\n- a {channel, order} object for sorting the named channel’s values" + }, + "stroke": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke" + }, + "strokeDasharray": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dasharray][1]; a constant number indicating the length in pixels of alternating dashes and gaps, or a constant string of numbers separated by spaces or commas (_e.g._, *10 2* for dashes of 10 pixels separated by gaps of 2 pixels), or *none* (the default) for no dashing\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dasharray" + }, + "strokeDashoffset": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dashoffset][1]; a constant indicating the offset in pixels of the first dash along the stroke; defaults to zero.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dashoffset" + }, + "strokeLinecap": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linecap][1]; a constant specifying how to cap stroked paths, such as *butt*, *round*, or *square*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linecap" + }, + "strokeLinejoin": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linejoin][1]; a constant specifying how to join stroked paths, such as *bevel*, *miter*, *miter-clip*, or *round*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linejoin" + }, + "strokeMiterlimit": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-miterlimit][1]; a constant number specifying how to limit the length of *miter* joins on stroked paths.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-miterlimit" + }, + "strokeOpacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-opacity" + }, + "strokeWidth": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-width][1]; a constant number in pixels, or a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-width" + }, + "target": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [target][1]; a constant string specifying the target window (_e.g._,\n*_blank*) for clickable links; used in conjunction with the **href** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/target" + }, + "tension": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The tension option only has an effect on bundle, cardinal and Catmull–Rom splines (*bundle*, *cardinal*, *cardinal-open*, *cardinal-closed*,\n*catmull-rom*, *catmull-rom-open*, and *catmull-rom-closed*). For bundle splines, it corresponds to [beta][1]; for cardinal splines, [tension][2]; for Catmull–Rom splines, [alpha][3].\n\n[1]: https://d3js.org/d3-shape/curve#curveBundle_beta [2]: https://d3js.org/d3-shape/curve#curveCardinal_tension [3]: https://d3js.org/d3-shape/curve#curveCatmullRom_alpha" + }, + "tip": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/TipPointer" + }, + { + "properties": { + "anchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The tip anchor specifies how to orient the tip box relative to its anchor position; it refers to the part of the tip box that is attached to the anchor point. For example, the *top-left* anchor places the top-left corner of tip box near the anchor position, hence placing the tip box below and to the right of the anchor position." + }, + "fontFamily": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font-family][1]; a constant; defaults to the plot’s font family, which is typically [*system-ui*][2].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-family [2]: https://drafts.csswg.org/css-fonts-4/#valdef-font-family-system-ui" + }, + "fontSize": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font size][1] in pixels; either a constant or a channel; defaults to the plot’s font size, which is typically 10. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-size" + }, + "fontStyle": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font style][1]; a constant; defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-style" + }, + "fontVariant": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font variant][1]; a constant; if the **text** channel contains numbers or dates, defaults to *tabular-nums* to facilitate comparing numbers; otherwise defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant" + }, + "fontWeight": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font weight][1]; a constant; defaults to the plot’s font weight, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight" + }, + "format": { + "additionalProperties": false, + "description": "How channel values are formatted for display. If a format is a string, it is interpreted as a (UTC) time format for temporal channels, and otherwise a number format.", + "properties": { + "ariaLabel": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fill": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fillOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fontSize": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fx": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fy": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "geometry": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "height": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "href": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "length": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "opacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "path": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "r": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "rotate": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "src": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "stroke": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeWidth": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "symbol": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "text": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "title": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "weight": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "width": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "z": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + } + }, + "type": "object" + }, + "frameAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The frame anchor specifies defaults for **x** and **y** based on the plot’s frame; it may be one of the four sides (*top*, *right*, *bottom*, *left*), one of the four corners (*top-left*, *top-right*, *bottom-right*,\n*bottom-left*), or the *middle* of the frame. For example, for tips distributed horizontally at the top of the frame:\n\n```js Plot.tip(data, {x: \"date\", frameAnchor: \"top\"}) ```" + }, + "lineHeight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line height in ems; defaults to 1. The line height affects the (typically vertical) separation between adjacent baselines of text, as well as the separation between the text and its anchor point." + }, + "lineWidth": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line width in ems (e.g., 10 for about 20 characters); defaults to infinity, disabling wrapping and clipping.\n\nIf **textOverflow** is null, lines will be wrapped at the specified length. If a line is split at a soft hyphen (\\xad), a hyphen (-) will be displayed at the end of the line. If **textOverflow** is not null, lines will be clipped according to the given strategy." + }, + "monospace": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, changes the default **fontFamily** to *monospace*, and uses simplified monospaced text metrics calculations." + }, + "pathFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The image filter for the tip’s box; defaults to a drop shadow." + }, + "pointer": { + "$ref": "#/definitions/TipPointer" + }, + "pointerSize": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The size of the tip’s pointer in pixels; defaults to 12." + }, + "preferredAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If an explicit tip anchor is not specified, an anchor is chosen automatically such that the tip fits within the plot’s frame; if the preferred anchor fits, it is chosen." + }, + "textAnchor": { + "anyOf": [ + { + "const": "start", + "type": "string" + }, + { + "const": "middle", + "type": "string" + }, + { + "const": "end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [text anchor][1] controls how text is aligned (typically horizontally) relative to its anchor point; it is one of *start*, *end*, or *middle*. If the frame anchor is *left*, *top-left*, or *bottom-left*, the default text anchor is *start*; if the frame anchor is *right*, *top-right*, or\n*bottom-right*, the default is *end*; otherwise it is *middle*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/text-anchor" + }, + "textOverflow": { + "anyOf": [ + { + "type": "null" + }, + { + "const": "clip", + "type": "string" + }, + { + "const": "ellipsis", + "type": "string" + }, + { + "const": "clip-start", + "type": "string" + }, + { + "const": "clip-end", + "type": "string" + }, + { + "const": "ellipsis-start", + "type": "string" + }, + { + "const": "ellipsis-middle", + "type": "string" + }, + { + "const": "ellipsis-end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How truncate (or wrap) lines of text longer than the given **lineWidth**; one of:\n\n- null (default) - preserve overflowing characters (and wrap if needed)\n- *clip* or *clip-end* - remove characters from the end\n- *clip-start* - remove characters from the start\n- *ellipsis* or *ellipsis-end* - replace characters from the end with an ellipsis (…)\n- *ellipsis-start* - replace characters from the start with an ellipsis (…)\n- *ellipsis-middle* - replace characters from the middle with an ellipsis (…)\n\nIf no **title** was specified, if text requires truncation, a title containing the non-truncated text will be implicitly added." + }, + "textPadding": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The padding around the text in pixels; defaults to 8." + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + } + }, + "type": "object" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to generate a tooltip for this mark, and any tip options." + }, + "title": { + "$ref": "#/definitions/ChannelValue", + "description": "The title; a channel specifying accessible, short textual descriptions as strings (possibly with newlines). If the tip option is specified, the title will be displayed with an interactive tooltip instead of using the SVG [title element][1].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/title" + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel, typically bound to the *x* scale." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel, typically bound to the *y* scale." + }, + "z": { + "$ref": "#/definitions/ChannelValue", + "description": "An optional ordinal channel for grouping to produce multiple (possibly overlapping) triangulations." + } + }, + "required": [ + "data", + "mark" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "$schema": { + "description": "A [JSON schema](http://json-schema.org/) URL for this specification, such as https://uwdata.github.io/mosaic/schema/latest.json. This property enables validation and autocomplete in editors with JSON schema support.", + "format": "uri", + "type": "string" + }, + "ariaDescription": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-description][1]; a constant textual description.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-description" + }, + "ariaHidden": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-hidden][1] state; a constant indicating whether the element is exposed to an accessibility API.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-hidden" + }, + "ariaLabel": { + "$ref": "#/definitions/ChannelValue", + "description": "The [aria-label][1]; a channel specifying short textual labels representing the value in the accessibility tree.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-label" + }, + "bandwidth": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The kernel density bandwidth for smoothing, in pixels." + }, + "clip": { + "anyOf": [ + { + "const": "frame", + "type": "string" + }, + { + "const": "sphere", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to clip the mark; one of:\n\n- *frame* or true - clip to the plot’s frame (inner area)\n- *sphere* - clip to the projected sphere (*e.g.*, front hemisphere)\n- null or false - do not clip\n\nThe *sphere* clip option requires a geographic projection." + }, + "config": { + "$ref": "#/definitions/Config", + "description": "Configuration options." + }, + "data": { + "$ref": "#/definitions/Data", + "description": "Dataset definitions." + }, + "dx": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The horizontal offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "dy": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The vertical offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "facet": { + "anyOf": [ + { + "const": "auto", + "type": "string" + }, + { + "const": "include", + "type": "string" + }, + { + "const": "exclude", + "type": "string" + }, + { + "const": "super", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to enable or disable faceting; one of:\n\n- *auto* (default) - automatically determine if this mark should be faceted\n- *include* (or true) - draw the subset of the mark’s data in the current facet\n- *exclude* - draw the subset of the mark’s data *not* in the current facet\n- *super* - draw this mark in a single frame that covers all facets\n- null (or false) - repeat this mark’s data across all facets (*i.e.*, no faceting)\n\nWhen a mark uses *super* faceting, it is not allowed to use position scales (*x*, *y*, *fx*, or *fy*); *super* faceting is intended for decorations, such as labels and legends.\n\nWhen top-level faceting is used, the default *auto* setting is equivalent to *include* when the mark data is strictly equal to the top-level facet data; otherwise it is equivalent to null. When the *include* or *exclude* facet mode is chosen, the mark data must be parallel to the top-level facet data: the data must have the same length and order. If the data are not parallel, then the wrong data may be shown in each facet. The default\n*auto* therefore requires strict equality (`===`) for safety, and using the facet data as mark data is recommended when using the *exclude* facet mode. (To construct parallel data safely, consider using [*array*.map][1] on the facet data.)\n\nWhen mark-level faceting is used, the default *auto* setting is equivalent to *include*: the mark will be faceted if either the **fx** or **fy** channel option (or both) is specified. The null or false option will disable faceting, while *exclude* draws the subset of the mark’s data *not* in the current facet.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map" + }, + "facetAnchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "right", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "const": "left", + "type": "string" + }, + { + "const": "top-left", + "type": "string" + }, + { + "const": "top-right", + "type": "string" + }, + { + "const": "bottom-left", + "type": "string" + }, + { + "const": "bottom-right", + "type": "string" + }, + { + "const": "top-empty", + "type": "string" + }, + { + "const": "right-empty", + "type": "string" + }, + { + "const": "bottom-empty", + "type": "string" + }, + { + "const": "left-empty", + "type": "string" + }, + { + "const": "empty", + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to place the mark with respect to facets; one of:\n\n- null (default for most marks) - display the mark in each non-empty facet\n- *top*, *right*, *bottom*, or *left* - display the mark only in facets on the given side\n- *top-empty*, *right-empty*, *bottom-empty*, or *left-empty* (default for axis marks) - display the mark only in facets that have empty space on the given side: either the margin, or an empty facet\n- *empty* - display the mark in empty facets only" + }, + "fill": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The fill, typically bound to the *color* scale. Can be specified as a constant or a channel based on the input data. Use the special value `\"density\"` to map computed density values to pixel colors. Use an aggregate expression to instead visualize an aggregate value per raster bin. If fill is set to a constant color or to a non-aggregate field, opacity will be used to convey densities. If a non-aggregate (group by) field is provided, multiple rasters are created with a unique categorical color per layer." + }, + "fillOpacity": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The opacity, typically bound to the *opacity* scale. Can be specified as a constant or a channel based on the input data. Use the special value `\"density\"` to map computed density values to opacity. Use an aggregate expression to instead visualize an aggregate value per raster bin." + }, + "filter": { + "$ref": "#/definitions/ChannelValue", + "description": "Applies a transform to filter the mark’s index according to the given channel values; only truthy values are retained.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "fx": { + "$ref": "#/definitions/ChannelValue", + "description": "The horizontal facet position channel, for mark-level faceting, bound to the *fx* scale." + }, + "fy": { + "$ref": "#/definitions/ChannelValue", + "description": "The vertical facet position channel, for mark-level faceting, bound to the\n*fy* scale." + }, + "height": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The height (number of rows) of the grid, in actual pixels." + }, + "href": { + "$ref": "#/definitions/ChannelValue", + "description": "The [href][1]; a channel specifying URLs for clickable links. May be used in conjunction with the **target** option to open links in another window.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/href" + }, + "imageFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A CSS [filter][1]; a constant string used to adjust the rendering of images, such as *blur(5px)*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/filter" + }, + "imageRendering": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [image-rendering attribute][1]; defaults to *auto* (bilinear). The option may be set to *pixelated* to disable bilinear interpolation for a sharper image; however, note that this is not supported in WebKit.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/image-rendering" + }, + "interpolate": { + "anyOf": [ + { + "$ref": "#/definitions/GridInterpolate" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The spatial interpolation method; one of:\n\n- *none* - do not perform interpolation (the default), maps samples to single bins\n- *linear* - apply proportional linear interpolation across adjacent bins\n- *nearest* - assign each pixel to the closest sample’s value (Voronoi diagram)\n- *barycentric* - apply barycentric interpolation over the Delaunay triangulation\n- *random-walk* - apply a random walk from each pixel, stopping when near a sample" + }, + "margin": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four mark margins: **marginTop**,\n**marginRight**, **marginBottom**, and **marginLeft**; typically defaults to 0, except for axis marks." + }, + "marginBottom": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s bottom margin; the minimum distance in pixels between the bottom edges of the inner and outer plot area." + }, + "marginLeft": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s left margin; the minimum distance in pixels between the left edges of the inner and outer plot area." + }, + "marginRight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s right margin; the minimum distance in pixels between the right edges of the mark’s inner and outer plot area." + }, + "marginTop": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s top margin; the minimum distance in pixels between the top edges of the inner and outer plot area." + }, + "mark": { + "const": "denseLine", + "description": "A denseLine mark that plots line densities rather than point densities. The mark forms a binned raster grid and \"draws\" straight lines into it. To avoid over-weighting steep lines, by default each drawn series is normalized on a per-column basis to approximate arc length normalization. The values for each series are aggregated to form the line density, which is then drawn as an image similar to the raster mark.", + "type": "string" + }, + "meta": { + "$ref": "#/definitions/Meta", + "description": "Specification metadata." + }, + "mixBlendMode": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [mix-blend-mode][1]; a constant string specifying how to blend content such as *multiply*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode" + }, + "normalize": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Flag to perform approximate arc length normalization of line segments to prevent artifacts due to overcounting steep lines. Defaults to `true`." + }, + "opacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally. For faster rendering, prefer the **strokeOpacity** or **fillOpacity** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/opacity" + }, + "pad": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The bin padding, one of 1 (default) to include extra padding for the final bin, or 0 to make the bins flush with the maximum domain value." + }, + "paintOrder": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [paint-order][1]; a constant string specifying the order in which the\n**fill**, **stroke**, and any markers are drawn; defaults to *normal*, which draws the fill, then stroke, then markers; defaults to *stroke* for the text mark to create a “halo” around text to improve legibility.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/paint-order" + }, + "params": { + "$ref": "#/definitions/Params", + "description": "Param and Selection definitions." + }, + "pixelSize": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The effective screen size of a raster pixel, used to determine the height and width of the raster from the frame’s dimensions; defaults to 1." + }, + "plotDefaults": { + "$ref": "#/definitions/PlotAttributes", + "description": "A default set of attributes to apply to all plot components." + }, + "pointerEvents": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [pointer-events][1] property; a constant string such as *none*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/pointer-events" + }, + "reverse": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Applies a transform to reverse the order of the mark’s index, say for reverse input order." + }, + "select": { + "$ref": "#/definitions/SelectFilter", + "description": "Applies a filter transform after data is loaded to highlight selected values only. For example, `first` and `last` select the first or last values of series only (using the *z* channel to separate series). Meanwhile, `nearestX` and `nearestY` select the point nearest to the pointer along the *x* or *y* channel dimension. Unlike Mosaic selections, a mark level *select* is internal to the mark only, and does not populate a param or selection value to be shared across clients.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "shapeRendering": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [shape-rendering][1]; a constant string such as *crispEdges*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/shape-rendering" + }, + "sort": { + "anyOf": [ + { + "$ref": "#/definitions/SortOrder" + }, + { + "$ref": "#/definitions/ChannelDomainSort" + } + ], + "description": "Either applies a transform to sort the mark’s index by the specified channel values, or imputes ordinal scale domains from this mark’s channels.\n\nWhen imputing ordinal scale domains from channel values, the **sort** option is an object whose keys are ordinal scale names such as *x* or *fx*, and whose values are channel names such as *y*, *y1*, or *y2*. For example, to impute the *y* scale’s domain from the associated *x* channel values in ascending order:\n\n```js sort: {y: \"x\"} ```\n\nFor different sort options for different scales, replace the channel name with a *value* object and per-scale options:\n\n```js sort: {y: {value: \"-x\"}} ```\n\nWhen sorting the mark’s index, the **sort** option is instead one of:\n\n- a channel value definition for sorting given values in ascending order\n- a {value, order} object for sorting given values\n- a {channel, order} object for sorting the named channel’s values" + }, + "stroke": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke" + }, + "strokeDasharray": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dasharray][1]; a constant number indicating the length in pixels of alternating dashes and gaps, or a constant string of numbers separated by spaces or commas (_e.g._, *10 2* for dashes of 10 pixels separated by gaps of 2 pixels), or *none* (the default) for no dashing\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dasharray" + }, + "strokeDashoffset": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dashoffset][1]; a constant indicating the offset in pixels of the first dash along the stroke; defaults to zero.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dashoffset" + }, + "strokeLinecap": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linecap][1]; a constant specifying how to cap stroked paths, such as *butt*, *round*, or *square*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linecap" + }, + "strokeLinejoin": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linejoin][1]; a constant specifying how to join stroked paths, such as *bevel*, *miter*, *miter-clip*, or *round*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linejoin" + }, + "strokeMiterlimit": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-miterlimit][1]; a constant number specifying how to limit the length of *miter* joins on stroked paths.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-miterlimit" + }, + "strokeOpacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-opacity" + }, + "strokeWidth": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-width][1]; a constant number in pixels, or a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-width" + }, + "target": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [target][1]; a constant string specifying the target window (_e.g._,\n*_blank*) for clickable links; used in conjunction with the **href** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/target" + }, + "tip": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/TipPointer" + }, + { + "properties": { + "anchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The tip anchor specifies how to orient the tip box relative to its anchor position; it refers to the part of the tip box that is attached to the anchor point. For example, the *top-left* anchor places the top-left corner of tip box near the anchor position, hence placing the tip box below and to the right of the anchor position." + }, + "fontFamily": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font-family][1]; a constant; defaults to the plot’s font family, which is typically [*system-ui*][2].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-family [2]: https://drafts.csswg.org/css-fonts-4/#valdef-font-family-system-ui" + }, + "fontSize": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font size][1] in pixels; either a constant or a channel; defaults to the plot’s font size, which is typically 10. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-size" + }, + "fontStyle": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font style][1]; a constant; defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-style" + }, + "fontVariant": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font variant][1]; a constant; if the **text** channel contains numbers or dates, defaults to *tabular-nums* to facilitate comparing numbers; otherwise defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant" + }, + "fontWeight": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font weight][1]; a constant; defaults to the plot’s font weight, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight" + }, + "format": { + "additionalProperties": false, + "description": "How channel values are formatted for display. If a format is a string, it is interpreted as a (UTC) time format for temporal channels, and otherwise a number format.", + "properties": { + "ariaLabel": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fill": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fillOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fontSize": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fx": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fy": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "geometry": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "height": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "href": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "length": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "opacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "path": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "r": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "rotate": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "src": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "stroke": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeWidth": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "symbol": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "text": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "title": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "weight": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "width": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "z": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + } + }, + "type": "object" + }, + "frameAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The frame anchor specifies defaults for **x** and **y** based on the plot’s frame; it may be one of the four sides (*top*, *right*, *bottom*, *left*), one of the four corners (*top-left*, *top-right*, *bottom-right*,\n*bottom-left*), or the *middle* of the frame. For example, for tips distributed horizontally at the top of the frame:\n\n```js Plot.tip(data, {x: \"date\", frameAnchor: \"top\"}) ```" + }, + "lineHeight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line height in ems; defaults to 1. The line height affects the (typically vertical) separation between adjacent baselines of text, as well as the separation between the text and its anchor point." + }, + "lineWidth": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line width in ems (e.g., 10 for about 20 characters); defaults to infinity, disabling wrapping and clipping.\n\nIf **textOverflow** is null, lines will be wrapped at the specified length. If a line is split at a soft hyphen (\\xad), a hyphen (-) will be displayed at the end of the line. If **textOverflow** is not null, lines will be clipped according to the given strategy." + }, + "monospace": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, changes the default **fontFamily** to *monospace*, and uses simplified monospaced text metrics calculations." + }, + "pathFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The image filter for the tip’s box; defaults to a drop shadow." + }, + "pointer": { + "$ref": "#/definitions/TipPointer" + }, + "pointerSize": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The size of the tip’s pointer in pixels; defaults to 12." + }, + "preferredAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If an explicit tip anchor is not specified, an anchor is chosen automatically such that the tip fits within the plot’s frame; if the preferred anchor fits, it is chosen." + }, + "textAnchor": { + "anyOf": [ + { + "const": "start", + "type": "string" + }, + { + "const": "middle", + "type": "string" + }, + { + "const": "end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [text anchor][1] controls how text is aligned (typically horizontally) relative to its anchor point; it is one of *start*, *end*, or *middle*. If the frame anchor is *left*, *top-left*, or *bottom-left*, the default text anchor is *start*; if the frame anchor is *right*, *top-right*, or\n*bottom-right*, the default is *end*; otherwise it is *middle*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/text-anchor" + }, + "textOverflow": { + "anyOf": [ + { + "type": "null" + }, + { + "const": "clip", + "type": "string" + }, + { + "const": "ellipsis", + "type": "string" + }, + { + "const": "clip-start", + "type": "string" + }, + { + "const": "clip-end", + "type": "string" + }, + { + "const": "ellipsis-start", + "type": "string" + }, + { + "const": "ellipsis-middle", + "type": "string" + }, + { + "const": "ellipsis-end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How truncate (or wrap) lines of text longer than the given **lineWidth**; one of:\n\n- null (default) - preserve overflowing characters (and wrap if needed)\n- *clip* or *clip-end* - remove characters from the end\n- *clip-start* - remove characters from the start\n- *ellipsis* or *ellipsis-end* - replace characters from the end with an ellipsis (…)\n- *ellipsis-start* - replace characters from the start with an ellipsis (…)\n- *ellipsis-middle* - replace characters from the middle with an ellipsis (…)\n\nIf no **title** was specified, if text requires truncation, a title containing the non-truncated text will be implicitly added." + }, + "textPadding": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The padding around the text in pixels; defaults to 8." + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + } + }, + "type": "object" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to generate a tooltip for this mark, and any tip options." + }, + "title": { + "$ref": "#/definitions/ChannelValue", + "description": "The title; a channel specifying accessible, short textual descriptions as strings (possibly with newlines). If the tip option is specified, the title will be displayed with an interactive tooltip instead of using the SVG [title element][1].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/title" + }, + "width": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The width (number of columns) of the grid, in actual pixels." + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel, typically bound to the *x* scale. Domain values are binned into a grid with *width* horizontal bins." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel, typically bound to the *y* scale. Domain values are binned into a grid with *height* vertical bins." + }, + "z": { + "$ref": "#/definitions/ChannelValue", + "description": "A ordinal channel for grouping data into series to be drawn as separate lines." + } + }, + "required": [ + "data", + "mark" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "$schema": { + "description": "A [JSON schema](http://json-schema.org/) URL for this specification, such as https://uwdata.github.io/mosaic/schema/latest.json. This property enables validation and autocomplete in editors with JSON schema support.", + "format": "uri", + "type": "string" + }, + "ariaDescription": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-description][1]; a constant textual description.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-description" + }, + "ariaHidden": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-hidden][1] state; a constant indicating whether the element is exposed to an accessibility API.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-hidden" + }, + "ariaLabel": { + "$ref": "#/definitions/ChannelValue", + "description": "The [aria-label][1]; a channel specifying short textual labels representing the value in the accessibility tree.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-label" + }, + "bandwidth": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The kernel density bandwidth for smoothing, in pixels." + }, + "clip": { + "anyOf": [ + { + "const": "frame", + "type": "string" + }, + { + "const": "sphere", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to clip the mark; one of:\n\n- *frame* or true - clip to the plot’s frame (inner area)\n- *sphere* - clip to the projected sphere (*e.g.*, front hemisphere)\n- null or false - do not clip\n\nThe *sphere* clip option requires a geographic projection." + }, + "config": { + "$ref": "#/definitions/Config", + "description": "Configuration options." + }, + "data": { + "$ref": "#/definitions/Data", + "description": "Dataset definitions." + }, + "dx": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The horizontal offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "dy": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The vertical offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "facet": { + "anyOf": [ + { + "const": "auto", + "type": "string" + }, + { + "const": "include", + "type": "string" + }, + { + "const": "exclude", + "type": "string" + }, + { + "const": "super", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to enable or disable faceting; one of:\n\n- *auto* (default) - automatically determine if this mark should be faceted\n- *include* (or true) - draw the subset of the mark’s data in the current facet\n- *exclude* - draw the subset of the mark’s data *not* in the current facet\n- *super* - draw this mark in a single frame that covers all facets\n- null (or false) - repeat this mark’s data across all facets (*i.e.*, no faceting)\n\nWhen a mark uses *super* faceting, it is not allowed to use position scales (*x*, *y*, *fx*, or *fy*); *super* faceting is intended for decorations, such as labels and legends.\n\nWhen top-level faceting is used, the default *auto* setting is equivalent to *include* when the mark data is strictly equal to the top-level facet data; otherwise it is equivalent to null. When the *include* or *exclude* facet mode is chosen, the mark data must be parallel to the top-level facet data: the data must have the same length and order. If the data are not parallel, then the wrong data may be shown in each facet. The default\n*auto* therefore requires strict equality (`===`) for safety, and using the facet data as mark data is recommended when using the *exclude* facet mode. (To construct parallel data safely, consider using [*array*.map][1] on the facet data.)\n\nWhen mark-level faceting is used, the default *auto* setting is equivalent to *include*: the mark will be faceted if either the **fx** or **fy** channel option (or both) is specified. The null or false option will disable faceting, while *exclude* draws the subset of the mark’s data *not* in the current facet.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map" + }, + "facetAnchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "right", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "const": "left", + "type": "string" + }, + { + "const": "top-left", + "type": "string" + }, + { + "const": "top-right", + "type": "string" + }, + { + "const": "bottom-left", + "type": "string" + }, + { + "const": "bottom-right", + "type": "string" + }, + { + "const": "top-empty", + "type": "string" + }, + { + "const": "right-empty", + "type": "string" + }, + { + "const": "bottom-empty", + "type": "string" + }, + { + "const": "left-empty", + "type": "string" + }, + { + "const": "empty", + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to place the mark with respect to facets; one of:\n\n- null (default for most marks) - display the mark in each non-empty facet\n- *top*, *right*, *bottom*, or *left* - display the mark only in facets on the given side\n- *top-empty*, *right-empty*, *bottom-empty*, or *left-empty* (default for axis marks) - display the mark only in facets that have empty space on the given side: either the margin, or an empty facet\n- *empty* - display the mark in empty facets only" + }, + "fill": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill" + }, + "fillOpacity": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill-opacity][1]; a constant number between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill-opacity" + }, + "filter": { + "$ref": "#/definitions/ChannelValue", + "description": "Applies a transform to filter the mark’s index according to the given channel values; only truthy values are retained.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "fontFamily": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font-family][1]; a constant; defaults to the plot’s font family, which is typically [*system-ui*][2].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-family [2]: https://drafts.csswg.org/css-fonts-4/#valdef-font-family-system-ui" + }, + "fontSize": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font size][1] in pixels; either a constant or a channel; defaults to the plot’s font size, which is typically 10. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-size" + }, + "fontStyle": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font style][1]; a constant; defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-style" + }, + "fontVariant": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font variant][1]; a constant; if the **text** channel contains numbers or dates, defaults to *tabular-nums* to facilitate comparing numbers; otherwise defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant" + }, + "fontWeight": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font weight][1]; a constant; defaults to the plot’s font weight, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight" + }, + "frameAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The frame anchor specifies defaults for **x** and **y** based on the plot’s frame; it may be one of the four sides (*top*, *right*, *bottom*, *left*), one of the four corners (*top-left*, *top-right*, *bottom-right*,\n*bottom-left*), or the *middle* of the frame. For example, for dots distributed horizontally at the top of the frame:\n\n```js Plot.dot(data, {x: \"date\", frameAnchor: \"top\"}) ```" + }, + "fx": { + "$ref": "#/definitions/ChannelValue", + "description": "The horizontal facet position channel, for mark-level faceting, bound to the *fx* scale." + }, + "fy": { + "$ref": "#/definitions/ChannelValue", + "description": "The vertical facet position channel, for mark-level faceting, bound to the\n*fy* scale." + }, + "height": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The height (number of rows) of the grid, in actual pixels." + }, + "href": { + "$ref": "#/definitions/ChannelValue", + "description": "The [href][1]; a channel specifying URLs for clickable links. May be used in conjunction with the **target** option to open links in another window.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/href" + }, + "imageFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A CSS [filter][1]; a constant string used to adjust the rendering of images, such as *blur(5px)*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/filter" + }, + "interpolate": { + "anyOf": [ + { + "$ref": "#/definitions/GridInterpolate" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The spatial interpolation method; one of:\n\n- *none* - do not perform interpolation (the default), maps samples to single bins\n- *linear* - apply proportional linear interpolation across adjacent bins\n- *nearest* - assign each pixel to the closest sample’s value (Voronoi diagram)\n- *barycentric* - apply barycentric interpolation over the Delaunay triangulation\n- *random-walk* - apply a random walk from each pixel, stopping when near a sample" + }, + "lineHeight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line height in ems; defaults to 1. The line height affects the (typically vertical) separation between adjacent baselines of text, as well as the separation between the text and its anchor point." + }, + "lineWidth": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line width in ems (e.g., 10 for about 20 characters); defaults to infinity, disabling wrapping and clipping.\n\nIf **textOverflow** is null, lines will be wrapped at the specified length. If a line is split at a soft hyphen (\\xad), a hyphen (-) will be displayed at the end of the line. If **textOverflow** is not null, lines will be clipped according to the given strategy." + }, + "margin": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four mark margins: **marginTop**,\n**marginRight**, **marginBottom**, and **marginLeft**; typically defaults to 0, except for axis marks." + }, + "marginBottom": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s bottom margin; the minimum distance in pixels between the bottom edges of the inner and outer plot area." + }, + "marginLeft": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s left margin; the minimum distance in pixels between the left edges of the inner and outer plot area." + }, + "marginRight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s right margin; the minimum distance in pixels between the right edges of the mark’s inner and outer plot area." + }, + "marginTop": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s top margin; the minimum distance in pixels between the top edges of the inner and outer plot area." + }, + "mark": { + "const": "density", + "description": "A 2D density mark that shows smoothed point cloud densities along two dimensions. The mark bins the data, counts the number of records that fall into each bin, and smooths the resulting counts, then plots the smoothed distribution, by default using a circular dot mark. The density mark calculates density values that can be mapped to encoding channels such as fill or r using the special field name \"density\".\n\nSet the *type* property to use a different base mark type.", + "type": "string" + }, + "meta": { + "$ref": "#/definitions/Meta", + "description": "Specification metadata." + }, + "mixBlendMode": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [mix-blend-mode][1]; a constant string specifying how to blend content such as *multiply*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode" + }, + "monospace": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, changes the default **fontFamily** to *monospace*, and uses simplified monospaced text metrics calculations." + }, + "opacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally. For faster rendering, prefer the **strokeOpacity** or **fillOpacity** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/opacity" + }, + "pad": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The bin padding, one of 1 (default) to include extra padding for the final bin, or 0 to make the bins flush with the maximum domain value." + }, + "paintOrder": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [paint-order][1]; a constant string specifying the order in which the\n**fill**, **stroke**, and any markers are drawn; defaults to *normal*, which draws the fill, then stroke, then markers; defaults to *stroke* for the text mark to create a “halo” around text to improve legibility.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/paint-order" + }, + "params": { + "$ref": "#/definitions/Params", + "description": "Param and Selection definitions." + }, + "pixelSize": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The effective screen size of a raster pixel, used to determine the height and width of the raster from the frame’s dimensions; defaults to 1." + }, + "plotDefaults": { + "$ref": "#/definitions/PlotAttributes", + "description": "A default set of attributes to apply to all plot components." + }, + "pointerEvents": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [pointer-events][1] property; a constant string such as *none*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/pointer-events" + }, + "r": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The radius of dots; either a channel or constant. When a number, it is interpreted as a constant radius in pixels. Otherwise it is interpreted as a channel, typically bound to the *r* channel, which defaults to the *sqrt* type for proportional symbols. The radius defaults to 4.5 pixels when using the **symbol** channel, and otherwise 3 pixels. Dots with a nonpositive radius are not drawn." + }, + "reverse": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Applies a transform to reverse the order of the mark’s index, say for reverse input order." + }, + "rotate": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The rotation angle of dots in degrees clockwise; either a channel or a constant. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel. Defaults to 0°, pointing up." + }, + "select": { + "$ref": "#/definitions/SelectFilter", + "description": "Applies a filter transform after data is loaded to highlight selected values only. For example, `first` and `last` select the first or last values of series only (using the *z* channel to separate series). Meanwhile, `nearestX` and `nearestY` select the point nearest to the pointer along the *x* or *y* channel dimension. Unlike Mosaic selections, a mark level *select* is internal to the mark only, and does not populate a param or selection value to be shared across clients.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "shapeRendering": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [shape-rendering][1]; a constant string such as *crispEdges*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/shape-rendering" + }, + "sort": { + "anyOf": [ + { + "$ref": "#/definitions/SortOrder" + }, + { + "$ref": "#/definitions/ChannelDomainSort" + } + ], + "description": "Either applies a transform to sort the mark’s index by the specified channel values, or imputes ordinal scale domains from this mark’s channels.\n\nWhen imputing ordinal scale domains from channel values, the **sort** option is an object whose keys are ordinal scale names such as *x* or *fx*, and whose values are channel names such as *y*, *y1*, or *y2*. For example, to impute the *y* scale’s domain from the associated *x* channel values in ascending order:\n\n```js sort: {y: \"x\"} ```\n\nFor different sort options for different scales, replace the channel name with a *value* object and per-scale options:\n\n```js sort: {y: {value: \"-x\"}} ```\n\nWhen sorting the mark’s index, the **sort** option is instead one of:\n\n- a channel value definition for sorting given values in ascending order\n- a {value, order} object for sorting given values\n- a {channel, order} object for sorting the named channel’s values" + }, + "stroke": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke" + }, + "strokeDasharray": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dasharray][1]; a constant number indicating the length in pixels of alternating dashes and gaps, or a constant string of numbers separated by spaces or commas (_e.g._, *10 2* for dashes of 10 pixels separated by gaps of 2 pixels), or *none* (the default) for no dashing\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dasharray" + }, + "strokeDashoffset": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dashoffset][1]; a constant indicating the offset in pixels of the first dash along the stroke; defaults to zero.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dashoffset" + }, + "strokeLinecap": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linecap][1]; a constant specifying how to cap stroked paths, such as *butt*, *round*, or *square*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linecap" + }, + "strokeLinejoin": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linejoin][1]; a constant specifying how to join stroked paths, such as *bevel*, *miter*, *miter-clip*, or *round*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linejoin" + }, + "strokeMiterlimit": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-miterlimit][1]; a constant number specifying how to limit the length of *miter* joins on stroked paths.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-miterlimit" + }, + "strokeOpacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-opacity" + }, + "strokeWidth": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-width][1]; a constant number in pixels, or a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-width" + }, + "symbol": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/SymbolType" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The categorical symbol; either a channel or a constant. A constant symbol can be specified by a valid symbol name such as *star*, or a symbol object (implementing the draw method); otherwise it is interpreted as a channel. Defaults to *circle* for the **dot** mark, and *hexagon* for the\n**hexagon** mark.\n\nIf the **symbol** channel’s values are all symbols, symbol names, or nullish, the channel is unscaled (values are interpreted literally); otherwise, the channel is bound to the *symbol* scale." + }, + "target": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [target][1]; a constant string specifying the target window (_e.g._,\n*_blank*) for clickable links; used in conjunction with the **href** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/target" + }, + "textAnchor": { + "anyOf": [ + { + "const": "start", + "type": "string" + }, + { + "const": "middle", + "type": "string" + }, + { + "const": "end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [text anchor][1] controls how text is aligned (typically horizontally) relative to its anchor point; it is one of *start*, *end*, or *middle*. If the frame anchor is *left*, *top-left*, or *bottom-left*, the default text anchor is *start*; if the frame anchor is *right*, *top-right*, or\n*bottom-right*, the default is *end*; otherwise it is *middle*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/text-anchor" + }, + "textOverflow": { + "anyOf": [ + { + "type": "null" + }, + { + "const": "clip", + "type": "string" + }, + { + "const": "ellipsis", + "type": "string" + }, + { + "const": "clip-start", + "type": "string" + }, + { + "const": "clip-end", + "type": "string" + }, + { + "const": "ellipsis-start", + "type": "string" + }, + { + "const": "ellipsis-middle", + "type": "string" + }, + { + "const": "ellipsis-end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How truncate (or wrap) lines of text longer than the given **lineWidth**; one of:\n\n- null (default) - preserve overflowing characters (and wrap if needed)\n- *clip* or *clip-end* - remove characters from the end\n- *clip-start* - remove characters from the start\n- *ellipsis* or *ellipsis-end* - replace characters from the end with an ellipsis (…)\n- *ellipsis-start* - replace characters from the start with an ellipsis (…)\n- *ellipsis-middle* - replace characters from the middle with an ellipsis (…)\n\nIf no **title** was specified, if text requires truncation, a title containing the non-truncated text will be implicitly added." + }, + "tip": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/TipPointer" + }, + { + "properties": { + "anchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The tip anchor specifies how to orient the tip box relative to its anchor position; it refers to the part of the tip box that is attached to the anchor point. For example, the *top-left* anchor places the top-left corner of tip box near the anchor position, hence placing the tip box below and to the right of the anchor position." + }, + "fontFamily": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font-family][1]; a constant; defaults to the plot’s font family, which is typically [*system-ui*][2].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-family [2]: https://drafts.csswg.org/css-fonts-4/#valdef-font-family-system-ui" + }, + "fontSize": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font size][1] in pixels; either a constant or a channel; defaults to the plot’s font size, which is typically 10. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-size" + }, + "fontStyle": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font style][1]; a constant; defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-style" + }, + "fontVariant": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font variant][1]; a constant; if the **text** channel contains numbers or dates, defaults to *tabular-nums* to facilitate comparing numbers; otherwise defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant" + }, + "fontWeight": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font weight][1]; a constant; defaults to the plot’s font weight, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight" + }, + "format": { + "additionalProperties": false, + "description": "How channel values are formatted for display. If a format is a string, it is interpreted as a (UTC) time format for temporal channels, and otherwise a number format.", + "properties": { + "ariaLabel": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fill": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fillOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fontSize": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fx": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fy": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "geometry": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "height": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "href": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "length": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "opacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "path": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "r": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "rotate": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "src": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "stroke": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeWidth": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "symbol": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "text": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "title": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "weight": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "width": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "z": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + } + }, + "type": "object" + }, + "frameAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The frame anchor specifies defaults for **x** and **y** based on the plot’s frame; it may be one of the four sides (*top*, *right*, *bottom*, *left*), one of the four corners (*top-left*, *top-right*, *bottom-right*,\n*bottom-left*), or the *middle* of the frame. For example, for tips distributed horizontally at the top of the frame:\n\n```js Plot.tip(data, {x: \"date\", frameAnchor: \"top\"}) ```" + }, + "lineHeight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line height in ems; defaults to 1. The line height affects the (typically vertical) separation between adjacent baselines of text, as well as the separation between the text and its anchor point." + }, + "lineWidth": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line width in ems (e.g., 10 for about 20 characters); defaults to infinity, disabling wrapping and clipping.\n\nIf **textOverflow** is null, lines will be wrapped at the specified length. If a line is split at a soft hyphen (\\xad), a hyphen (-) will be displayed at the end of the line. If **textOverflow** is not null, lines will be clipped according to the given strategy." + }, + "monospace": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, changes the default **fontFamily** to *monospace*, and uses simplified monospaced text metrics calculations." + }, + "pathFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The image filter for the tip’s box; defaults to a drop shadow." + }, + "pointer": { + "$ref": "#/definitions/TipPointer" + }, + "pointerSize": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The size of the tip’s pointer in pixels; defaults to 12." + }, + "preferredAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If an explicit tip anchor is not specified, an anchor is chosen automatically such that the tip fits within the plot’s frame; if the preferred anchor fits, it is chosen." + }, + "textAnchor": { + "anyOf": [ + { + "const": "start", + "type": "string" + }, + { + "const": "middle", + "type": "string" + }, + { + "const": "end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [text anchor][1] controls how text is aligned (typically horizontally) relative to its anchor point; it is one of *start*, *end*, or *middle*. If the frame anchor is *left*, *top-left*, or *bottom-left*, the default text anchor is *start*; if the frame anchor is *right*, *top-right*, or\n*bottom-right*, the default is *end*; otherwise it is *middle*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/text-anchor" + }, + "textOverflow": { + "anyOf": [ + { + "type": "null" + }, + { + "const": "clip", + "type": "string" + }, + { + "const": "ellipsis", + "type": "string" + }, + { + "const": "clip-start", + "type": "string" + }, + { + "const": "clip-end", + "type": "string" + }, + { + "const": "ellipsis-start", + "type": "string" + }, + { + "const": "ellipsis-middle", + "type": "string" + }, + { + "const": "ellipsis-end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How truncate (or wrap) lines of text longer than the given **lineWidth**; one of:\n\n- null (default) - preserve overflowing characters (and wrap if needed)\n- *clip* or *clip-end* - remove characters from the end\n- *clip-start* - remove characters from the start\n- *ellipsis* or *ellipsis-end* - replace characters from the end with an ellipsis (…)\n- *ellipsis-start* - replace characters from the start with an ellipsis (…)\n- *ellipsis-middle* - replace characters from the middle with an ellipsis (…)\n\nIf no **title** was specified, if text requires truncation, a title containing the non-truncated text will be implicitly added." + }, + "textPadding": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The padding around the text in pixels; defaults to 8." + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + } + }, + "type": "object" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to generate a tooltip for this mark, and any tip options." + }, + "title": { + "$ref": "#/definitions/ChannelValue", + "description": "The title; a channel specifying accessible, short textual descriptions as strings (possibly with newlines). If the tip option is specified, the title will be displayed with an interactive tooltip instead of using the SVG [title element][1].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/title" + }, + "type": { + "anyOf": [ + { + "const": "dot", + "type": "string" + }, + { + "const": "circle", + "type": "string" + }, + { + "const": "hexagon", + "type": "string" + }, + { + "const": "cell", + "type": "string" + }, + { + "const": "text", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The basic mark type to use to render 2D density values. Defaults to a dot mark; cell and text marks are also supported." + }, + "width": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The width (number of columns) of the grid, in actual pixels." + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel, typically bound to the *x* scale. Domain values are binned into a grid with *width* horizontal bins." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel, typically bound to the *y* scale. Domain values are binned into a grid with *height* vertical bins." + }, + "z": { + "$ref": "#/definitions/ChannelValue", + "description": "An optional ordinal channel for grouping data into series." + } + }, + "required": [ + "data", + "mark" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "$schema": { + "description": "A [JSON schema](http://json-schema.org/) URL for this specification, such as https://uwdata.github.io/mosaic/schema/latest.json. This property enables validation and autocomplete in editors with JSON schema support.", + "format": "uri", + "type": "string" + }, + "ariaDescription": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-description][1]; a constant textual description.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-description" + }, + "ariaHidden": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-hidden][1] state; a constant indicating whether the element is exposed to an accessibility API.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-hidden" + }, + "ariaLabel": { + "$ref": "#/definitions/ChannelValue", + "description": "The [aria-label][1]; a channel specifying short textual labels representing the value in the accessibility tree.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-label" + }, + "bandwidth": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The kernel density bandwidth for smoothing, in pixels. Defaults to 20." + }, + "bins": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The number of bins over which to discretize the data prior to smoothing. Defaults to 1024." + }, + "clip": { + "anyOf": [ + { + "const": "frame", + "type": "string" + }, + { + "const": "sphere", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to clip the mark; one of:\n\n- *frame* or true - clip to the plot’s frame (inner area)\n- *sphere* - clip to the projected sphere (*e.g.*, front hemisphere)\n- null or false - do not clip\n\nThe *sphere* clip option requires a geographic projection." + }, + "config": { + "$ref": "#/definitions/Config", + "description": "Configuration options." + }, + "curve": { + "anyOf": [ + { + "$ref": "#/definitions/Curve" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The curve (interpolation) method for connecting adjacent points. One of:\n\n- *basis* - a cubic basis spline (repeating the end points)\n- *basis-open* - an open cubic basis spline\n- *basis-closed* - a closed cubic basis spline\n- *bump-x* - a Bézier curve with horizontal tangents\n- *bump-y* - a Bézier curve with vertical tangents\n- *bundle* - a straightened cubic basis spline (suitable for lines only, not areas)\n- *cardinal* - a cubic cardinal spline (with one-sided differences at the ends)\n- *cardinal-open* - an open cubic cardinal spline\n- *cardinal-closed* - an closed cubic cardinal spline\n- *catmull-rom* - a cubic Catmull–Rom spline (with one-sided differences at the ends)\n- *catmull-rom-open* - an open cubic Catmull–Rom spline\n- *catmull-rom-closed* - a closed cubic Catmull–Rom spline\n- *linear* - a piecewise linear curve (*i.e.*, straight line segments)\n- *linear-closed* - a closed piecewise linear curve (*i.e.*, straight line segments)\n- *monotone-x* - a cubic spline that preserves monotonicity in *x*\n- *monotone-y* - a cubic spline that preserves monotonicity in *y*\n- *natural* - a natural cubic spline\n- *step* - a piecewise constant function where *y* changes at the midpoint of *x*\n- *step-after* - a piecewise constant function where *y* changes after *x*\n- *step-before* - a piecewise constant function where *x* changes after *y*" + }, + "data": { + "$ref": "#/definitions/Data", + "description": "Dataset definitions." + }, + "dx": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The horizontal offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "dy": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The vertical offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "facet": { + "anyOf": [ + { + "const": "auto", + "type": "string" + }, + { + "const": "include", + "type": "string" + }, + { + "const": "exclude", + "type": "string" + }, + { + "const": "super", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to enable or disable faceting; one of:\n\n- *auto* (default) - automatically determine if this mark should be faceted\n- *include* (or true) - draw the subset of the mark’s data in the current facet\n- *exclude* - draw the subset of the mark’s data *not* in the current facet\n- *super* - draw this mark in a single frame that covers all facets\n- null (or false) - repeat this mark’s data across all facets (*i.e.*, no faceting)\n\nWhen a mark uses *super* faceting, it is not allowed to use position scales (*x*, *y*, *fx*, or *fy*); *super* faceting is intended for decorations, such as labels and legends.\n\nWhen top-level faceting is used, the default *auto* setting is equivalent to *include* when the mark data is strictly equal to the top-level facet data; otherwise it is equivalent to null. When the *include* or *exclude* facet mode is chosen, the mark data must be parallel to the top-level facet data: the data must have the same length and order. If the data are not parallel, then the wrong data may be shown in each facet. The default\n*auto* therefore requires strict equality (`===`) for safety, and using the facet data as mark data is recommended when using the *exclude* facet mode. (To construct parallel data safely, consider using [*array*.map][1] on the facet data.)\n\nWhen mark-level faceting is used, the default *auto* setting is equivalent to *include*: the mark will be faceted if either the **fx** or **fy** channel option (or both) is specified. The null or false option will disable faceting, while *exclude* draws the subset of the mark’s data *not* in the current facet.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map" + }, + "facetAnchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "right", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "const": "left", + "type": "string" + }, + { + "const": "top-left", + "type": "string" + }, + { + "const": "top-right", + "type": "string" + }, + { + "const": "bottom-left", + "type": "string" + }, + { + "const": "bottom-right", + "type": "string" + }, + { + "const": "top-empty", + "type": "string" + }, + { + "const": "right-empty", + "type": "string" + }, + { + "const": "bottom-empty", + "type": "string" + }, + { + "const": "left-empty", + "type": "string" + }, + { + "const": "empty", + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to place the mark with respect to facets; one of:\n\n- null (default for most marks) - display the mark in each non-empty facet\n- *top*, *right*, *bottom*, or *left* - display the mark only in facets on the given side\n- *top-empty*, *right-empty*, *bottom-empty*, or *left-empty* (default for axis marks) - display the mark only in facets that have empty space on the given side: either the margin, or an empty facet\n- *empty* - display the mark in empty facets only" + }, + "fill": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill" + }, + "fillOpacity": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill-opacity][1]; a constant number between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill-opacity" + }, + "filter": { + "$ref": "#/definitions/ChannelValue", + "description": "Applies a transform to filter the mark’s index according to the given channel values; only truthy values are retained.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "fx": { + "$ref": "#/definitions/ChannelValue", + "description": "The horizontal facet position channel, for mark-level faceting, bound to the *fx* scale." + }, + "fy": { + "$ref": "#/definitions/ChannelValue", + "description": "The vertical facet position channel, for mark-level faceting, bound to the\n*fy* scale." + }, + "href": { + "$ref": "#/definitions/ChannelValue", + "description": "The [href][1]; a channel specifying URLs for clickable links. May be used in conjunction with the **target** option to open links in another window.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/href" + }, + "imageFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A CSS [filter][1]; a constant string used to adjust the rendering of images, such as *blur(5px)*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/filter" + }, + "margin": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four mark margins: **marginTop**,\n**marginRight**, **marginBottom**, and **marginLeft**; typically defaults to 0, except for axis marks." + }, + "marginBottom": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s bottom margin; the minimum distance in pixels between the bottom edges of the inner and outer plot area." + }, + "marginLeft": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s left margin; the minimum distance in pixels between the left edges of the inner and outer plot area." + }, + "marginRight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s right margin; the minimum distance in pixels between the right edges of the mark’s inner and outer plot area." + }, + "marginTop": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s top margin; the minimum distance in pixels between the top edges of the inner and outer plot area." + }, + "mark": { + "const": "densityX", + "description": "A densityX mark that visualizes smoothed point cloud densities along the\n**x** dimension. The mark bins the data, counts the number of records that fall into each bin, smooths the resulting counts, and then plots the smoothed distribution, by default using an areaX mark.\n\nSet the *type* property to use a different base mark type.", + "type": "string" + }, + "meta": { + "$ref": "#/definitions/Meta", + "description": "Specification metadata." + }, + "mixBlendMode": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [mix-blend-mode][1]; a constant string specifying how to blend content such as *multiply*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode" + }, + "offset": { + "anyOf": [ + { + "$ref": "#/definitions/StackOffset" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "After stacking, an optional **offset** can be applied to translate and scale stacks, say to produce a streamgraph; defaults to null for a zero baseline (**y** = 0 for stackY, and **x** = 0 for stackX). If the *wiggle* offset is used, the default **order** changes to *inside-out*." + }, + "opacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally. For faster rendering, prefer the **strokeOpacity** or **fillOpacity** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/opacity" + }, + "order": { + "anyOf": [ + { + "$ref": "#/definitions/StackOrder" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The order in which stacks are layered; one of:\n\n- null (default) for input order\n- a named stack order method such as *inside-out* or *sum*\n- a field name, for natural order of the corresponding values\n- a function of data, for natural order of the corresponding values\n- an array of explicit **z** values in the desired order\n\nIf the *wiggle* **offset** is used, as for a streamgraph, the default changes to *inside-out*." + }, + "paintOrder": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [paint-order][1]; a constant string specifying the order in which the\n**fill**, **stroke**, and any markers are drawn; defaults to *normal*, which draws the fill, then stroke, then markers; defaults to *stroke* for the text mark to create a “halo” around text to improve legibility.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/paint-order" + }, + "params": { + "$ref": "#/definitions/Params", + "description": "Param and Selection definitions." + }, + "plotDefaults": { + "$ref": "#/definitions/PlotAttributes", + "description": "A default set of attributes to apply to all plot components." + }, + "pointerEvents": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [pointer-events][1] property; a constant string such as *none*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/pointer-events" + }, + "reverse": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Applies a transform to reverse the order of the mark’s index, say for reverse input order." + }, + "select": { + "$ref": "#/definitions/SelectFilter", + "description": "Applies a filter transform after data is loaded to highlight selected values only. For example, `first` and `last` select the first or last values of series only (using the *z* channel to separate series). Meanwhile, `nearestX` and `nearestY` select the point nearest to the pointer along the *x* or *y* channel dimension. Unlike Mosaic selections, a mark level *select* is internal to the mark only, and does not populate a param or selection value to be shared across clients.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "shapeRendering": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [shape-rendering][1]; a constant string such as *crispEdges*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/shape-rendering" + }, + "sort": { + "anyOf": [ + { + "$ref": "#/definitions/SortOrder" + }, + { + "$ref": "#/definitions/ChannelDomainSort" + } + ], + "description": "Either applies a transform to sort the mark’s index by the specified channel values, or imputes ordinal scale domains from this mark’s channels.\n\nWhen imputing ordinal scale domains from channel values, the **sort** option is an object whose keys are ordinal scale names such as *x* or *fx*, and whose values are channel names such as *y*, *y1*, or *y2*. For example, to impute the *y* scale’s domain from the associated *x* channel values in ascending order:\n\n```js sort: {y: \"x\"} ```\n\nFor different sort options for different scales, replace the channel name with a *value* object and per-scale options:\n\n```js sort: {y: {value: \"-x\"}} ```\n\nWhen sorting the mark’s index, the **sort** option is instead one of:\n\n- a channel value definition for sorting given values in ascending order\n- a {value, order} object for sorting given values\n- a {channel, order} object for sorting the named channel’s values" + }, + "stroke": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke" + }, + "strokeDasharray": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dasharray][1]; a constant number indicating the length in pixels of alternating dashes and gaps, or a constant string of numbers separated by spaces or commas (_e.g._, *10 2* for dashes of 10 pixels separated by gaps of 2 pixels), or *none* (the default) for no dashing\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dasharray" + }, + "strokeDashoffset": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dashoffset][1]; a constant indicating the offset in pixels of the first dash along the stroke; defaults to zero.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dashoffset" + }, + "strokeLinecap": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linecap][1]; a constant specifying how to cap stroked paths, such as *butt*, *round*, or *square*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linecap" + }, + "strokeLinejoin": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linejoin][1]; a constant specifying how to join stroked paths, such as *bevel*, *miter*, *miter-clip*, or *round*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linejoin" + }, + "strokeMiterlimit": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-miterlimit][1]; a constant number specifying how to limit the length of *miter* joins on stroked paths.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-miterlimit" + }, + "strokeOpacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-opacity" + }, + "strokeWidth": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-width][1]; a constant number in pixels, or a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-width" + }, + "target": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [target][1]; a constant string specifying the target window (_e.g._,\n*_blank*) for clickable links; used in conjunction with the **href** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/target" + }, + "tension": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The tension option only has an effect on bundle, cardinal and Catmull–Rom splines (*bundle*, *cardinal*, *cardinal-open*, *cardinal-closed*,\n*catmull-rom*, *catmull-rom-open*, and *catmull-rom-closed*). For bundle splines, it corresponds to [beta][1]; for cardinal splines, [tension][2]; for Catmull–Rom splines, [alpha][3].\n\n[1]: https://d3js.org/d3-shape/curve#curveBundle_beta [2]: https://d3js.org/d3-shape/curve#curveCardinal_tension [3]: https://d3js.org/d3-shape/curve#curveCatmullRom_alpha" + }, + "tip": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/TipPointer" + }, + { + "properties": { + "anchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The tip anchor specifies how to orient the tip box relative to its anchor position; it refers to the part of the tip box that is attached to the anchor point. For example, the *top-left* anchor places the top-left corner of tip box near the anchor position, hence placing the tip box below and to the right of the anchor position." + }, + "fontFamily": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font-family][1]; a constant; defaults to the plot’s font family, which is typically [*system-ui*][2].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-family [2]: https://drafts.csswg.org/css-fonts-4/#valdef-font-family-system-ui" + }, + "fontSize": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font size][1] in pixels; either a constant or a channel; defaults to the plot’s font size, which is typically 10. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-size" + }, + "fontStyle": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font style][1]; a constant; defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-style" + }, + "fontVariant": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font variant][1]; a constant; if the **text** channel contains numbers or dates, defaults to *tabular-nums* to facilitate comparing numbers; otherwise defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant" + }, + "fontWeight": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font weight][1]; a constant; defaults to the plot’s font weight, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight" + }, + "format": { + "additionalProperties": false, + "description": "How channel values are formatted for display. If a format is a string, it is interpreted as a (UTC) time format for temporal channels, and otherwise a number format.", + "properties": { + "ariaLabel": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fill": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fillOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fontSize": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fx": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fy": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "geometry": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "height": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "href": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "length": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "opacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "path": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "r": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "rotate": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "src": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "stroke": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeWidth": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "symbol": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "text": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "title": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "weight": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "width": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "z": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + } + }, + "type": "object" + }, + "frameAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The frame anchor specifies defaults for **x** and **y** based on the plot’s frame; it may be one of the four sides (*top*, *right*, *bottom*, *left*), one of the four corners (*top-left*, *top-right*, *bottom-right*,\n*bottom-left*), or the *middle* of the frame. For example, for tips distributed horizontally at the top of the frame:\n\n```js Plot.tip(data, {x: \"date\", frameAnchor: \"top\"}) ```" + }, + "lineHeight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line height in ems; defaults to 1. The line height affects the (typically vertical) separation between adjacent baselines of text, as well as the separation between the text and its anchor point." + }, + "lineWidth": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line width in ems (e.g., 10 for about 20 characters); defaults to infinity, disabling wrapping and clipping.\n\nIf **textOverflow** is null, lines will be wrapped at the specified length. If a line is split at a soft hyphen (\\xad), a hyphen (-) will be displayed at the end of the line. If **textOverflow** is not null, lines will be clipped according to the given strategy." + }, + "monospace": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, changes the default **fontFamily** to *monospace*, and uses simplified monospaced text metrics calculations." + }, + "pathFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The image filter for the tip’s box; defaults to a drop shadow." + }, + "pointer": { + "$ref": "#/definitions/TipPointer" + }, + "pointerSize": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The size of the tip’s pointer in pixels; defaults to 12." + }, + "preferredAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If an explicit tip anchor is not specified, an anchor is chosen automatically such that the tip fits within the plot’s frame; if the preferred anchor fits, it is chosen." + }, + "textAnchor": { + "anyOf": [ + { + "const": "start", + "type": "string" + }, + { + "const": "middle", + "type": "string" + }, + { + "const": "end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [text anchor][1] controls how text is aligned (typically horizontally) relative to its anchor point; it is one of *start*, *end*, or *middle*. If the frame anchor is *left*, *top-left*, or *bottom-left*, the default text anchor is *start*; if the frame anchor is *right*, *top-right*, or\n*bottom-right*, the default is *end*; otherwise it is *middle*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/text-anchor" + }, + "textOverflow": { + "anyOf": [ + { + "type": "null" + }, + { + "const": "clip", + "type": "string" + }, + { + "const": "ellipsis", + "type": "string" + }, + { + "const": "clip-start", + "type": "string" + }, + { + "const": "clip-end", + "type": "string" + }, + { + "const": "ellipsis-start", + "type": "string" + }, + { + "const": "ellipsis-middle", + "type": "string" + }, + { + "const": "ellipsis-end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How truncate (or wrap) lines of text longer than the given **lineWidth**; one of:\n\n- null (default) - preserve overflowing characters (and wrap if needed)\n- *clip* or *clip-end* - remove characters from the end\n- *clip-start* - remove characters from the start\n- *ellipsis* or *ellipsis-end* - replace characters from the end with an ellipsis (…)\n- *ellipsis-start* - replace characters from the start with an ellipsis (…)\n- *ellipsis-middle* - replace characters from the middle with an ellipsis (…)\n\nIf no **title** was specified, if text requires truncation, a title containing the non-truncated text will be implicitly added." + }, + "textPadding": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The padding around the text in pixels; defaults to 8." + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + } + }, + "type": "object" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to generate a tooltip for this mark, and any tip options." + }, + "title": { + "$ref": "#/definitions/ChannelValue", + "description": "The title; a channel specifying accessible, short textual descriptions as strings (possibly with newlines). If the tip option is specified, the title will be displayed with an interactive tooltip instead of using the SVG [title element][1].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/title" + }, + "type": { + "const": "areaX", + "description": "The basic mark type to use to render 1D density values. Defaults to an areaX mark; lineX, dotX, and textX marks are also supported.", + "type": "string" + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel, typically bound to the *y* scale; defaults to the zero-based index of the data [0, 1, 2, …]." + }, + "z": { + "$ref": "#/definitions/ChannelValue", + "description": "An optional ordinal channel for grouping data into (possibly stacked) series to be drawn as separate areas; defaults to **fill** if a channel, or\n**stroke** if a channel." + } + }, + "required": [ + "data", + "mark", + "type" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "$schema": { + "description": "A [JSON schema](http://json-schema.org/) URL for this specification, such as https://uwdata.github.io/mosaic/schema/latest.json. This property enables validation and autocomplete in editors with JSON schema support.", + "format": "uri", + "type": "string" + }, + "ariaDescription": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-description][1]; a constant textual description.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-description" + }, + "ariaHidden": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-hidden][1] state; a constant indicating whether the element is exposed to an accessibility API.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-hidden" + }, + "ariaLabel": { + "$ref": "#/definitions/ChannelValue", + "description": "The [aria-label][1]; a channel specifying short textual labels representing the value in the accessibility tree.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-label" + }, + "bandwidth": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The kernel density bandwidth for smoothing, in pixels. Defaults to 20." + }, + "bins": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The number of bins over which to discretize the data prior to smoothing. Defaults to 1024." + }, + "clip": { + "anyOf": [ + { + "const": "frame", + "type": "string" + }, + { + "const": "sphere", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to clip the mark; one of:\n\n- *frame* or true - clip to the plot’s frame (inner area)\n- *sphere* - clip to the projected sphere (*e.g.*, front hemisphere)\n- null or false - do not clip\n\nThe *sphere* clip option requires a geographic projection." + }, + "config": { + "$ref": "#/definitions/Config", + "description": "Configuration options." + }, + "curve": { + "anyOf": [ + { + "$ref": "#/definitions/Curve" + }, + { + "const": "auto", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The curve (interpolation) method for connecting adjacent points. One of:\n\n- *basis* - a cubic basis spline (repeating the end points)\n- *basis-open* - an open cubic basis spline\n- *basis-closed* - a closed cubic basis spline\n- *bump-x* - a Bézier curve with horizontal tangents\n- *bump-y* - a Bézier curve with vertical tangents\n- *bundle* - a straightened cubic basis spline (suitable for lines only, not areas)\n- *cardinal* - a cubic cardinal spline (with one-sided differences at the ends)\n- *cardinal-open* - an open cubic cardinal spline\n- *cardinal-closed* - an closed cubic cardinal spline\n- *catmull-rom* - a cubic Catmull–Rom spline (with one-sided differences at the ends)\n- *catmull-rom-open* - an open cubic Catmull–Rom spline\n- *catmull-rom-closed* - a closed cubic Catmull–Rom spline\n- *linear* - a piecewise linear curve (*i.e.*, straight line segments)\n- *linear-closed* - a closed piecewise linear curve (*i.e.*, straight line segments)\n- *monotone-x* - a cubic spline that preserves monotonicity in *x*\n- *monotone-y* - a cubic spline that preserves monotonicity in *y*\n- *natural* - a natural cubic spline\n- *step* - a piecewise constant function where *y* changes at the midpoint of *x*\n- *step-after* - a piecewise constant function where *y* changes after *x*\n- *step-before* - a piecewise constant function where *x* changes after *y*\n- *auto* (default) - like *linear*, but use the (possibly spherical) projection, if any\n\nThe *auto* curve is typically used in conjunction with a spherical projection to interpolate along geodesics." + }, + "data": { + "$ref": "#/definitions/Data", + "description": "Dataset definitions." + }, + "dx": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The horizontal offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "dy": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The vertical offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "facet": { + "anyOf": [ + { + "const": "auto", + "type": "string" + }, + { + "const": "include", + "type": "string" + }, + { + "const": "exclude", + "type": "string" + }, + { + "const": "super", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to enable or disable faceting; one of:\n\n- *auto* (default) - automatically determine if this mark should be faceted\n- *include* (or true) - draw the subset of the mark’s data in the current facet\n- *exclude* - draw the subset of the mark’s data *not* in the current facet\n- *super* - draw this mark in a single frame that covers all facets\n- null (or false) - repeat this mark’s data across all facets (*i.e.*, no faceting)\n\nWhen a mark uses *super* faceting, it is not allowed to use position scales (*x*, *y*, *fx*, or *fy*); *super* faceting is intended for decorations, such as labels and legends.\n\nWhen top-level faceting is used, the default *auto* setting is equivalent to *include* when the mark data is strictly equal to the top-level facet data; otherwise it is equivalent to null. When the *include* or *exclude* facet mode is chosen, the mark data must be parallel to the top-level facet data: the data must have the same length and order. If the data are not parallel, then the wrong data may be shown in each facet. The default\n*auto* therefore requires strict equality (`===`) for safety, and using the facet data as mark data is recommended when using the *exclude* facet mode. (To construct parallel data safely, consider using [*array*.map][1] on the facet data.)\n\nWhen mark-level faceting is used, the default *auto* setting is equivalent to *include*: the mark will be faceted if either the **fx** or **fy** channel option (or both) is specified. The null or false option will disable faceting, while *exclude* draws the subset of the mark’s data *not* in the current facet.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map" + }, + "facetAnchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "right", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "const": "left", + "type": "string" + }, + { + "const": "top-left", + "type": "string" + }, + { + "const": "top-right", + "type": "string" + }, + { + "const": "bottom-left", + "type": "string" + }, + { + "const": "bottom-right", + "type": "string" + }, + { + "const": "top-empty", + "type": "string" + }, + { + "const": "right-empty", + "type": "string" + }, + { + "const": "bottom-empty", + "type": "string" + }, + { + "const": "left-empty", + "type": "string" + }, + { + "const": "empty", + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to place the mark with respect to facets; one of:\n\n- null (default for most marks) - display the mark in each non-empty facet\n- *top*, *right*, *bottom*, or *left* - display the mark only in facets on the given side\n- *top-empty*, *right-empty*, *bottom-empty*, or *left-empty* (default for axis marks) - display the mark only in facets that have empty space on the given side: either the margin, or an empty facet\n- *empty* - display the mark in empty facets only" + }, + "fill": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill" + }, + "fillOpacity": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill-opacity][1]; a constant number between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill-opacity" + }, + "filter": { + "$ref": "#/definitions/ChannelValue", + "description": "Applies a transform to filter the mark’s index according to the given channel values; only truthy values are retained.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "fx": { + "$ref": "#/definitions/ChannelValue", + "description": "The horizontal facet position channel, for mark-level faceting, bound to the *fx* scale." + }, + "fy": { + "$ref": "#/definitions/ChannelValue", + "description": "The vertical facet position channel, for mark-level faceting, bound to the\n*fy* scale." + }, + "href": { + "$ref": "#/definitions/ChannelValue", + "description": "The [href][1]; a channel specifying URLs for clickable links. May be used in conjunction with the **target** option to open links in another window.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/href" + }, + "imageFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A CSS [filter][1]; a constant string used to adjust the rendering of images, such as *blur(5px)*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/filter" + }, + "margin": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four mark margins: **marginTop**,\n**marginRight**, **marginBottom**, and **marginLeft**; typically defaults to 0, except for axis marks." + }, + "marginBottom": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s bottom margin; the minimum distance in pixels between the bottom edges of the inner and outer plot area." + }, + "marginLeft": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s left margin; the minimum distance in pixels between the left edges of the inner and outer plot area." + }, + "marginRight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s right margin; the minimum distance in pixels between the right edges of the mark’s inner and outer plot area." + }, + "marginTop": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s top margin; the minimum distance in pixels between the top edges of the inner and outer plot area." + }, + "mark": { + "const": "densityX", + "description": "A densityX mark that visualizes smoothed point cloud densities along the\n**x** dimension. The mark bins the data, counts the number of records that fall into each bin, smooths the resulting counts, and then plots the smoothed distribution, by default using an areaX mark.\n\nSet the *type* property to use a different base mark type.", + "type": "string" + }, + "marker": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for markerStart, markerMid, and markerEnd; one of:\n\n- a marker name such as *arrow* or *circle*\n- *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*" + }, + "markerEnd": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The marker for the ending point of a line segment; one of:\n\n- a marker name such as *arrow* or *circle*\n* *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*" + }, + "markerMid": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The marker for any middle (interior) points of a line segment. If the line segment only has a start and end point, this option has no effect. One of:\n\n- a marker name such as *arrow* or *circle*\n* *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*\n* a function - a custom marker function; see below" + }, + "markerStart": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The marker for the starting point of a line segment; one of:\n\n- a marker name such as *arrow* or *circle*\n* *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*" + }, + "meta": { + "$ref": "#/definitions/Meta", + "description": "Specification metadata." + }, + "mixBlendMode": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [mix-blend-mode][1]; a constant string specifying how to blend content such as *multiply*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode" + }, + "opacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally. For faster rendering, prefer the **strokeOpacity** or **fillOpacity** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/opacity" + }, + "paintOrder": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [paint-order][1]; a constant string specifying the order in which the\n**fill**, **stroke**, and any markers are drawn; defaults to *normal*, which draws the fill, then stroke, then markers; defaults to *stroke* for the text mark to create a “halo” around text to improve legibility.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/paint-order" + }, + "params": { + "$ref": "#/definitions/Params", + "description": "Param and Selection definitions." + }, + "plotDefaults": { + "$ref": "#/definitions/PlotAttributes", + "description": "A default set of attributes to apply to all plot components." + }, + "pointerEvents": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [pointer-events][1] property; a constant string such as *none*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/pointer-events" + }, + "reverse": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Applies a transform to reverse the order of the mark’s index, say for reverse input order." + }, + "select": { + "$ref": "#/definitions/SelectFilter", + "description": "Applies a filter transform after data is loaded to highlight selected values only. For example, `first` and `last` select the first or last values of series only (using the *z* channel to separate series). Meanwhile, `nearestX` and `nearestY` select the point nearest to the pointer along the *x* or *y* channel dimension. Unlike Mosaic selections, a mark level *select* is internal to the mark only, and does not populate a param or selection value to be shared across clients.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "shapeRendering": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [shape-rendering][1]; a constant string such as *crispEdges*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/shape-rendering" + }, + "sort": { + "anyOf": [ + { + "$ref": "#/definitions/SortOrder" + }, + { + "$ref": "#/definitions/ChannelDomainSort" + } + ], + "description": "Either applies a transform to sort the mark’s index by the specified channel values, or imputes ordinal scale domains from this mark’s channels.\n\nWhen imputing ordinal scale domains from channel values, the **sort** option is an object whose keys are ordinal scale names such as *x* or *fx*, and whose values are channel names such as *y*, *y1*, or *y2*. For example, to impute the *y* scale’s domain from the associated *x* channel values in ascending order:\n\n```js sort: {y: \"x\"} ```\n\nFor different sort options for different scales, replace the channel name with a *value* object and per-scale options:\n\n```js sort: {y: {value: \"-x\"}} ```\n\nWhen sorting the mark’s index, the **sort** option is instead one of:\n\n- a channel value definition for sorting given values in ascending order\n- a {value, order} object for sorting given values\n- a {channel, order} object for sorting the named channel’s values" + }, + "stroke": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke" + }, + "strokeDasharray": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dasharray][1]; a constant number indicating the length in pixels of alternating dashes and gaps, or a constant string of numbers separated by spaces or commas (_e.g._, *10 2* for dashes of 10 pixels separated by gaps of 2 pixels), or *none* (the default) for no dashing\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dasharray" + }, + "strokeDashoffset": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dashoffset][1]; a constant indicating the offset in pixels of the first dash along the stroke; defaults to zero.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dashoffset" + }, + "strokeLinecap": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linecap][1]; a constant specifying how to cap stroked paths, such as *butt*, *round*, or *square*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linecap" + }, + "strokeLinejoin": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linejoin][1]; a constant specifying how to join stroked paths, such as *bevel*, *miter*, *miter-clip*, or *round*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linejoin" + }, + "strokeMiterlimit": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-miterlimit][1]; a constant number specifying how to limit the length of *miter* joins on stroked paths.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-miterlimit" + }, + "strokeOpacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-opacity" + }, + "strokeWidth": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-width][1]; a constant number in pixels, or a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-width" + }, + "target": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [target][1]; a constant string specifying the target window (_e.g._,\n*_blank*) for clickable links; used in conjunction with the **href** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/target" + }, + "tension": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The tension option only has an effect on bundle, cardinal and Catmull–Rom splines (*bundle*, *cardinal*, *cardinal-open*, *cardinal-closed*,\n*catmull-rom*, *catmull-rom-open*, and *catmull-rom-closed*). For bundle splines, it corresponds to [beta][1]; for cardinal splines, [tension][2]; for Catmull–Rom splines, [alpha][3].\n\n[1]: https://d3js.org/d3-shape/curve#curveBundle_beta [2]: https://d3js.org/d3-shape/curve#curveCardinal_tension [3]: https://d3js.org/d3-shape/curve#curveCatmullRom_alpha" + }, + "tip": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/TipPointer" + }, + { + "properties": { + "anchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The tip anchor specifies how to orient the tip box relative to its anchor position; it refers to the part of the tip box that is attached to the anchor point. For example, the *top-left* anchor places the top-left corner of tip box near the anchor position, hence placing the tip box below and to the right of the anchor position." + }, + "fontFamily": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font-family][1]; a constant; defaults to the plot’s font family, which is typically [*system-ui*][2].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-family [2]: https://drafts.csswg.org/css-fonts-4/#valdef-font-family-system-ui" + }, + "fontSize": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font size][1] in pixels; either a constant or a channel; defaults to the plot’s font size, which is typically 10. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-size" + }, + "fontStyle": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font style][1]; a constant; defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-style" + }, + "fontVariant": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font variant][1]; a constant; if the **text** channel contains numbers or dates, defaults to *tabular-nums* to facilitate comparing numbers; otherwise defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant" + }, + "fontWeight": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font weight][1]; a constant; defaults to the plot’s font weight, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight" + }, + "format": { + "additionalProperties": false, + "description": "How channel values are formatted for display. If a format is a string, it is interpreted as a (UTC) time format for temporal channels, and otherwise a number format.", + "properties": { + "ariaLabel": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fill": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fillOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fontSize": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fx": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fy": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "geometry": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "height": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "href": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "length": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "opacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "path": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "r": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "rotate": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "src": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "stroke": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeWidth": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "symbol": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "text": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "title": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "weight": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "width": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "z": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + } + }, + "type": "object" + }, + "frameAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The frame anchor specifies defaults for **x** and **y** based on the plot’s frame; it may be one of the four sides (*top*, *right*, *bottom*, *left*), one of the four corners (*top-left*, *top-right*, *bottom-right*,\n*bottom-left*), or the *middle* of the frame. For example, for tips distributed horizontally at the top of the frame:\n\n```js Plot.tip(data, {x: \"date\", frameAnchor: \"top\"}) ```" + }, + "lineHeight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line height in ems; defaults to 1. The line height affects the (typically vertical) separation between adjacent baselines of text, as well as the separation between the text and its anchor point." + }, + "lineWidth": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line width in ems (e.g., 10 for about 20 characters); defaults to infinity, disabling wrapping and clipping.\n\nIf **textOverflow** is null, lines will be wrapped at the specified length. If a line is split at a soft hyphen (\\xad), a hyphen (-) will be displayed at the end of the line. If **textOverflow** is not null, lines will be clipped according to the given strategy." + }, + "monospace": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, changes the default **fontFamily** to *monospace*, and uses simplified monospaced text metrics calculations." + }, + "pathFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The image filter for the tip’s box; defaults to a drop shadow." + }, + "pointer": { + "$ref": "#/definitions/TipPointer" + }, + "pointerSize": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The size of the tip’s pointer in pixels; defaults to 12." + }, + "preferredAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If an explicit tip anchor is not specified, an anchor is chosen automatically such that the tip fits within the plot’s frame; if the preferred anchor fits, it is chosen." + }, + "textAnchor": { + "anyOf": [ + { + "const": "start", + "type": "string" + }, + { + "const": "middle", + "type": "string" + }, + { + "const": "end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [text anchor][1] controls how text is aligned (typically horizontally) relative to its anchor point; it is one of *start*, *end*, or *middle*. If the frame anchor is *left*, *top-left*, or *bottom-left*, the default text anchor is *start*; if the frame anchor is *right*, *top-right*, or\n*bottom-right*, the default is *end*; otherwise it is *middle*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/text-anchor" + }, + "textOverflow": { + "anyOf": [ + { + "type": "null" + }, + { + "const": "clip", + "type": "string" + }, + { + "const": "ellipsis", + "type": "string" + }, + { + "const": "clip-start", + "type": "string" + }, + { + "const": "clip-end", + "type": "string" + }, + { + "const": "ellipsis-start", + "type": "string" + }, + { + "const": "ellipsis-middle", + "type": "string" + }, + { + "const": "ellipsis-end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How truncate (or wrap) lines of text longer than the given **lineWidth**; one of:\n\n- null (default) - preserve overflowing characters (and wrap if needed)\n- *clip* or *clip-end* - remove characters from the end\n- *clip-start* - remove characters from the start\n- *ellipsis* or *ellipsis-end* - replace characters from the end with an ellipsis (…)\n- *ellipsis-start* - replace characters from the start with an ellipsis (…)\n- *ellipsis-middle* - replace characters from the middle with an ellipsis (…)\n\nIf no **title** was specified, if text requires truncation, a title containing the non-truncated text will be implicitly added." + }, + "textPadding": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The padding around the text in pixels; defaults to 8." + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + } + }, + "type": "object" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to generate a tooltip for this mark, and any tip options." + }, + "title": { + "$ref": "#/definitions/ChannelValue", + "description": "The title; a channel specifying accessible, short textual descriptions as strings (possibly with newlines). If the tip option is specified, the title will be displayed with an interactive tooltip instead of using the SVG [title element][1].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/title" + }, + "type": { + "const": "lineX", + "description": "The basic mark type to use to render 1D density values. Defaults to an areaX mark; lineX, dotX, and textX marks are also supported.", + "type": "string" + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel, typically bound to the *y* scale; defaults to the zero-based index of the data [0, 1, 2, …]." + }, + "z": { + "$ref": "#/definitions/ChannelValue", + "description": "An optional ordinal channel for grouping data into (possibly stacked) series to be drawn as separate lines. If not specified, it defaults to\n**fill** if a channel, or **stroke** if a channel." + } + }, + "required": [ + "data", + "mark", + "type" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "$schema": { + "description": "A [JSON schema](http://json-schema.org/) URL for this specification, such as https://uwdata.github.io/mosaic/schema/latest.json. This property enables validation and autocomplete in editors with JSON schema support.", + "format": "uri", + "type": "string" + }, + "ariaDescription": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-description][1]; a constant textual description.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-description" + }, + "ariaHidden": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-hidden][1] state; a constant indicating whether the element is exposed to an accessibility API.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-hidden" + }, + "ariaLabel": { + "$ref": "#/definitions/ChannelValue", + "description": "The [aria-label][1]; a channel specifying short textual labels representing the value in the accessibility tree.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-label" + }, + "bandwidth": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The kernel density bandwidth for smoothing, in pixels. Defaults to 20." + }, + "bins": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The number of bins over which to discretize the data prior to smoothing. Defaults to 1024." + }, + "clip": { + "anyOf": [ + { + "const": "frame", + "type": "string" + }, + { + "const": "sphere", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to clip the mark; one of:\n\n- *frame* or true - clip to the plot’s frame (inner area)\n- *sphere* - clip to the projected sphere (*e.g.*, front hemisphere)\n- null or false - do not clip\n\nThe *sphere* clip option requires a geographic projection." + }, + "config": { + "$ref": "#/definitions/Config", + "description": "Configuration options." + }, + "data": { + "$ref": "#/definitions/Data", + "description": "Dataset definitions." + }, + "dx": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The horizontal offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "dy": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The vertical offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "facet": { + "anyOf": [ + { + "const": "auto", + "type": "string" + }, + { + "const": "include", + "type": "string" + }, + { + "const": "exclude", + "type": "string" + }, + { + "const": "super", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to enable or disable faceting; one of:\n\n- *auto* (default) - automatically determine if this mark should be faceted\n- *include* (or true) - draw the subset of the mark’s data in the current facet\n- *exclude* - draw the subset of the mark’s data *not* in the current facet\n- *super* - draw this mark in a single frame that covers all facets\n- null (or false) - repeat this mark’s data across all facets (*i.e.*, no faceting)\n\nWhen a mark uses *super* faceting, it is not allowed to use position scales (*x*, *y*, *fx*, or *fy*); *super* faceting is intended for decorations, such as labels and legends.\n\nWhen top-level faceting is used, the default *auto* setting is equivalent to *include* when the mark data is strictly equal to the top-level facet data; otherwise it is equivalent to null. When the *include* or *exclude* facet mode is chosen, the mark data must be parallel to the top-level facet data: the data must have the same length and order. If the data are not parallel, then the wrong data may be shown in each facet. The default\n*auto* therefore requires strict equality (`===`) for safety, and using the facet data as mark data is recommended when using the *exclude* facet mode. (To construct parallel data safely, consider using [*array*.map][1] on the facet data.)\n\nWhen mark-level faceting is used, the default *auto* setting is equivalent to *include*: the mark will be faceted if either the **fx** or **fy** channel option (or both) is specified. The null or false option will disable faceting, while *exclude* draws the subset of the mark’s data *not* in the current facet.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map" + }, + "facetAnchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "right", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "const": "left", + "type": "string" + }, + { + "const": "top-left", + "type": "string" + }, + { + "const": "top-right", + "type": "string" + }, + { + "const": "bottom-left", + "type": "string" + }, + { + "const": "bottom-right", + "type": "string" + }, + { + "const": "top-empty", + "type": "string" + }, + { + "const": "right-empty", + "type": "string" + }, + { + "const": "bottom-empty", + "type": "string" + }, + { + "const": "left-empty", + "type": "string" + }, + { + "const": "empty", + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to place the mark with respect to facets; one of:\n\n- null (default for most marks) - display the mark in each non-empty facet\n- *top*, *right*, *bottom*, or *left* - display the mark only in facets on the given side\n- *top-empty*, *right-empty*, *bottom-empty*, or *left-empty* (default for axis marks) - display the mark only in facets that have empty space on the given side: either the margin, or an empty facet\n- *empty* - display the mark in empty facets only" + }, + "fill": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill" + }, + "fillOpacity": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill-opacity][1]; a constant number between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill-opacity" + }, + "filter": { + "$ref": "#/definitions/ChannelValue", + "description": "Applies a transform to filter the mark’s index according to the given channel values; only truthy values are retained.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "frameAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The frame anchor specifies defaults for **x** and **y** based on the plot’s frame; it may be one of the four sides (*top*, *right*, *bottom*, *left*), one of the four corners (*top-left*, *top-right*, *bottom-right*,\n*bottom-left*), or the *middle* of the frame. For example, for dots distributed horizontally at the top of the frame:\n\n```js Plot.dot(data, {x: \"date\", frameAnchor: \"top\"}) ```" + }, + "fx": { + "$ref": "#/definitions/ChannelValue", + "description": "The horizontal facet position channel, for mark-level faceting, bound to the *fx* scale." + }, + "fy": { + "$ref": "#/definitions/ChannelValue", + "description": "The vertical facet position channel, for mark-level faceting, bound to the\n*fy* scale." + }, + "href": { + "$ref": "#/definitions/ChannelValue", + "description": "The [href][1]; a channel specifying URLs for clickable links. May be used in conjunction with the **target** option to open links in another window.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/href" + }, + "imageFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A CSS [filter][1]; a constant string used to adjust the rendering of images, such as *blur(5px)*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/filter" + }, + "margin": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four mark margins: **marginTop**,\n**marginRight**, **marginBottom**, and **marginLeft**; typically defaults to 0, except for axis marks." + }, + "marginBottom": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s bottom margin; the minimum distance in pixels between the bottom edges of the inner and outer plot area." + }, + "marginLeft": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s left margin; the minimum distance in pixels between the left edges of the inner and outer plot area." + }, + "marginRight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s right margin; the minimum distance in pixels between the right edges of the mark’s inner and outer plot area." + }, + "marginTop": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s top margin; the minimum distance in pixels between the top edges of the inner and outer plot area." + }, + "mark": { + "const": "densityX", + "description": "A densityX mark that visualizes smoothed point cloud densities along the\n**x** dimension. The mark bins the data, counts the number of records that fall into each bin, smooths the resulting counts, and then plots the smoothed distribution, by default using an areaX mark.\n\nSet the *type* property to use a different base mark type.", + "type": "string" + }, + "meta": { + "$ref": "#/definitions/Meta", + "description": "Specification metadata." + }, + "mixBlendMode": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [mix-blend-mode][1]; a constant string specifying how to blend content such as *multiply*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode" + }, + "opacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally. For faster rendering, prefer the **strokeOpacity** or **fillOpacity** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/opacity" + }, + "paintOrder": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [paint-order][1]; a constant string specifying the order in which the\n**fill**, **stroke**, and any markers are drawn; defaults to *normal*, which draws the fill, then stroke, then markers; defaults to *stroke* for the text mark to create a “halo” around text to improve legibility.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/paint-order" + }, + "params": { + "$ref": "#/definitions/Params", + "description": "Param and Selection definitions." + }, + "plotDefaults": { + "$ref": "#/definitions/PlotAttributes", + "description": "A default set of attributes to apply to all plot components." + }, + "pointerEvents": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [pointer-events][1] property; a constant string such as *none*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/pointer-events" + }, + "r": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The radius of dots; either a channel or constant. When a number, it is interpreted as a constant radius in pixels. Otherwise it is interpreted as a channel, typically bound to the *r* channel, which defaults to the *sqrt* type for proportional symbols. The radius defaults to 4.5 pixels when using the **symbol** channel, and otherwise 3 pixels. Dots with a nonpositive radius are not drawn." + }, + "reverse": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Applies a transform to reverse the order of the mark’s index, say for reverse input order." + }, + "rotate": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The rotation angle of dots in degrees clockwise; either a channel or a constant. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel. Defaults to 0°, pointing up." + }, + "select": { + "$ref": "#/definitions/SelectFilter", + "description": "Applies a filter transform after data is loaded to highlight selected values only. For example, `first` and `last` select the first or last values of series only (using the *z* channel to separate series). Meanwhile, `nearestX` and `nearestY` select the point nearest to the pointer along the *x* or *y* channel dimension. Unlike Mosaic selections, a mark level *select* is internal to the mark only, and does not populate a param or selection value to be shared across clients.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "shapeRendering": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [shape-rendering][1]; a constant string such as *crispEdges*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/shape-rendering" + }, + "sort": { + "anyOf": [ + { + "$ref": "#/definitions/SortOrder" + }, + { + "$ref": "#/definitions/ChannelDomainSort" + } + ], + "description": "Either applies a transform to sort the mark’s index by the specified channel values, or imputes ordinal scale domains from this mark’s channels.\n\nWhen imputing ordinal scale domains from channel values, the **sort** option is an object whose keys are ordinal scale names such as *x* or *fx*, and whose values are channel names such as *y*, *y1*, or *y2*. For example, to impute the *y* scale’s domain from the associated *x* channel values in ascending order:\n\n```js sort: {y: \"x\"} ```\n\nFor different sort options for different scales, replace the channel name with a *value* object and per-scale options:\n\n```js sort: {y: {value: \"-x\"}} ```\n\nWhen sorting the mark’s index, the **sort** option is instead one of:\n\n- a channel value definition for sorting given values in ascending order\n- a {value, order} object for sorting given values\n- a {channel, order} object for sorting the named channel’s values" + }, + "stroke": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke" + }, + "strokeDasharray": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dasharray][1]; a constant number indicating the length in pixels of alternating dashes and gaps, or a constant string of numbers separated by spaces or commas (_e.g._, *10 2* for dashes of 10 pixels separated by gaps of 2 pixels), or *none* (the default) for no dashing\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dasharray" + }, + "strokeDashoffset": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dashoffset][1]; a constant indicating the offset in pixels of the first dash along the stroke; defaults to zero.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dashoffset" + }, + "strokeLinecap": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linecap][1]; a constant specifying how to cap stroked paths, such as *butt*, *round*, or *square*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linecap" + }, + "strokeLinejoin": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linejoin][1]; a constant specifying how to join stroked paths, such as *bevel*, *miter*, *miter-clip*, or *round*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linejoin" + }, + "strokeMiterlimit": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-miterlimit][1]; a constant number specifying how to limit the length of *miter* joins on stroked paths.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-miterlimit" + }, + "strokeOpacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-opacity" + }, + "strokeWidth": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-width][1]; a constant number in pixels, or a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-width" + }, + "symbol": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/SymbolType" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The categorical symbol; either a channel or a constant. A constant symbol can be specified by a valid symbol name such as *star*, or a symbol object (implementing the draw method); otherwise it is interpreted as a channel. Defaults to *circle* for the **dot** mark, and *hexagon* for the\n**hexagon** mark.\n\nIf the **symbol** channel’s values are all symbols, symbol names, or nullish, the channel is unscaled (values are interpreted literally); otherwise, the channel is bound to the *symbol* scale." + }, + "target": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [target][1]; a constant string specifying the target window (_e.g._,\n*_blank*) for clickable links; used in conjunction with the **href** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/target" + }, + "tip": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/TipPointer" + }, + { + "properties": { + "anchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The tip anchor specifies how to orient the tip box relative to its anchor position; it refers to the part of the tip box that is attached to the anchor point. For example, the *top-left* anchor places the top-left corner of tip box near the anchor position, hence placing the tip box below and to the right of the anchor position." + }, + "fontFamily": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font-family][1]; a constant; defaults to the plot’s font family, which is typically [*system-ui*][2].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-family [2]: https://drafts.csswg.org/css-fonts-4/#valdef-font-family-system-ui" + }, + "fontSize": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font size][1] in pixels; either a constant or a channel; defaults to the plot’s font size, which is typically 10. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-size" + }, + "fontStyle": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font style][1]; a constant; defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-style" + }, + "fontVariant": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font variant][1]; a constant; if the **text** channel contains numbers or dates, defaults to *tabular-nums* to facilitate comparing numbers; otherwise defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant" + }, + "fontWeight": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font weight][1]; a constant; defaults to the plot’s font weight, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight" + }, + "format": { + "additionalProperties": false, + "description": "How channel values are formatted for display. If a format is a string, it is interpreted as a (UTC) time format for temporal channels, and otherwise a number format.", + "properties": { + "ariaLabel": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fill": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fillOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fontSize": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fx": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fy": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "geometry": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "height": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "href": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "length": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "opacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "path": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "r": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "rotate": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "src": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "stroke": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeWidth": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "symbol": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "text": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "title": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "weight": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "width": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "z": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + } + }, + "type": "object" + }, + "frameAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The frame anchor specifies defaults for **x** and **y** based on the plot’s frame; it may be one of the four sides (*top*, *right*, *bottom*, *left*), one of the four corners (*top-left*, *top-right*, *bottom-right*,\n*bottom-left*), or the *middle* of the frame. For example, for tips distributed horizontally at the top of the frame:\n\n```js Plot.tip(data, {x: \"date\", frameAnchor: \"top\"}) ```" + }, + "lineHeight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line height in ems; defaults to 1. The line height affects the (typically vertical) separation between adjacent baselines of text, as well as the separation between the text and its anchor point." + }, + "lineWidth": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line width in ems (e.g., 10 for about 20 characters); defaults to infinity, disabling wrapping and clipping.\n\nIf **textOverflow** is null, lines will be wrapped at the specified length. If a line is split at a soft hyphen (\\xad), a hyphen (-) will be displayed at the end of the line. If **textOverflow** is not null, lines will be clipped according to the given strategy." + }, + "monospace": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, changes the default **fontFamily** to *monospace*, and uses simplified monospaced text metrics calculations." + }, + "pathFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The image filter for the tip’s box; defaults to a drop shadow." + }, + "pointer": { + "$ref": "#/definitions/TipPointer" + }, + "pointerSize": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The size of the tip’s pointer in pixels; defaults to 12." + }, + "preferredAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If an explicit tip anchor is not specified, an anchor is chosen automatically such that the tip fits within the plot’s frame; if the preferred anchor fits, it is chosen." + }, + "textAnchor": { + "anyOf": [ + { + "const": "start", + "type": "string" + }, + { + "const": "middle", + "type": "string" + }, + { + "const": "end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [text anchor][1] controls how text is aligned (typically horizontally) relative to its anchor point; it is one of *start*, *end*, or *middle*. If the frame anchor is *left*, *top-left*, or *bottom-left*, the default text anchor is *start*; if the frame anchor is *right*, *top-right*, or\n*bottom-right*, the default is *end*; otherwise it is *middle*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/text-anchor" + }, + "textOverflow": { + "anyOf": [ + { + "type": "null" + }, + { + "const": "clip", + "type": "string" + }, + { + "const": "ellipsis", + "type": "string" + }, + { + "const": "clip-start", + "type": "string" + }, + { + "const": "clip-end", + "type": "string" + }, + { + "const": "ellipsis-start", + "type": "string" + }, + { + "const": "ellipsis-middle", + "type": "string" + }, + { + "const": "ellipsis-end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How truncate (or wrap) lines of text longer than the given **lineWidth**; one of:\n\n- null (default) - preserve overflowing characters (and wrap if needed)\n- *clip* or *clip-end* - remove characters from the end\n- *clip-start* - remove characters from the start\n- *ellipsis* or *ellipsis-end* - replace characters from the end with an ellipsis (…)\n- *ellipsis-start* - replace characters from the start with an ellipsis (…)\n- *ellipsis-middle* - replace characters from the middle with an ellipsis (…)\n\nIf no **title** was specified, if text requires truncation, a title containing the non-truncated text will be implicitly added." + }, + "textPadding": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The padding around the text in pixels; defaults to 8." + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + } + }, + "type": "object" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to generate a tooltip for this mark, and any tip options." + }, + "title": { + "$ref": "#/definitions/ChannelValue", + "description": "The title; a channel specifying accessible, short textual descriptions as strings (possibly with newlines). If the tip option is specified, the title will be displayed with an interactive tooltip instead of using the SVG [title element][1].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/title" + }, + "type": { + "const": "dotX", + "description": "The basic mark type to use to render 1D density values. Defaults to an areaX mark; lineX, dotX, and textX marks are also supported.", + "type": "string" + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel specifying the dot’s center, typically bound to the *y* scale." + }, + "z": { + "$ref": "#/definitions/ChannelValue", + "description": "An optional ordinal channel for grouping data into series." + } + }, + "required": [ + "data", + "mark", + "type" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "$schema": { + "description": "A [JSON schema](http://json-schema.org/) URL for this specification, such as https://uwdata.github.io/mosaic/schema/latest.json. This property enables validation and autocomplete in editors with JSON schema support.", + "format": "uri", + "type": "string" + }, + "ariaDescription": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-description][1]; a constant textual description.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-description" + }, + "ariaHidden": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-hidden][1] state; a constant indicating whether the element is exposed to an accessibility API.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-hidden" + }, + "ariaLabel": { + "$ref": "#/definitions/ChannelValue", + "description": "The [aria-label][1]; a channel specifying short textual labels representing the value in the accessibility tree.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-label" + }, + "bandwidth": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The kernel density bandwidth for smoothing, in pixels. Defaults to 20." + }, + "bins": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The number of bins over which to discretize the data prior to smoothing. Defaults to 1024." + }, + "clip": { + "anyOf": [ + { + "const": "frame", + "type": "string" + }, + { + "const": "sphere", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to clip the mark; one of:\n\n- *frame* or true - clip to the plot’s frame (inner area)\n- *sphere* - clip to the projected sphere (*e.g.*, front hemisphere)\n- null or false - do not clip\n\nThe *sphere* clip option requires a geographic projection." + }, + "config": { + "$ref": "#/definitions/Config", + "description": "Configuration options." + }, + "data": { + "$ref": "#/definitions/Data", + "description": "Dataset definitions." + }, + "dx": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The horizontal offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "dy": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The vertical offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "facet": { + "anyOf": [ + { + "const": "auto", + "type": "string" + }, + { + "const": "include", + "type": "string" + }, + { + "const": "exclude", + "type": "string" + }, + { + "const": "super", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to enable or disable faceting; one of:\n\n- *auto* (default) - automatically determine if this mark should be faceted\n- *include* (or true) - draw the subset of the mark’s data in the current facet\n- *exclude* - draw the subset of the mark’s data *not* in the current facet\n- *super* - draw this mark in a single frame that covers all facets\n- null (or false) - repeat this mark’s data across all facets (*i.e.*, no faceting)\n\nWhen a mark uses *super* faceting, it is not allowed to use position scales (*x*, *y*, *fx*, or *fy*); *super* faceting is intended for decorations, such as labels and legends.\n\nWhen top-level faceting is used, the default *auto* setting is equivalent to *include* when the mark data is strictly equal to the top-level facet data; otherwise it is equivalent to null. When the *include* or *exclude* facet mode is chosen, the mark data must be parallel to the top-level facet data: the data must have the same length and order. If the data are not parallel, then the wrong data may be shown in each facet. The default\n*auto* therefore requires strict equality (`===`) for safety, and using the facet data as mark data is recommended when using the *exclude* facet mode. (To construct parallel data safely, consider using [*array*.map][1] on the facet data.)\n\nWhen mark-level faceting is used, the default *auto* setting is equivalent to *include*: the mark will be faceted if either the **fx** or **fy** channel option (or both) is specified. The null or false option will disable faceting, while *exclude* draws the subset of the mark’s data *not* in the current facet.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map" + }, + "facetAnchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "right", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "const": "left", + "type": "string" + }, + { + "const": "top-left", + "type": "string" + }, + { + "const": "top-right", + "type": "string" + }, + { + "const": "bottom-left", + "type": "string" + }, + { + "const": "bottom-right", + "type": "string" + }, + { + "const": "top-empty", + "type": "string" + }, + { + "const": "right-empty", + "type": "string" + }, + { + "const": "bottom-empty", + "type": "string" + }, + { + "const": "left-empty", + "type": "string" + }, + { + "const": "empty", + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to place the mark with respect to facets; one of:\n\n- null (default for most marks) - display the mark in each non-empty facet\n- *top*, *right*, *bottom*, or *left* - display the mark only in facets on the given side\n- *top-empty*, *right-empty*, *bottom-empty*, or *left-empty* (default for axis marks) - display the mark only in facets that have empty space on the given side: either the margin, or an empty facet\n- *empty* - display the mark in empty facets only" + }, + "fill": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill" + }, + "fillOpacity": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill-opacity][1]; a constant number between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill-opacity" + }, + "filter": { + "$ref": "#/definitions/ChannelValue", + "description": "Applies a transform to filter the mark’s index according to the given channel values; only truthy values are retained.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "fontFamily": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font-family][1]; a constant; defaults to the plot’s font family, which is typically [*system-ui*][2].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-family [2]: https://drafts.csswg.org/css-fonts-4/#valdef-font-family-system-ui" + }, + "fontSize": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font size][1] in pixels; either a constant or a channel; defaults to the plot’s font size, which is typically 10. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-size" + }, + "fontStyle": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font style][1]; a constant; defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-style" + }, + "fontVariant": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font variant][1]; a constant; if the **text** channel contains numbers or dates, defaults to *tabular-nums* to facilitate comparing numbers; otherwise defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant" + }, + "fontWeight": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font weight][1]; a constant; defaults to the plot’s font weight, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight" + }, + "frameAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The frame anchor specifies defaults for **x** and **y**, along with\n**textAnchor** and **lineAnchor**, based on the plot’s frame; it may be one of the four sides (*top*, *right*, *bottom*, *left*), one of the four corners (*top-left*, *top-right*, *bottom-right*, *bottom-left*), or the\n*middle* of the frame." + }, + "fx": { + "$ref": "#/definitions/ChannelValue", + "description": "The horizontal facet position channel, for mark-level faceting, bound to the *fx* scale." + }, + "fy": { + "$ref": "#/definitions/ChannelValue", + "description": "The vertical facet position channel, for mark-level faceting, bound to the\n*fy* scale." + }, + "href": { + "$ref": "#/definitions/ChannelValue", + "description": "The [href][1]; a channel specifying URLs for clickable links. May be used in conjunction with the **target** option to open links in another window.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/href" + }, + "imageFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A CSS [filter][1]; a constant string used to adjust the rendering of images, such as *blur(5px)*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/filter" + }, + "lineAnchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "middle", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line anchor controls how text is aligned (typically vertically) relative to its anchor point; it is one of *top*, *bottom*, or *middle*. If the frame anchor is *top*, *top-left*, or *top-right*, the default line anchor is *top*; if the frame anchor is *bottom*, *bottom-right*, or\n*bottom-left*, the default is *bottom*; otherwise it is *middle*." + }, + "lineHeight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line height in ems; defaults to 1. The line height affects the (typically vertical) separation between adjacent baselines of text, as well as the separation between the text and its anchor point." + }, + "lineWidth": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line width in ems (e.g., 10 for about 20 characters); defaults to infinity, disabling wrapping and clipping.\n\nIf **textOverflow** is null, lines will be wrapped at the specified length. If a line is split at a soft hyphen (\\xad), a hyphen (-) will be displayed at the end of the line. If **textOverflow** is not null, lines will be clipped according to the given strategy." + }, + "margin": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four mark margins: **marginTop**,\n**marginRight**, **marginBottom**, and **marginLeft**; typically defaults to 0, except for axis marks." + }, + "marginBottom": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s bottom margin; the minimum distance in pixels between the bottom edges of the inner and outer plot area." + }, + "marginLeft": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s left margin; the minimum distance in pixels between the left edges of the inner and outer plot area." + }, + "marginRight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s right margin; the minimum distance in pixels between the right edges of the mark’s inner and outer plot area." + }, + "marginTop": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s top margin; the minimum distance in pixels between the top edges of the inner and outer plot area." + }, + "mark": { + "const": "densityX", + "description": "A densityX mark that visualizes smoothed point cloud densities along the\n**x** dimension. The mark bins the data, counts the number of records that fall into each bin, smooths the resulting counts, and then plots the smoothed distribution, by default using an areaX mark.\n\nSet the *type* property to use a different base mark type.", + "type": "string" + }, + "meta": { + "$ref": "#/definitions/Meta", + "description": "Specification metadata." + }, + "mixBlendMode": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [mix-blend-mode][1]; a constant string specifying how to blend content such as *multiply*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode" + }, + "monospace": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, changes the default **fontFamily** to *monospace*, and uses simplified monospaced text metrics calculations." + }, + "opacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally. For faster rendering, prefer the **strokeOpacity** or **fillOpacity** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/opacity" + }, + "paintOrder": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [paint-order][1]; a constant string specifying the order in which the\n**fill**, **stroke**, and any markers are drawn; defaults to *normal*, which draws the fill, then stroke, then markers; defaults to *stroke* for the text mark to create a “halo” around text to improve legibility.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/paint-order" + }, + "params": { + "$ref": "#/definitions/Params", + "description": "Param and Selection definitions." + }, + "plotDefaults": { + "$ref": "#/definitions/PlotAttributes", + "description": "A default set of attributes to apply to all plot components." + }, + "pointerEvents": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [pointer-events][1] property; a constant string such as *none*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/pointer-events" + }, + "reverse": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Applies a transform to reverse the order of the mark’s index, say for reverse input order." + }, + "rotate": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The rotation angle in degrees clockwise; a constant or a channel; defaults to 0°. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel." + }, + "select": { + "$ref": "#/definitions/SelectFilter", + "description": "Applies a filter transform after data is loaded to highlight selected values only. For example, `first` and `last` select the first or last values of series only (using the *z* channel to separate series). Meanwhile, `nearestX` and `nearestY` select the point nearest to the pointer along the *x* or *y* channel dimension. Unlike Mosaic selections, a mark level *select* is internal to the mark only, and does not populate a param or selection value to be shared across clients.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "shapeRendering": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [shape-rendering][1]; a constant string such as *crispEdges*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/shape-rendering" + }, + "sort": { + "anyOf": [ + { + "$ref": "#/definitions/SortOrder" + }, + { + "$ref": "#/definitions/ChannelDomainSort" + } + ], + "description": "Either applies a transform to sort the mark’s index by the specified channel values, or imputes ordinal scale domains from this mark’s channels.\n\nWhen imputing ordinal scale domains from channel values, the **sort** option is an object whose keys are ordinal scale names such as *x* or *fx*, and whose values are channel names such as *y*, *y1*, or *y2*. For example, to impute the *y* scale’s domain from the associated *x* channel values in ascending order:\n\n```js sort: {y: \"x\"} ```\n\nFor different sort options for different scales, replace the channel name with a *value* object and per-scale options:\n\n```js sort: {y: {value: \"-x\"}} ```\n\nWhen sorting the mark’s index, the **sort** option is instead one of:\n\n- a channel value definition for sorting given values in ascending order\n- a {value, order} object for sorting given values\n- a {channel, order} object for sorting the named channel’s values" + }, + "stroke": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke" + }, + "strokeDasharray": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dasharray][1]; a constant number indicating the length in pixels of alternating dashes and gaps, or a constant string of numbers separated by spaces or commas (_e.g._, *10 2* for dashes of 10 pixels separated by gaps of 2 pixels), or *none* (the default) for no dashing\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dasharray" + }, + "strokeDashoffset": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dashoffset][1]; a constant indicating the offset in pixels of the first dash along the stroke; defaults to zero.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dashoffset" + }, + "strokeLinecap": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linecap][1]; a constant specifying how to cap stroked paths, such as *butt*, *round*, or *square*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linecap" + }, + "strokeLinejoin": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linejoin][1]; a constant specifying how to join stroked paths, such as *bevel*, *miter*, *miter-clip*, or *round*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linejoin" + }, + "strokeMiterlimit": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-miterlimit][1]; a constant number specifying how to limit the length of *miter* joins on stroked paths.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-miterlimit" + }, + "strokeOpacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-opacity" + }, + "strokeWidth": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-width][1]; a constant number in pixels, or a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-width" + }, + "target": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [target][1]; a constant string specifying the target window (_e.g._,\n*_blank*) for clickable links; used in conjunction with the **href** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/target" + }, + "text": { + "$ref": "#/definitions/ChannelValue", + "description": "The text contents channel, possibly with line breaks (\\n, \\r\\n, or \\r). If not specified, defaults to the zero-based index [0, 1, 2, …]." + }, + "textAnchor": { + "anyOf": [ + { + "const": "start", + "type": "string" + }, + { + "const": "middle", + "type": "string" + }, + { + "const": "end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [text anchor][1] controls how text is aligned (typically horizontally) relative to its anchor point; it is one of *start*, *end*, or *middle*. If the frame anchor is *left*, *top-left*, or *bottom-left*, the default text anchor is *start*; if the frame anchor is *right*, *top-right*, or\n*bottom-right*, the default is *end*; otherwise it is *middle*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/text-anchor" + }, + "textOverflow": { + "anyOf": [ + { + "type": "null" + }, + { + "const": "clip", + "type": "string" + }, + { + "const": "ellipsis", + "type": "string" + }, + { + "const": "clip-start", + "type": "string" + }, + { + "const": "clip-end", + "type": "string" + }, + { + "const": "ellipsis-start", + "type": "string" + }, + { + "const": "ellipsis-middle", + "type": "string" + }, + { + "const": "ellipsis-end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How truncate (or wrap) lines of text longer than the given **lineWidth**; one of:\n\n- null (default) - preserve overflowing characters (and wrap if needed)\n- *clip* or *clip-end* - remove characters from the end\n- *clip-start* - remove characters from the start\n- *ellipsis* or *ellipsis-end* - replace characters from the end with an ellipsis (…)\n- *ellipsis-start* - replace characters from the start with an ellipsis (…)\n- *ellipsis-middle* - replace characters from the middle with an ellipsis (…)\n\nIf no **title** was specified, if text requires truncation, a title containing the non-truncated text will be implicitly added." + }, + "tip": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/TipPointer" + }, + { + "properties": { + "anchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The tip anchor specifies how to orient the tip box relative to its anchor position; it refers to the part of the tip box that is attached to the anchor point. For example, the *top-left* anchor places the top-left corner of tip box near the anchor position, hence placing the tip box below and to the right of the anchor position." + }, + "fontFamily": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font-family][1]; a constant; defaults to the plot’s font family, which is typically [*system-ui*][2].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-family [2]: https://drafts.csswg.org/css-fonts-4/#valdef-font-family-system-ui" + }, + "fontSize": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font size][1] in pixels; either a constant or a channel; defaults to the plot’s font size, which is typically 10. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-size" + }, + "fontStyle": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font style][1]; a constant; defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-style" + }, + "fontVariant": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font variant][1]; a constant; if the **text** channel contains numbers or dates, defaults to *tabular-nums* to facilitate comparing numbers; otherwise defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant" + }, + "fontWeight": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font weight][1]; a constant; defaults to the plot’s font weight, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight" + }, + "format": { + "additionalProperties": false, + "description": "How channel values are formatted for display. If a format is a string, it is interpreted as a (UTC) time format for temporal channels, and otherwise a number format.", + "properties": { + "ariaLabel": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fill": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fillOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fontSize": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fx": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fy": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "geometry": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "height": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "href": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "length": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "opacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "path": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "r": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "rotate": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "src": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "stroke": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeWidth": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "symbol": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "text": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "title": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "weight": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "width": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "z": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + } + }, + "type": "object" + }, + "frameAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The frame anchor specifies defaults for **x** and **y** based on the plot’s frame; it may be one of the four sides (*top*, *right*, *bottom*, *left*), one of the four corners (*top-left*, *top-right*, *bottom-right*,\n*bottom-left*), or the *middle* of the frame. For example, for tips distributed horizontally at the top of the frame:\n\n```js Plot.tip(data, {x: \"date\", frameAnchor: \"top\"}) ```" + }, + "lineHeight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line height in ems; defaults to 1. The line height affects the (typically vertical) separation between adjacent baselines of text, as well as the separation between the text and its anchor point." + }, + "lineWidth": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line width in ems (e.g., 10 for about 20 characters); defaults to infinity, disabling wrapping and clipping.\n\nIf **textOverflow** is null, lines will be wrapped at the specified length. If a line is split at a soft hyphen (\\xad), a hyphen (-) will be displayed at the end of the line. If **textOverflow** is not null, lines will be clipped according to the given strategy." + }, + "monospace": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, changes the default **fontFamily** to *monospace*, and uses simplified monospaced text metrics calculations." + }, + "pathFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The image filter for the tip’s box; defaults to a drop shadow." + }, + "pointer": { + "$ref": "#/definitions/TipPointer" + }, + "pointerSize": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The size of the tip’s pointer in pixels; defaults to 12." + }, + "preferredAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If an explicit tip anchor is not specified, an anchor is chosen automatically such that the tip fits within the plot’s frame; if the preferred anchor fits, it is chosen." + }, + "textAnchor": { + "anyOf": [ + { + "const": "start", + "type": "string" + }, + { + "const": "middle", + "type": "string" + }, + { + "const": "end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [text anchor][1] controls how text is aligned (typically horizontally) relative to its anchor point; it is one of *start*, *end*, or *middle*. If the frame anchor is *left*, *top-left*, or *bottom-left*, the default text anchor is *start*; if the frame anchor is *right*, *top-right*, or\n*bottom-right*, the default is *end*; otherwise it is *middle*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/text-anchor" + }, + "textOverflow": { + "anyOf": [ + { + "type": "null" + }, + { + "const": "clip", + "type": "string" + }, + { + "const": "ellipsis", + "type": "string" + }, + { + "const": "clip-start", + "type": "string" + }, + { + "const": "clip-end", + "type": "string" + }, + { + "const": "ellipsis-start", + "type": "string" + }, + { + "const": "ellipsis-middle", + "type": "string" + }, + { + "const": "ellipsis-end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How truncate (or wrap) lines of text longer than the given **lineWidth**; one of:\n\n- null (default) - preserve overflowing characters (and wrap if needed)\n- *clip* or *clip-end* - remove characters from the end\n- *clip-start* - remove characters from the start\n- *ellipsis* or *ellipsis-end* - replace characters from the end with an ellipsis (…)\n- *ellipsis-start* - replace characters from the start with an ellipsis (…)\n- *ellipsis-middle* - replace characters from the middle with an ellipsis (…)\n\nIf no **title** was specified, if text requires truncation, a title containing the non-truncated text will be implicitly added." + }, + "textPadding": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The padding around the text in pixels; defaults to 8." + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + } + }, + "type": "object" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to generate a tooltip for this mark, and any tip options." + }, + "title": { + "$ref": "#/definitions/ChannelValue", + "description": "The title; a channel specifying accessible, short textual descriptions as strings (possibly with newlines). If the tip option is specified, the title will be displayed with an interactive tooltip instead of using the SVG [title element][1].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/title" + }, + "type": { + "const": "textX", + "description": "The basic mark type to use to render 1D density values. Defaults to an areaX mark; lineX, dotX, and textX marks are also supported.", + "type": "string" + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel specifying the text’s anchor point, typically bound to the *y* scale." + }, + "z": { + "$ref": "#/definitions/ChannelValue", + "description": "An optional ordinal channel for grouping data into series." + } + }, + "required": [ + "data", + "mark", + "type" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "$schema": { + "description": "A [JSON schema](http://json-schema.org/) URL for this specification, such as https://uwdata.github.io/mosaic/schema/latest.json. This property enables validation and autocomplete in editors with JSON schema support.", + "format": "uri", + "type": "string" + }, + "ariaDescription": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-description][1]; a constant textual description.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-description" + }, + "ariaHidden": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-hidden][1] state; a constant indicating whether the element is exposed to an accessibility API.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-hidden" + }, + "ariaLabel": { + "$ref": "#/definitions/ChannelValue", + "description": "The [aria-label][1]; a channel specifying short textual labels representing the value in the accessibility tree.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-label" + }, + "bandwidth": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The kernel density bandwidth for smoothing, in pixels. Defaults to 20." + }, + "bins": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The number of bins over which to discretize the data prior to smoothing. Defaults to 1024." + }, + "clip": { + "anyOf": [ + { + "const": "frame", + "type": "string" + }, + { + "const": "sphere", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to clip the mark; one of:\n\n- *frame* or true - clip to the plot’s frame (inner area)\n- *sphere* - clip to the projected sphere (*e.g.*, front hemisphere)\n- null or false - do not clip\n\nThe *sphere* clip option requires a geographic projection." + }, + "config": { + "$ref": "#/definitions/Config", + "description": "Configuration options." + }, + "curve": { + "anyOf": [ + { + "$ref": "#/definitions/Curve" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The curve (interpolation) method for connecting adjacent points. One of:\n\n- *basis* - a cubic basis spline (repeating the end points)\n- *basis-open* - an open cubic basis spline\n- *basis-closed* - a closed cubic basis spline\n- *bump-x* - a Bézier curve with horizontal tangents\n- *bump-y* - a Bézier curve with vertical tangents\n- *bundle* - a straightened cubic basis spline (suitable for lines only, not areas)\n- *cardinal* - a cubic cardinal spline (with one-sided differences at the ends)\n- *cardinal-open* - an open cubic cardinal spline\n- *cardinal-closed* - an closed cubic cardinal spline\n- *catmull-rom* - a cubic Catmull–Rom spline (with one-sided differences at the ends)\n- *catmull-rom-open* - an open cubic Catmull–Rom spline\n- *catmull-rom-closed* - a closed cubic Catmull–Rom spline\n- *linear* - a piecewise linear curve (*i.e.*, straight line segments)\n- *linear-closed* - a closed piecewise linear curve (*i.e.*, straight line segments)\n- *monotone-x* - a cubic spline that preserves monotonicity in *x*\n- *monotone-y* - a cubic spline that preserves monotonicity in *y*\n- *natural* - a natural cubic spline\n- *step* - a piecewise constant function where *y* changes at the midpoint of *x*\n- *step-after* - a piecewise constant function where *y* changes after *x*\n- *step-before* - a piecewise constant function where *x* changes after *y*" + }, + "data": { + "$ref": "#/definitions/Data", + "description": "Dataset definitions." + }, + "dx": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The horizontal offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "dy": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The vertical offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "facet": { + "anyOf": [ + { + "const": "auto", + "type": "string" + }, + { + "const": "include", + "type": "string" + }, + { + "const": "exclude", + "type": "string" + }, + { + "const": "super", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to enable or disable faceting; one of:\n\n- *auto* (default) - automatically determine if this mark should be faceted\n- *include* (or true) - draw the subset of the mark’s data in the current facet\n- *exclude* - draw the subset of the mark’s data *not* in the current facet\n- *super* - draw this mark in a single frame that covers all facets\n- null (or false) - repeat this mark’s data across all facets (*i.e.*, no faceting)\n\nWhen a mark uses *super* faceting, it is not allowed to use position scales (*x*, *y*, *fx*, or *fy*); *super* faceting is intended for decorations, such as labels and legends.\n\nWhen top-level faceting is used, the default *auto* setting is equivalent to *include* when the mark data is strictly equal to the top-level facet data; otherwise it is equivalent to null. When the *include* or *exclude* facet mode is chosen, the mark data must be parallel to the top-level facet data: the data must have the same length and order. If the data are not parallel, then the wrong data may be shown in each facet. The default\n*auto* therefore requires strict equality (`===`) for safety, and using the facet data as mark data is recommended when using the *exclude* facet mode. (To construct parallel data safely, consider using [*array*.map][1] on the facet data.)\n\nWhen mark-level faceting is used, the default *auto* setting is equivalent to *include*: the mark will be faceted if either the **fx** or **fy** channel option (or both) is specified. The null or false option will disable faceting, while *exclude* draws the subset of the mark’s data *not* in the current facet.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map" + }, + "facetAnchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "right", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "const": "left", + "type": "string" + }, + { + "const": "top-left", + "type": "string" + }, + { + "const": "top-right", + "type": "string" + }, + { + "const": "bottom-left", + "type": "string" + }, + { + "const": "bottom-right", + "type": "string" + }, + { + "const": "top-empty", + "type": "string" + }, + { + "const": "right-empty", + "type": "string" + }, + { + "const": "bottom-empty", + "type": "string" + }, + { + "const": "left-empty", + "type": "string" + }, + { + "const": "empty", + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to place the mark with respect to facets; one of:\n\n- null (default for most marks) - display the mark in each non-empty facet\n- *top*, *right*, *bottom*, or *left* - display the mark only in facets on the given side\n- *top-empty*, *right-empty*, *bottom-empty*, or *left-empty* (default for axis marks) - display the mark only in facets that have empty space on the given side: either the margin, or an empty facet\n- *empty* - display the mark in empty facets only" + }, + "fill": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill" + }, + "fillOpacity": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill-opacity][1]; a constant number between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill-opacity" + }, + "filter": { + "$ref": "#/definitions/ChannelValue", + "description": "Applies a transform to filter the mark’s index according to the given channel values; only truthy values are retained.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "fx": { + "$ref": "#/definitions/ChannelValue", + "description": "The horizontal facet position channel, for mark-level faceting, bound to the *fx* scale." + }, + "fy": { + "$ref": "#/definitions/ChannelValue", + "description": "The vertical facet position channel, for mark-level faceting, bound to the\n*fy* scale." + }, + "href": { + "$ref": "#/definitions/ChannelValue", + "description": "The [href][1]; a channel specifying URLs for clickable links. May be used in conjunction with the **target** option to open links in another window.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/href" + }, + "imageFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A CSS [filter][1]; a constant string used to adjust the rendering of images, such as *blur(5px)*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/filter" + }, + "margin": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four mark margins: **marginTop**,\n**marginRight**, **marginBottom**, and **marginLeft**; typically defaults to 0, except for axis marks." + }, + "marginBottom": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s bottom margin; the minimum distance in pixels between the bottom edges of the inner and outer plot area." + }, + "marginLeft": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s left margin; the minimum distance in pixels between the left edges of the inner and outer plot area." + }, + "marginRight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s right margin; the minimum distance in pixels between the right edges of the mark’s inner and outer plot area." + }, + "marginTop": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s top margin; the minimum distance in pixels between the top edges of the inner and outer plot area." + }, + "mark": { + "const": "densityY", + "description": "A densityY mark that visualizes smoothed point cloud densities along the\n**y** dimension. The mark bins the data, counts the number of records that fall into each bin, smooths the resulting counts, and then plots the smoothed distribution, by default using an areaY mark.\n\nSet the *type* property to use a different base mark type.", + "type": "string" + }, + "meta": { + "$ref": "#/definitions/Meta", + "description": "Specification metadata." + }, + "mixBlendMode": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [mix-blend-mode][1]; a constant string specifying how to blend content such as *multiply*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode" + }, + "offset": { + "anyOf": [ + { + "$ref": "#/definitions/StackOffset" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "After stacking, an optional **offset** can be applied to translate and scale stacks, say to produce a streamgraph; defaults to null for a zero baseline (**y** = 0 for stackY, and **x** = 0 for stackX). If the *wiggle* offset is used, the default **order** changes to *inside-out*." + }, + "opacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally. For faster rendering, prefer the **strokeOpacity** or **fillOpacity** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/opacity" + }, + "order": { + "anyOf": [ + { + "$ref": "#/definitions/StackOrder" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The order in which stacks are layered; one of:\n\n- null (default) for input order\n- a named stack order method such as *inside-out* or *sum*\n- a field name, for natural order of the corresponding values\n- a function of data, for natural order of the corresponding values\n- an array of explicit **z** values in the desired order\n\nIf the *wiggle* **offset** is used, as for a streamgraph, the default changes to *inside-out*." + }, + "paintOrder": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [paint-order][1]; a constant string specifying the order in which the\n**fill**, **stroke**, and any markers are drawn; defaults to *normal*, which draws the fill, then stroke, then markers; defaults to *stroke* for the text mark to create a “halo” around text to improve legibility.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/paint-order" + }, + "params": { + "$ref": "#/definitions/Params", + "description": "Param and Selection definitions." + }, + "plotDefaults": { + "$ref": "#/definitions/PlotAttributes", + "description": "A default set of attributes to apply to all plot components." + }, + "pointerEvents": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [pointer-events][1] property; a constant string such as *none*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/pointer-events" + }, + "reverse": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Applies a transform to reverse the order of the mark’s index, say for reverse input order." + }, + "select": { + "$ref": "#/definitions/SelectFilter", + "description": "Applies a filter transform after data is loaded to highlight selected values only. For example, `first` and `last` select the first or last values of series only (using the *z* channel to separate series). Meanwhile, `nearestX` and `nearestY` select the point nearest to the pointer along the *x* or *y* channel dimension. Unlike Mosaic selections, a mark level *select* is internal to the mark only, and does not populate a param or selection value to be shared across clients.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "shapeRendering": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [shape-rendering][1]; a constant string such as *crispEdges*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/shape-rendering" + }, + "sort": { + "anyOf": [ + { + "$ref": "#/definitions/SortOrder" + }, + { + "$ref": "#/definitions/ChannelDomainSort" + } + ], + "description": "Either applies a transform to sort the mark’s index by the specified channel values, or imputes ordinal scale domains from this mark’s channels.\n\nWhen imputing ordinal scale domains from channel values, the **sort** option is an object whose keys are ordinal scale names such as *x* or *fx*, and whose values are channel names such as *y*, *y1*, or *y2*. For example, to impute the *y* scale’s domain from the associated *x* channel values in ascending order:\n\n```js sort: {y: \"x\"} ```\n\nFor different sort options for different scales, replace the channel name with a *value* object and per-scale options:\n\n```js sort: {y: {value: \"-x\"}} ```\n\nWhen sorting the mark’s index, the **sort** option is instead one of:\n\n- a channel value definition for sorting given values in ascending order\n- a {value, order} object for sorting given values\n- a {channel, order} object for sorting the named channel’s values" + }, + "stroke": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke" + }, + "strokeDasharray": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dasharray][1]; a constant number indicating the length in pixels of alternating dashes and gaps, or a constant string of numbers separated by spaces or commas (_e.g._, *10 2* for dashes of 10 pixels separated by gaps of 2 pixels), or *none* (the default) for no dashing\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dasharray" + }, + "strokeDashoffset": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dashoffset][1]; a constant indicating the offset in pixels of the first dash along the stroke; defaults to zero.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dashoffset" + }, + "strokeLinecap": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linecap][1]; a constant specifying how to cap stroked paths, such as *butt*, *round*, or *square*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linecap" + }, + "strokeLinejoin": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linejoin][1]; a constant specifying how to join stroked paths, such as *bevel*, *miter*, *miter-clip*, or *round*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linejoin" + }, + "strokeMiterlimit": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-miterlimit][1]; a constant number specifying how to limit the length of *miter* joins on stroked paths.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-miterlimit" + }, + "strokeOpacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-opacity" + }, + "strokeWidth": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-width][1]; a constant number in pixels, or a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-width" + }, + "target": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [target][1]; a constant string specifying the target window (_e.g._,\n*_blank*) for clickable links; used in conjunction with the **href** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/target" + }, + "tension": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The tension option only has an effect on bundle, cardinal and Catmull–Rom splines (*bundle*, *cardinal*, *cardinal-open*, *cardinal-closed*,\n*catmull-rom*, *catmull-rom-open*, and *catmull-rom-closed*). For bundle splines, it corresponds to [beta][1]; for cardinal splines, [tension][2]; for Catmull–Rom splines, [alpha][3].\n\n[1]: https://d3js.org/d3-shape/curve#curveBundle_beta [2]: https://d3js.org/d3-shape/curve#curveCardinal_tension [3]: https://d3js.org/d3-shape/curve#curveCatmullRom_alpha" + }, + "tip": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/TipPointer" + }, + { + "properties": { + "anchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The tip anchor specifies how to orient the tip box relative to its anchor position; it refers to the part of the tip box that is attached to the anchor point. For example, the *top-left* anchor places the top-left corner of tip box near the anchor position, hence placing the tip box below and to the right of the anchor position." + }, + "fontFamily": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font-family][1]; a constant; defaults to the plot’s font family, which is typically [*system-ui*][2].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-family [2]: https://drafts.csswg.org/css-fonts-4/#valdef-font-family-system-ui" + }, + "fontSize": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font size][1] in pixels; either a constant or a channel; defaults to the plot’s font size, which is typically 10. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-size" + }, + "fontStyle": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font style][1]; a constant; defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-style" + }, + "fontVariant": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font variant][1]; a constant; if the **text** channel contains numbers or dates, defaults to *tabular-nums* to facilitate comparing numbers; otherwise defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant" + }, + "fontWeight": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font weight][1]; a constant; defaults to the plot’s font weight, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight" + }, + "format": { + "additionalProperties": false, + "description": "How channel values are formatted for display. If a format is a string, it is interpreted as a (UTC) time format for temporal channels, and otherwise a number format.", + "properties": { + "ariaLabel": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fill": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fillOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fontSize": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fx": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fy": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "geometry": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "height": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "href": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "length": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "opacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "path": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "r": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "rotate": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "src": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "stroke": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeWidth": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "symbol": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "text": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "title": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "weight": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "width": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "z": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + } + }, + "type": "object" + }, + "frameAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The frame anchor specifies defaults for **x** and **y** based on the plot’s frame; it may be one of the four sides (*top*, *right*, *bottom*, *left*), one of the four corners (*top-left*, *top-right*, *bottom-right*,\n*bottom-left*), or the *middle* of the frame. For example, for tips distributed horizontally at the top of the frame:\n\n```js Plot.tip(data, {x: \"date\", frameAnchor: \"top\"}) ```" + }, + "lineHeight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line height in ems; defaults to 1. The line height affects the (typically vertical) separation between adjacent baselines of text, as well as the separation between the text and its anchor point." + }, + "lineWidth": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line width in ems (e.g., 10 for about 20 characters); defaults to infinity, disabling wrapping and clipping.\n\nIf **textOverflow** is null, lines will be wrapped at the specified length. If a line is split at a soft hyphen (\\xad), a hyphen (-) will be displayed at the end of the line. If **textOverflow** is not null, lines will be clipped according to the given strategy." + }, + "monospace": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, changes the default **fontFamily** to *monospace*, and uses simplified monospaced text metrics calculations." + }, + "pathFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The image filter for the tip’s box; defaults to a drop shadow." + }, + "pointer": { + "$ref": "#/definitions/TipPointer" + }, + "pointerSize": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The size of the tip’s pointer in pixels; defaults to 12." + }, + "preferredAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If an explicit tip anchor is not specified, an anchor is chosen automatically such that the tip fits within the plot’s frame; if the preferred anchor fits, it is chosen." + }, + "textAnchor": { + "anyOf": [ + { + "const": "start", + "type": "string" + }, + { + "const": "middle", + "type": "string" + }, + { + "const": "end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [text anchor][1] controls how text is aligned (typically horizontally) relative to its anchor point; it is one of *start*, *end*, or *middle*. If the frame anchor is *left*, *top-left*, or *bottom-left*, the default text anchor is *start*; if the frame anchor is *right*, *top-right*, or\n*bottom-right*, the default is *end*; otherwise it is *middle*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/text-anchor" + }, + "textOverflow": { + "anyOf": [ + { + "type": "null" + }, + { + "const": "clip", + "type": "string" + }, + { + "const": "ellipsis", + "type": "string" + }, + { + "const": "clip-start", + "type": "string" + }, + { + "const": "clip-end", + "type": "string" + }, + { + "const": "ellipsis-start", + "type": "string" + }, + { + "const": "ellipsis-middle", + "type": "string" + }, + { + "const": "ellipsis-end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How truncate (or wrap) lines of text longer than the given **lineWidth**; one of:\n\n- null (default) - preserve overflowing characters (and wrap if needed)\n- *clip* or *clip-end* - remove characters from the end\n- *clip-start* - remove characters from the start\n- *ellipsis* or *ellipsis-end* - replace characters from the end with an ellipsis (…)\n- *ellipsis-start* - replace characters from the start with an ellipsis (…)\n- *ellipsis-middle* - replace characters from the middle with an ellipsis (…)\n\nIf no **title** was specified, if text requires truncation, a title containing the non-truncated text will be implicitly added." + }, + "textPadding": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The padding around the text in pixels; defaults to 8." + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + } + }, + "type": "object" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to generate a tooltip for this mark, and any tip options." + }, + "title": { + "$ref": "#/definitions/ChannelValue", + "description": "The title; a channel specifying accessible, short textual descriptions as strings (possibly with newlines). If the tip option is specified, the title will be displayed with an interactive tooltip instead of using the SVG [title element][1].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/title" + }, + "type": { + "const": "areaY", + "description": "The basic mark type to use to render 1D density values. Defaults to an areaY mark; lineY, dot, and text marks are also supported.", + "type": "string" + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel, typically bound to the *x* scale; defaults to the zero-based index of the data [0, 1, 2, …]." + }, + "z": { + "$ref": "#/definitions/ChannelValue", + "description": "An optional ordinal channel for grouping data into (possibly stacked) series to be drawn as separate areas; defaults to **fill** if a channel, or\n**stroke** if a channel." + } + }, + "required": [ + "data", + "mark" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "$schema": { + "description": "A [JSON schema](http://json-schema.org/) URL for this specification, such as https://uwdata.github.io/mosaic/schema/latest.json. This property enables validation and autocomplete in editors with JSON schema support.", + "format": "uri", + "type": "string" + }, + "ariaDescription": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-description][1]; a constant textual description.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-description" + }, + "ariaHidden": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-hidden][1] state; a constant indicating whether the element is exposed to an accessibility API.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-hidden" + }, + "ariaLabel": { + "$ref": "#/definitions/ChannelValue", + "description": "The [aria-label][1]; a channel specifying short textual labels representing the value in the accessibility tree.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-label" + }, + "bandwidth": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The kernel density bandwidth for smoothing, in pixels. Defaults to 20." + }, + "bins": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The number of bins over which to discretize the data prior to smoothing. Defaults to 1024." + }, + "clip": { + "anyOf": [ + { + "const": "frame", + "type": "string" + }, + { + "const": "sphere", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to clip the mark; one of:\n\n- *frame* or true - clip to the plot’s frame (inner area)\n- *sphere* - clip to the projected sphere (*e.g.*, front hemisphere)\n- null or false - do not clip\n\nThe *sphere* clip option requires a geographic projection." + }, + "config": { + "$ref": "#/definitions/Config", + "description": "Configuration options." + }, + "curve": { + "anyOf": [ + { + "$ref": "#/definitions/Curve" + }, + { + "const": "auto", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The curve (interpolation) method for connecting adjacent points. One of:\n\n- *basis* - a cubic basis spline (repeating the end points)\n- *basis-open* - an open cubic basis spline\n- *basis-closed* - a closed cubic basis spline\n- *bump-x* - a Bézier curve with horizontal tangents\n- *bump-y* - a Bézier curve with vertical tangents\n- *bundle* - a straightened cubic basis spline (suitable for lines only, not areas)\n- *cardinal* - a cubic cardinal spline (with one-sided differences at the ends)\n- *cardinal-open* - an open cubic cardinal spline\n- *cardinal-closed* - an closed cubic cardinal spline\n- *catmull-rom* - a cubic Catmull–Rom spline (with one-sided differences at the ends)\n- *catmull-rom-open* - an open cubic Catmull–Rom spline\n- *catmull-rom-closed* - a closed cubic Catmull–Rom spline\n- *linear* - a piecewise linear curve (*i.e.*, straight line segments)\n- *linear-closed* - a closed piecewise linear curve (*i.e.*, straight line segments)\n- *monotone-x* - a cubic spline that preserves monotonicity in *x*\n- *monotone-y* - a cubic spline that preserves monotonicity in *y*\n- *natural* - a natural cubic spline\n- *step* - a piecewise constant function where *y* changes at the midpoint of *x*\n- *step-after* - a piecewise constant function where *y* changes after *x*\n- *step-before* - a piecewise constant function where *x* changes after *y*\n- *auto* (default) - like *linear*, but use the (possibly spherical) projection, if any\n\nThe *auto* curve is typically used in conjunction with a spherical projection to interpolate along geodesics." + }, + "data": { + "$ref": "#/definitions/Data", + "description": "Dataset definitions." + }, + "dx": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The horizontal offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "dy": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The vertical offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "facet": { + "anyOf": [ + { + "const": "auto", + "type": "string" + }, + { + "const": "include", + "type": "string" + }, + { + "const": "exclude", + "type": "string" + }, + { + "const": "super", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to enable or disable faceting; one of:\n\n- *auto* (default) - automatically determine if this mark should be faceted\n- *include* (or true) - draw the subset of the mark’s data in the current facet\n- *exclude* - draw the subset of the mark’s data *not* in the current facet\n- *super* - draw this mark in a single frame that covers all facets\n- null (or false) - repeat this mark’s data across all facets (*i.e.*, no faceting)\n\nWhen a mark uses *super* faceting, it is not allowed to use position scales (*x*, *y*, *fx*, or *fy*); *super* faceting is intended for decorations, such as labels and legends.\n\nWhen top-level faceting is used, the default *auto* setting is equivalent to *include* when the mark data is strictly equal to the top-level facet data; otherwise it is equivalent to null. When the *include* or *exclude* facet mode is chosen, the mark data must be parallel to the top-level facet data: the data must have the same length and order. If the data are not parallel, then the wrong data may be shown in each facet. The default\n*auto* therefore requires strict equality (`===`) for safety, and using the facet data as mark data is recommended when using the *exclude* facet mode. (To construct parallel data safely, consider using [*array*.map][1] on the facet data.)\n\nWhen mark-level faceting is used, the default *auto* setting is equivalent to *include*: the mark will be faceted if either the **fx** or **fy** channel option (or both) is specified. The null or false option will disable faceting, while *exclude* draws the subset of the mark’s data *not* in the current facet.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map" + }, + "facetAnchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "right", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "const": "left", + "type": "string" + }, + { + "const": "top-left", + "type": "string" + }, + { + "const": "top-right", + "type": "string" + }, + { + "const": "bottom-left", + "type": "string" + }, + { + "const": "bottom-right", + "type": "string" + }, + { + "const": "top-empty", + "type": "string" + }, + { + "const": "right-empty", + "type": "string" + }, + { + "const": "bottom-empty", + "type": "string" + }, + { + "const": "left-empty", + "type": "string" + }, + { + "const": "empty", + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to place the mark with respect to facets; one of:\n\n- null (default for most marks) - display the mark in each non-empty facet\n- *top*, *right*, *bottom*, or *left* - display the mark only in facets on the given side\n- *top-empty*, *right-empty*, *bottom-empty*, or *left-empty* (default for axis marks) - display the mark only in facets that have empty space on the given side: either the margin, or an empty facet\n- *empty* - display the mark in empty facets only" + }, + "fill": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill" + }, + "fillOpacity": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill-opacity][1]; a constant number between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill-opacity" + }, + "filter": { + "$ref": "#/definitions/ChannelValue", + "description": "Applies a transform to filter the mark’s index according to the given channel values; only truthy values are retained.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "fx": { + "$ref": "#/definitions/ChannelValue", + "description": "The horizontal facet position channel, for mark-level faceting, bound to the *fx* scale." + }, + "fy": { + "$ref": "#/definitions/ChannelValue", + "description": "The vertical facet position channel, for mark-level faceting, bound to the\n*fy* scale." + }, + "href": { + "$ref": "#/definitions/ChannelValue", + "description": "The [href][1]; a channel specifying URLs for clickable links. May be used in conjunction with the **target** option to open links in another window.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/href" + }, + "imageFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A CSS [filter][1]; a constant string used to adjust the rendering of images, such as *blur(5px)*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/filter" + }, + "margin": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four mark margins: **marginTop**,\n**marginRight**, **marginBottom**, and **marginLeft**; typically defaults to 0, except for axis marks." + }, + "marginBottom": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s bottom margin; the minimum distance in pixels between the bottom edges of the inner and outer plot area." + }, + "marginLeft": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s left margin; the minimum distance in pixels between the left edges of the inner and outer plot area." + }, + "marginRight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s right margin; the minimum distance in pixels between the right edges of the mark’s inner and outer plot area." + }, + "marginTop": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s top margin; the minimum distance in pixels between the top edges of the inner and outer plot area." + }, + "mark": { + "const": "densityY", + "description": "A densityY mark that visualizes smoothed point cloud densities along the\n**y** dimension. The mark bins the data, counts the number of records that fall into each bin, smooths the resulting counts, and then plots the smoothed distribution, by default using an areaY mark.\n\nSet the *type* property to use a different base mark type.", + "type": "string" + }, + "marker": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for markerStart, markerMid, and markerEnd; one of:\n\n- a marker name such as *arrow* or *circle*\n- *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*" + }, + "markerEnd": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The marker for the ending point of a line segment; one of:\n\n- a marker name such as *arrow* or *circle*\n* *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*" + }, + "markerMid": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The marker for any middle (interior) points of a line segment. If the line segment only has a start and end point, this option has no effect. One of:\n\n- a marker name such as *arrow* or *circle*\n* *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*\n* a function - a custom marker function; see below" + }, + "markerStart": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The marker for the starting point of a line segment; one of:\n\n- a marker name such as *arrow* or *circle*\n* *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*" + }, + "meta": { + "$ref": "#/definitions/Meta", + "description": "Specification metadata." + }, + "mixBlendMode": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [mix-blend-mode][1]; a constant string specifying how to blend content such as *multiply*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode" + }, + "opacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally. For faster rendering, prefer the **strokeOpacity** or **fillOpacity** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/opacity" + }, + "paintOrder": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [paint-order][1]; a constant string specifying the order in which the\n**fill**, **stroke**, and any markers are drawn; defaults to *normal*, which draws the fill, then stroke, then markers; defaults to *stroke* for the text mark to create a “halo” around text to improve legibility.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/paint-order" + }, + "params": { + "$ref": "#/definitions/Params", + "description": "Param and Selection definitions." + }, + "plotDefaults": { + "$ref": "#/definitions/PlotAttributes", + "description": "A default set of attributes to apply to all plot components." + }, + "pointerEvents": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [pointer-events][1] property; a constant string such as *none*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/pointer-events" + }, + "reverse": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Applies a transform to reverse the order of the mark’s index, say for reverse input order." + }, + "select": { + "$ref": "#/definitions/SelectFilter", + "description": "Applies a filter transform after data is loaded to highlight selected values only. For example, `first` and `last` select the first or last values of series only (using the *z* channel to separate series). Meanwhile, `nearestX` and `nearestY` select the point nearest to the pointer along the *x* or *y* channel dimension. Unlike Mosaic selections, a mark level *select* is internal to the mark only, and does not populate a param or selection value to be shared across clients.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "shapeRendering": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [shape-rendering][1]; a constant string such as *crispEdges*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/shape-rendering" + }, + "sort": { + "anyOf": [ + { + "$ref": "#/definitions/SortOrder" + }, + { + "$ref": "#/definitions/ChannelDomainSort" + } + ], + "description": "Either applies a transform to sort the mark’s index by the specified channel values, or imputes ordinal scale domains from this mark’s channels.\n\nWhen imputing ordinal scale domains from channel values, the **sort** option is an object whose keys are ordinal scale names such as *x* or *fx*, and whose values are channel names such as *y*, *y1*, or *y2*. For example, to impute the *y* scale’s domain from the associated *x* channel values in ascending order:\n\n```js sort: {y: \"x\"} ```\n\nFor different sort options for different scales, replace the channel name with a *value* object and per-scale options:\n\n```js sort: {y: {value: \"-x\"}} ```\n\nWhen sorting the mark’s index, the **sort** option is instead one of:\n\n- a channel value definition for sorting given values in ascending order\n- a {value, order} object for sorting given values\n- a {channel, order} object for sorting the named channel’s values" + }, + "stroke": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke" + }, + "strokeDasharray": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dasharray][1]; a constant number indicating the length in pixels of alternating dashes and gaps, or a constant string of numbers separated by spaces or commas (_e.g._, *10 2* for dashes of 10 pixels separated by gaps of 2 pixels), or *none* (the default) for no dashing\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dasharray" + }, + "strokeDashoffset": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dashoffset][1]; a constant indicating the offset in pixels of the first dash along the stroke; defaults to zero.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dashoffset" + }, + "strokeLinecap": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linecap][1]; a constant specifying how to cap stroked paths, such as *butt*, *round*, or *square*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linecap" + }, + "strokeLinejoin": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linejoin][1]; a constant specifying how to join stroked paths, such as *bevel*, *miter*, *miter-clip*, or *round*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linejoin" + }, + "strokeMiterlimit": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-miterlimit][1]; a constant number specifying how to limit the length of *miter* joins on stroked paths.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-miterlimit" + }, + "strokeOpacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-opacity" + }, + "strokeWidth": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-width][1]; a constant number in pixels, or a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-width" + }, + "target": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [target][1]; a constant string specifying the target window (_e.g._,\n*_blank*) for clickable links; used in conjunction with the **href** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/target" + }, + "tension": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The tension option only has an effect on bundle, cardinal and Catmull–Rom splines (*bundle*, *cardinal*, *cardinal-open*, *cardinal-closed*,\n*catmull-rom*, *catmull-rom-open*, and *catmull-rom-closed*). For bundle splines, it corresponds to [beta][1]; for cardinal splines, [tension][2]; for Catmull–Rom splines, [alpha][3].\n\n[1]: https://d3js.org/d3-shape/curve#curveBundle_beta [2]: https://d3js.org/d3-shape/curve#curveCardinal_tension [3]: https://d3js.org/d3-shape/curve#curveCatmullRom_alpha" + }, + "tip": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/TipPointer" + }, + { + "properties": { + "anchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The tip anchor specifies how to orient the tip box relative to its anchor position; it refers to the part of the tip box that is attached to the anchor point. For example, the *top-left* anchor places the top-left corner of tip box near the anchor position, hence placing the tip box below and to the right of the anchor position." + }, + "fontFamily": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font-family][1]; a constant; defaults to the plot’s font family, which is typically [*system-ui*][2].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-family [2]: https://drafts.csswg.org/css-fonts-4/#valdef-font-family-system-ui" + }, + "fontSize": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font size][1] in pixels; either a constant or a channel; defaults to the plot’s font size, which is typically 10. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-size" + }, + "fontStyle": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font style][1]; a constant; defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-style" + }, + "fontVariant": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font variant][1]; a constant; if the **text** channel contains numbers or dates, defaults to *tabular-nums* to facilitate comparing numbers; otherwise defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant" + }, + "fontWeight": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font weight][1]; a constant; defaults to the plot’s font weight, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight" + }, + "format": { + "additionalProperties": false, + "description": "How channel values are formatted for display. If a format is a string, it is interpreted as a (UTC) time format for temporal channels, and otherwise a number format.", + "properties": { + "ariaLabel": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fill": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fillOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fontSize": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fx": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fy": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "geometry": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "height": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "href": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "length": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "opacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "path": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "r": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "rotate": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "src": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "stroke": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeWidth": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "symbol": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "text": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "title": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "weight": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "width": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "z": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + } + }, + "type": "object" + }, + "frameAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The frame anchor specifies defaults for **x** and **y** based on the plot’s frame; it may be one of the four sides (*top*, *right*, *bottom*, *left*), one of the four corners (*top-left*, *top-right*, *bottom-right*,\n*bottom-left*), or the *middle* of the frame. For example, for tips distributed horizontally at the top of the frame:\n\n```js Plot.tip(data, {x: \"date\", frameAnchor: \"top\"}) ```" + }, + "lineHeight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line height in ems; defaults to 1. The line height affects the (typically vertical) separation between adjacent baselines of text, as well as the separation between the text and its anchor point." + }, + "lineWidth": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line width in ems (e.g., 10 for about 20 characters); defaults to infinity, disabling wrapping and clipping.\n\nIf **textOverflow** is null, lines will be wrapped at the specified length. If a line is split at a soft hyphen (\\xad), a hyphen (-) will be displayed at the end of the line. If **textOverflow** is not null, lines will be clipped according to the given strategy." + }, + "monospace": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, changes the default **fontFamily** to *monospace*, and uses simplified monospaced text metrics calculations." + }, + "pathFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The image filter for the tip’s box; defaults to a drop shadow." + }, + "pointer": { + "$ref": "#/definitions/TipPointer" + }, + "pointerSize": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The size of the tip’s pointer in pixels; defaults to 12." + }, + "preferredAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If an explicit tip anchor is not specified, an anchor is chosen automatically such that the tip fits within the plot’s frame; if the preferred anchor fits, it is chosen." + }, + "textAnchor": { + "anyOf": [ + { + "const": "start", + "type": "string" + }, + { + "const": "middle", + "type": "string" + }, + { + "const": "end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [text anchor][1] controls how text is aligned (typically horizontally) relative to its anchor point; it is one of *start*, *end*, or *middle*. If the frame anchor is *left*, *top-left*, or *bottom-left*, the default text anchor is *start*; if the frame anchor is *right*, *top-right*, or\n*bottom-right*, the default is *end*; otherwise it is *middle*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/text-anchor" + }, + "textOverflow": { + "anyOf": [ + { + "type": "null" + }, + { + "const": "clip", + "type": "string" + }, + { + "const": "ellipsis", + "type": "string" + }, + { + "const": "clip-start", + "type": "string" + }, + { + "const": "clip-end", + "type": "string" + }, + { + "const": "ellipsis-start", + "type": "string" + }, + { + "const": "ellipsis-middle", + "type": "string" + }, + { + "const": "ellipsis-end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How truncate (or wrap) lines of text longer than the given **lineWidth**; one of:\n\n- null (default) - preserve overflowing characters (and wrap if needed)\n- *clip* or *clip-end* - remove characters from the end\n- *clip-start* - remove characters from the start\n- *ellipsis* or *ellipsis-end* - replace characters from the end with an ellipsis (…)\n- *ellipsis-start* - replace characters from the start with an ellipsis (…)\n- *ellipsis-middle* - replace characters from the middle with an ellipsis (…)\n\nIf no **title** was specified, if text requires truncation, a title containing the non-truncated text will be implicitly added." + }, + "textPadding": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The padding around the text in pixels; defaults to 8." + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + } + }, + "type": "object" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to generate a tooltip for this mark, and any tip options." + }, + "title": { + "$ref": "#/definitions/ChannelValue", + "description": "The title; a channel specifying accessible, short textual descriptions as strings (possibly with newlines). If the tip option is specified, the title will be displayed with an interactive tooltip instead of using the SVG [title element][1].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/title" + }, + "type": { + "const": "lineY", + "description": "The basic mark type to use to render 1D density values. Defaults to an areaY mark; lineY, dot, and text marks are also supported.", + "type": "string" + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel, typically bound to the *x* scale; defaults to the zero-based index of the data [0, 1, 2, …]." + }, + "z": { + "$ref": "#/definitions/ChannelValue", + "description": "An optional ordinal channel for grouping data into (possibly stacked) series to be drawn as separate lines. If not specified, it defaults to\n**fill** if a channel, or **stroke** if a channel." + } + }, + "required": [ + "data", + "mark", + "type" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "$schema": { + "description": "A [JSON schema](http://json-schema.org/) URL for this specification, such as https://uwdata.github.io/mosaic/schema/latest.json. This property enables validation and autocomplete in editors with JSON schema support.", + "format": "uri", + "type": "string" + }, + "ariaDescription": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-description][1]; a constant textual description.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-description" + }, + "ariaHidden": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-hidden][1] state; a constant indicating whether the element is exposed to an accessibility API.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-hidden" + }, + "ariaLabel": { + "$ref": "#/definitions/ChannelValue", + "description": "The [aria-label][1]; a channel specifying short textual labels representing the value in the accessibility tree.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-label" + }, + "bandwidth": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The kernel density bandwidth for smoothing, in pixels. Defaults to 20." + }, + "bins": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The number of bins over which to discretize the data prior to smoothing. Defaults to 1024." + }, + "clip": { + "anyOf": [ + { + "const": "frame", + "type": "string" + }, + { + "const": "sphere", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to clip the mark; one of:\n\n- *frame* or true - clip to the plot’s frame (inner area)\n- *sphere* - clip to the projected sphere (*e.g.*, front hemisphere)\n- null or false - do not clip\n\nThe *sphere* clip option requires a geographic projection." + }, + "config": { + "$ref": "#/definitions/Config", + "description": "Configuration options." + }, + "data": { + "$ref": "#/definitions/Data", + "description": "Dataset definitions." + }, + "dx": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The horizontal offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "dy": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The vertical offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "facet": { + "anyOf": [ + { + "const": "auto", + "type": "string" + }, + { + "const": "include", + "type": "string" + }, + { + "const": "exclude", + "type": "string" + }, + { + "const": "super", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to enable or disable faceting; one of:\n\n- *auto* (default) - automatically determine if this mark should be faceted\n- *include* (or true) - draw the subset of the mark’s data in the current facet\n- *exclude* - draw the subset of the mark’s data *not* in the current facet\n- *super* - draw this mark in a single frame that covers all facets\n- null (or false) - repeat this mark’s data across all facets (*i.e.*, no faceting)\n\nWhen a mark uses *super* faceting, it is not allowed to use position scales (*x*, *y*, *fx*, or *fy*); *super* faceting is intended for decorations, such as labels and legends.\n\nWhen top-level faceting is used, the default *auto* setting is equivalent to *include* when the mark data is strictly equal to the top-level facet data; otherwise it is equivalent to null. When the *include* or *exclude* facet mode is chosen, the mark data must be parallel to the top-level facet data: the data must have the same length and order. If the data are not parallel, then the wrong data may be shown in each facet. The default\n*auto* therefore requires strict equality (`===`) for safety, and using the facet data as mark data is recommended when using the *exclude* facet mode. (To construct parallel data safely, consider using [*array*.map][1] on the facet data.)\n\nWhen mark-level faceting is used, the default *auto* setting is equivalent to *include*: the mark will be faceted if either the **fx** or **fy** channel option (or both) is specified. The null or false option will disable faceting, while *exclude* draws the subset of the mark’s data *not* in the current facet.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map" + }, + "facetAnchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "right", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "const": "left", + "type": "string" + }, + { + "const": "top-left", + "type": "string" + }, + { + "const": "top-right", + "type": "string" + }, + { + "const": "bottom-left", + "type": "string" + }, + { + "const": "bottom-right", + "type": "string" + }, + { + "const": "top-empty", + "type": "string" + }, + { + "const": "right-empty", + "type": "string" + }, + { + "const": "bottom-empty", + "type": "string" + }, + { + "const": "left-empty", + "type": "string" + }, + { + "const": "empty", + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to place the mark with respect to facets; one of:\n\n- null (default for most marks) - display the mark in each non-empty facet\n- *top*, *right*, *bottom*, or *left* - display the mark only in facets on the given side\n- *top-empty*, *right-empty*, *bottom-empty*, or *left-empty* (default for axis marks) - display the mark only in facets that have empty space on the given side: either the margin, or an empty facet\n- *empty* - display the mark in empty facets only" + }, + "fill": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill" + }, + "fillOpacity": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill-opacity][1]; a constant number between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill-opacity" + }, + "filter": { + "$ref": "#/definitions/ChannelValue", + "description": "Applies a transform to filter the mark’s index according to the given channel values; only truthy values are retained.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "frameAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The frame anchor specifies defaults for **x** and **y** based on the plot’s frame; it may be one of the four sides (*top*, *right*, *bottom*, *left*), one of the four corners (*top-left*, *top-right*, *bottom-right*,\n*bottom-left*), or the *middle* of the frame. For example, for dots distributed horizontally at the top of the frame:\n\n```js Plot.dot(data, {x: \"date\", frameAnchor: \"top\"}) ```" + }, + "fx": { + "$ref": "#/definitions/ChannelValue", + "description": "The horizontal facet position channel, for mark-level faceting, bound to the *fx* scale." + }, + "fy": { + "$ref": "#/definitions/ChannelValue", + "description": "The vertical facet position channel, for mark-level faceting, bound to the\n*fy* scale." + }, + "href": { + "$ref": "#/definitions/ChannelValue", + "description": "The [href][1]; a channel specifying URLs for clickable links. May be used in conjunction with the **target** option to open links in another window.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/href" + }, + "imageFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A CSS [filter][1]; a constant string used to adjust the rendering of images, such as *blur(5px)*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/filter" + }, + "margin": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four mark margins: **marginTop**,\n**marginRight**, **marginBottom**, and **marginLeft**; typically defaults to 0, except for axis marks." + }, + "marginBottom": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s bottom margin; the minimum distance in pixels between the bottom edges of the inner and outer plot area." + }, + "marginLeft": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s left margin; the minimum distance in pixels between the left edges of the inner and outer plot area." + }, + "marginRight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s right margin; the minimum distance in pixels between the right edges of the mark’s inner and outer plot area." + }, + "marginTop": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s top margin; the minimum distance in pixels between the top edges of the inner and outer plot area." + }, + "mark": { + "const": "densityY", + "description": "A densityY mark that visualizes smoothed point cloud densities along the\n**y** dimension. The mark bins the data, counts the number of records that fall into each bin, smooths the resulting counts, and then plots the smoothed distribution, by default using an areaY mark.\n\nSet the *type* property to use a different base mark type.", + "type": "string" + }, + "meta": { + "$ref": "#/definitions/Meta", + "description": "Specification metadata." + }, + "mixBlendMode": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [mix-blend-mode][1]; a constant string specifying how to blend content such as *multiply*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode" + }, + "opacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally. For faster rendering, prefer the **strokeOpacity** or **fillOpacity** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/opacity" + }, + "paintOrder": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [paint-order][1]; a constant string specifying the order in which the\n**fill**, **stroke**, and any markers are drawn; defaults to *normal*, which draws the fill, then stroke, then markers; defaults to *stroke* for the text mark to create a “halo” around text to improve legibility.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/paint-order" + }, + "params": { + "$ref": "#/definitions/Params", + "description": "Param and Selection definitions." + }, + "plotDefaults": { + "$ref": "#/definitions/PlotAttributes", + "description": "A default set of attributes to apply to all plot components." + }, + "pointerEvents": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [pointer-events][1] property; a constant string such as *none*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/pointer-events" + }, + "r": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The radius of dots; either a channel or constant. When a number, it is interpreted as a constant radius in pixels. Otherwise it is interpreted as a channel, typically bound to the *r* channel, which defaults to the *sqrt* type for proportional symbols. The radius defaults to 4.5 pixels when using the **symbol** channel, and otherwise 3 pixels. Dots with a nonpositive radius are not drawn." + }, + "reverse": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Applies a transform to reverse the order of the mark’s index, say for reverse input order." + }, + "rotate": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The rotation angle of dots in degrees clockwise; either a channel or a constant. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel. Defaults to 0°, pointing up." + }, + "select": { + "$ref": "#/definitions/SelectFilter", + "description": "Applies a filter transform after data is loaded to highlight selected values only. For example, `first` and `last` select the first or last values of series only (using the *z* channel to separate series). Meanwhile, `nearestX` and `nearestY` select the point nearest to the pointer along the *x* or *y* channel dimension. Unlike Mosaic selections, a mark level *select* is internal to the mark only, and does not populate a param or selection value to be shared across clients.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "shapeRendering": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [shape-rendering][1]; a constant string such as *crispEdges*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/shape-rendering" + }, + "sort": { + "anyOf": [ + { + "$ref": "#/definitions/SortOrder" + }, + { + "$ref": "#/definitions/ChannelDomainSort" + } + ], + "description": "Either applies a transform to sort the mark’s index by the specified channel values, or imputes ordinal scale domains from this mark’s channels.\n\nWhen imputing ordinal scale domains from channel values, the **sort** option is an object whose keys are ordinal scale names such as *x* or *fx*, and whose values are channel names such as *y*, *y1*, or *y2*. For example, to impute the *y* scale’s domain from the associated *x* channel values in ascending order:\n\n```js sort: {y: \"x\"} ```\n\nFor different sort options for different scales, replace the channel name with a *value* object and per-scale options:\n\n```js sort: {y: {value: \"-x\"}} ```\n\nWhen sorting the mark’s index, the **sort** option is instead one of:\n\n- a channel value definition for sorting given values in ascending order\n- a {value, order} object for sorting given values\n- a {channel, order} object for sorting the named channel’s values" + }, + "stroke": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke" + }, + "strokeDasharray": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dasharray][1]; a constant number indicating the length in pixels of alternating dashes and gaps, or a constant string of numbers separated by spaces or commas (_e.g._, *10 2* for dashes of 10 pixels separated by gaps of 2 pixels), or *none* (the default) for no dashing\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dasharray" + }, + "strokeDashoffset": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dashoffset][1]; a constant indicating the offset in pixels of the first dash along the stroke; defaults to zero.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dashoffset" + }, + "strokeLinecap": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linecap][1]; a constant specifying how to cap stroked paths, such as *butt*, *round*, or *square*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linecap" + }, + "strokeLinejoin": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linejoin][1]; a constant specifying how to join stroked paths, such as *bevel*, *miter*, *miter-clip*, or *round*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linejoin" + }, + "strokeMiterlimit": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-miterlimit][1]; a constant number specifying how to limit the length of *miter* joins on stroked paths.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-miterlimit" + }, + "strokeOpacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-opacity" + }, + "strokeWidth": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-width][1]; a constant number in pixels, or a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-width" + }, + "symbol": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/SymbolType" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The categorical symbol; either a channel or a constant. A constant symbol can be specified by a valid symbol name such as *star*, or a symbol object (implementing the draw method); otherwise it is interpreted as a channel. Defaults to *circle* for the **dot** mark, and *hexagon* for the\n**hexagon** mark.\n\nIf the **symbol** channel’s values are all symbols, symbol names, or nullish, the channel is unscaled (values are interpreted literally); otherwise, the channel is bound to the *symbol* scale." + }, + "target": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [target][1]; a constant string specifying the target window (_e.g._,\n*_blank*) for clickable links; used in conjunction with the **href** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/target" + }, + "tip": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/TipPointer" + }, + { + "properties": { + "anchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The tip anchor specifies how to orient the tip box relative to its anchor position; it refers to the part of the tip box that is attached to the anchor point. For example, the *top-left* anchor places the top-left corner of tip box near the anchor position, hence placing the tip box below and to the right of the anchor position." + }, + "fontFamily": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font-family][1]; a constant; defaults to the plot’s font family, which is typically [*system-ui*][2].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-family [2]: https://drafts.csswg.org/css-fonts-4/#valdef-font-family-system-ui" + }, + "fontSize": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font size][1] in pixels; either a constant or a channel; defaults to the plot’s font size, which is typically 10. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-size" + }, + "fontStyle": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font style][1]; a constant; defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-style" + }, + "fontVariant": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font variant][1]; a constant; if the **text** channel contains numbers or dates, defaults to *tabular-nums* to facilitate comparing numbers; otherwise defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant" + }, + "fontWeight": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font weight][1]; a constant; defaults to the plot’s font weight, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight" + }, + "format": { + "additionalProperties": false, + "description": "How channel values are formatted for display. If a format is a string, it is interpreted as a (UTC) time format for temporal channels, and otherwise a number format.", + "properties": { + "ariaLabel": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fill": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fillOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fontSize": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fx": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fy": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "geometry": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "height": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "href": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "length": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "opacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "path": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "r": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "rotate": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "src": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "stroke": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeWidth": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "symbol": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "text": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "title": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "weight": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "width": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "z": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + } + }, + "type": "object" + }, + "frameAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The frame anchor specifies defaults for **x** and **y** based on the plot’s frame; it may be one of the four sides (*top*, *right*, *bottom*, *left*), one of the four corners (*top-left*, *top-right*, *bottom-right*,\n*bottom-left*), or the *middle* of the frame. For example, for tips distributed horizontally at the top of the frame:\n\n```js Plot.tip(data, {x: \"date\", frameAnchor: \"top\"}) ```" + }, + "lineHeight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line height in ems; defaults to 1. The line height affects the (typically vertical) separation between adjacent baselines of text, as well as the separation between the text and its anchor point." + }, + "lineWidth": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line width in ems (e.g., 10 for about 20 characters); defaults to infinity, disabling wrapping and clipping.\n\nIf **textOverflow** is null, lines will be wrapped at the specified length. If a line is split at a soft hyphen (\\xad), a hyphen (-) will be displayed at the end of the line. If **textOverflow** is not null, lines will be clipped according to the given strategy." + }, + "monospace": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, changes the default **fontFamily** to *monospace*, and uses simplified monospaced text metrics calculations." + }, + "pathFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The image filter for the tip’s box; defaults to a drop shadow." + }, + "pointer": { + "$ref": "#/definitions/TipPointer" + }, + "pointerSize": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The size of the tip’s pointer in pixels; defaults to 12." + }, + "preferredAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If an explicit tip anchor is not specified, an anchor is chosen automatically such that the tip fits within the plot’s frame; if the preferred anchor fits, it is chosen." + }, + "textAnchor": { + "anyOf": [ + { + "const": "start", + "type": "string" + }, + { + "const": "middle", + "type": "string" + }, + { + "const": "end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [text anchor][1] controls how text is aligned (typically horizontally) relative to its anchor point; it is one of *start*, *end*, or *middle*. If the frame anchor is *left*, *top-left*, or *bottom-left*, the default text anchor is *start*; if the frame anchor is *right*, *top-right*, or\n*bottom-right*, the default is *end*; otherwise it is *middle*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/text-anchor" + }, + "textOverflow": { + "anyOf": [ + { + "type": "null" + }, + { + "const": "clip", + "type": "string" + }, + { + "const": "ellipsis", + "type": "string" + }, + { + "const": "clip-start", + "type": "string" + }, + { + "const": "clip-end", + "type": "string" + }, + { + "const": "ellipsis-start", + "type": "string" + }, + { + "const": "ellipsis-middle", + "type": "string" + }, + { + "const": "ellipsis-end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How truncate (or wrap) lines of text longer than the given **lineWidth**; one of:\n\n- null (default) - preserve overflowing characters (and wrap if needed)\n- *clip* or *clip-end* - remove characters from the end\n- *clip-start* - remove characters from the start\n- *ellipsis* or *ellipsis-end* - replace characters from the end with an ellipsis (…)\n- *ellipsis-start* - replace characters from the start with an ellipsis (…)\n- *ellipsis-middle* - replace characters from the middle with an ellipsis (…)\n\nIf no **title** was specified, if text requires truncation, a title containing the non-truncated text will be implicitly added." + }, + "textPadding": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The padding around the text in pixels; defaults to 8." + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + } + }, + "type": "object" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to generate a tooltip for this mark, and any tip options." + }, + "title": { + "$ref": "#/definitions/ChannelValue", + "description": "The title; a channel specifying accessible, short textual descriptions as strings (possibly with newlines). If the tip option is specified, the title will be displayed with an interactive tooltip instead of using the SVG [title element][1].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/title" + }, + "type": { + "description": "The basic mark type to use to render 1D density values. Defaults to an areaY mark; lineY, dot, and text marks are also supported.", + "enum": [ + "dot", + "dotY", + "circle", + "hexagon" + ], + "type": "string" + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel specifying the dot’s center, typically bound to the *x* scale." + }, + "z": { + "$ref": "#/definitions/ChannelValue", + "description": "An optional ordinal channel for grouping data into series." + } + }, + "required": [ + "data", + "mark", + "type" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "$schema": { + "description": "A [JSON schema](http://json-schema.org/) URL for this specification, such as https://uwdata.github.io/mosaic/schema/latest.json. This property enables validation and autocomplete in editors with JSON schema support.", + "format": "uri", + "type": "string" + }, + "ariaDescription": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-description][1]; a constant textual description.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-description" + }, + "ariaHidden": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-hidden][1] state; a constant indicating whether the element is exposed to an accessibility API.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-hidden" + }, + "ariaLabel": { + "$ref": "#/definitions/ChannelValue", + "description": "The [aria-label][1]; a channel specifying short textual labels representing the value in the accessibility tree.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-label" + }, + "bandwidth": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The kernel density bandwidth for smoothing, in pixels. Defaults to 20." + }, + "bins": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The number of bins over which to discretize the data prior to smoothing. Defaults to 1024." + }, + "clip": { + "anyOf": [ + { + "const": "frame", + "type": "string" + }, + { + "const": "sphere", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to clip the mark; one of:\n\n- *frame* or true - clip to the plot’s frame (inner area)\n- *sphere* - clip to the projected sphere (*e.g.*, front hemisphere)\n- null or false - do not clip\n\nThe *sphere* clip option requires a geographic projection." + }, + "config": { + "$ref": "#/definitions/Config", + "description": "Configuration options." + }, + "data": { + "$ref": "#/definitions/Data", + "description": "Dataset definitions." + }, + "dx": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The horizontal offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "dy": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The vertical offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "facet": { + "anyOf": [ + { + "const": "auto", + "type": "string" + }, + { + "const": "include", + "type": "string" + }, + { + "const": "exclude", + "type": "string" + }, + { + "const": "super", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to enable or disable faceting; one of:\n\n- *auto* (default) - automatically determine if this mark should be faceted\n- *include* (or true) - draw the subset of the mark’s data in the current facet\n- *exclude* - draw the subset of the mark’s data *not* in the current facet\n- *super* - draw this mark in a single frame that covers all facets\n- null (or false) - repeat this mark’s data across all facets (*i.e.*, no faceting)\n\nWhen a mark uses *super* faceting, it is not allowed to use position scales (*x*, *y*, *fx*, or *fy*); *super* faceting is intended for decorations, such as labels and legends.\n\nWhen top-level faceting is used, the default *auto* setting is equivalent to *include* when the mark data is strictly equal to the top-level facet data; otherwise it is equivalent to null. When the *include* or *exclude* facet mode is chosen, the mark data must be parallel to the top-level facet data: the data must have the same length and order. If the data are not parallel, then the wrong data may be shown in each facet. The default\n*auto* therefore requires strict equality (`===`) for safety, and using the facet data as mark data is recommended when using the *exclude* facet mode. (To construct parallel data safely, consider using [*array*.map][1] on the facet data.)\n\nWhen mark-level faceting is used, the default *auto* setting is equivalent to *include*: the mark will be faceted if either the **fx** or **fy** channel option (or both) is specified. The null or false option will disable faceting, while *exclude* draws the subset of the mark’s data *not* in the current facet.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map" + }, + "facetAnchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "right", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "const": "left", + "type": "string" + }, + { + "const": "top-left", + "type": "string" + }, + { + "const": "top-right", + "type": "string" + }, + { + "const": "bottom-left", + "type": "string" + }, + { + "const": "bottom-right", + "type": "string" + }, + { + "const": "top-empty", + "type": "string" + }, + { + "const": "right-empty", + "type": "string" + }, + { + "const": "bottom-empty", + "type": "string" + }, + { + "const": "left-empty", + "type": "string" + }, + { + "const": "empty", + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to place the mark with respect to facets; one of:\n\n- null (default for most marks) - display the mark in each non-empty facet\n- *top*, *right*, *bottom*, or *left* - display the mark only in facets on the given side\n- *top-empty*, *right-empty*, *bottom-empty*, or *left-empty* (default for axis marks) - display the mark only in facets that have empty space on the given side: either the margin, or an empty facet\n- *empty* - display the mark in empty facets only" + }, + "fill": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill" + }, + "fillOpacity": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill-opacity][1]; a constant number between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill-opacity" + }, + "filter": { + "$ref": "#/definitions/ChannelValue", + "description": "Applies a transform to filter the mark’s index according to the given channel values; only truthy values are retained.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "fontFamily": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font-family][1]; a constant; defaults to the plot’s font family, which is typically [*system-ui*][2].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-family [2]: https://drafts.csswg.org/css-fonts-4/#valdef-font-family-system-ui" + }, + "fontSize": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font size][1] in pixels; either a constant or a channel; defaults to the plot’s font size, which is typically 10. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-size" + }, + "fontStyle": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font style][1]; a constant; defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-style" + }, + "fontVariant": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font variant][1]; a constant; if the **text** channel contains numbers or dates, defaults to *tabular-nums* to facilitate comparing numbers; otherwise defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant" + }, + "fontWeight": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font weight][1]; a constant; defaults to the plot’s font weight, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight" + }, + "frameAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The frame anchor specifies defaults for **x** and **y**, along with\n**textAnchor** and **lineAnchor**, based on the plot’s frame; it may be one of the four sides (*top*, *right*, *bottom*, *left*), one of the four corners (*top-left*, *top-right*, *bottom-right*, *bottom-left*), or the\n*middle* of the frame." + }, + "fx": { + "$ref": "#/definitions/ChannelValue", + "description": "The horizontal facet position channel, for mark-level faceting, bound to the *fx* scale." + }, + "fy": { + "$ref": "#/definitions/ChannelValue", + "description": "The vertical facet position channel, for mark-level faceting, bound to the\n*fy* scale." + }, + "href": { + "$ref": "#/definitions/ChannelValue", + "description": "The [href][1]; a channel specifying URLs for clickable links. May be used in conjunction with the **target** option to open links in another window.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/href" + }, + "imageFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A CSS [filter][1]; a constant string used to adjust the rendering of images, such as *blur(5px)*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/filter" + }, + "lineAnchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "middle", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line anchor controls how text is aligned (typically vertically) relative to its anchor point; it is one of *top*, *bottom*, or *middle*. If the frame anchor is *top*, *top-left*, or *top-right*, the default line anchor is *top*; if the frame anchor is *bottom*, *bottom-right*, or\n*bottom-left*, the default is *bottom*; otherwise it is *middle*." + }, + "lineHeight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line height in ems; defaults to 1. The line height affects the (typically vertical) separation between adjacent baselines of text, as well as the separation between the text and its anchor point." + }, + "lineWidth": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line width in ems (e.g., 10 for about 20 characters); defaults to infinity, disabling wrapping and clipping.\n\nIf **textOverflow** is null, lines will be wrapped at the specified length. If a line is split at a soft hyphen (\\xad), a hyphen (-) will be displayed at the end of the line. If **textOverflow** is not null, lines will be clipped according to the given strategy." + }, + "margin": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four mark margins: **marginTop**,\n**marginRight**, **marginBottom**, and **marginLeft**; typically defaults to 0, except for axis marks." + }, + "marginBottom": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s bottom margin; the minimum distance in pixels between the bottom edges of the inner and outer plot area." + }, + "marginLeft": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s left margin; the minimum distance in pixels between the left edges of the inner and outer plot area." + }, + "marginRight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s right margin; the minimum distance in pixels between the right edges of the mark’s inner and outer plot area." + }, + "marginTop": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s top margin; the minimum distance in pixels between the top edges of the inner and outer plot area." + }, + "mark": { + "const": "densityY", + "description": "A densityY mark that visualizes smoothed point cloud densities along the\n**y** dimension. The mark bins the data, counts the number of records that fall into each bin, smooths the resulting counts, and then plots the smoothed distribution, by default using an areaY mark.\n\nSet the *type* property to use a different base mark type.", + "type": "string" + }, + "meta": { + "$ref": "#/definitions/Meta", + "description": "Specification metadata." + }, + "mixBlendMode": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [mix-blend-mode][1]; a constant string specifying how to blend content such as *multiply*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode" + }, + "monospace": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, changes the default **fontFamily** to *monospace*, and uses simplified monospaced text metrics calculations." + }, + "opacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally. For faster rendering, prefer the **strokeOpacity** or **fillOpacity** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/opacity" + }, + "paintOrder": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [paint-order][1]; a constant string specifying the order in which the\n**fill**, **stroke**, and any markers are drawn; defaults to *normal*, which draws the fill, then stroke, then markers; defaults to *stroke* for the text mark to create a “halo” around text to improve legibility.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/paint-order" + }, + "params": { + "$ref": "#/definitions/Params", + "description": "Param and Selection definitions." + }, + "plotDefaults": { + "$ref": "#/definitions/PlotAttributes", + "description": "A default set of attributes to apply to all plot components." + }, + "pointerEvents": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [pointer-events][1] property; a constant string such as *none*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/pointer-events" + }, + "reverse": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Applies a transform to reverse the order of the mark’s index, say for reverse input order." + }, + "rotate": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The rotation angle in degrees clockwise; a constant or a channel; defaults to 0°. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel." + }, + "select": { + "$ref": "#/definitions/SelectFilter", + "description": "Applies a filter transform after data is loaded to highlight selected values only. For example, `first` and `last` select the first or last values of series only (using the *z* channel to separate series). Meanwhile, `nearestX` and `nearestY` select the point nearest to the pointer along the *x* or *y* channel dimension. Unlike Mosaic selections, a mark level *select* is internal to the mark only, and does not populate a param or selection value to be shared across clients.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "shapeRendering": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [shape-rendering][1]; a constant string such as *crispEdges*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/shape-rendering" + }, + "sort": { + "anyOf": [ + { + "$ref": "#/definitions/SortOrder" + }, + { + "$ref": "#/definitions/ChannelDomainSort" + } + ], + "description": "Either applies a transform to sort the mark’s index by the specified channel values, or imputes ordinal scale domains from this mark’s channels.\n\nWhen imputing ordinal scale domains from channel values, the **sort** option is an object whose keys are ordinal scale names such as *x* or *fx*, and whose values are channel names such as *y*, *y1*, or *y2*. For example, to impute the *y* scale’s domain from the associated *x* channel values in ascending order:\n\n```js sort: {y: \"x\"} ```\n\nFor different sort options for different scales, replace the channel name with a *value* object and per-scale options:\n\n```js sort: {y: {value: \"-x\"}} ```\n\nWhen sorting the mark’s index, the **sort** option is instead one of:\n\n- a channel value definition for sorting given values in ascending order\n- a {value, order} object for sorting given values\n- a {channel, order} object for sorting the named channel’s values" + }, + "stroke": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke" + }, + "strokeDasharray": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dasharray][1]; a constant number indicating the length in pixels of alternating dashes and gaps, or a constant string of numbers separated by spaces or commas (_e.g._, *10 2* for dashes of 10 pixels separated by gaps of 2 pixels), or *none* (the default) for no dashing\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dasharray" + }, + "strokeDashoffset": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dashoffset][1]; a constant indicating the offset in pixels of the first dash along the stroke; defaults to zero.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dashoffset" + }, + "strokeLinecap": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linecap][1]; a constant specifying how to cap stroked paths, such as *butt*, *round*, or *square*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linecap" + }, + "strokeLinejoin": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linejoin][1]; a constant specifying how to join stroked paths, such as *bevel*, *miter*, *miter-clip*, or *round*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linejoin" + }, + "strokeMiterlimit": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-miterlimit][1]; a constant number specifying how to limit the length of *miter* joins on stroked paths.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-miterlimit" + }, + "strokeOpacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-opacity" + }, + "strokeWidth": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-width][1]; a constant number in pixels, or a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-width" + }, + "target": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [target][1]; a constant string specifying the target window (_e.g._,\n*_blank*) for clickable links; used in conjunction with the **href** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/target" + }, + "text": { + "$ref": "#/definitions/ChannelValue", + "description": "The text contents channel, possibly with line breaks (\\n, \\r\\n, or \\r). If not specified, defaults to the zero-based index [0, 1, 2, …]." + }, + "textAnchor": { + "anyOf": [ + { + "const": "start", + "type": "string" + }, + { + "const": "middle", + "type": "string" + }, + { + "const": "end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [text anchor][1] controls how text is aligned (typically horizontally) relative to its anchor point; it is one of *start*, *end*, or *middle*. If the frame anchor is *left*, *top-left*, or *bottom-left*, the default text anchor is *start*; if the frame anchor is *right*, *top-right*, or\n*bottom-right*, the default is *end*; otherwise it is *middle*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/text-anchor" + }, + "textOverflow": { + "anyOf": [ + { + "type": "null" + }, + { + "const": "clip", + "type": "string" + }, + { + "const": "ellipsis", + "type": "string" + }, + { + "const": "clip-start", + "type": "string" + }, + { + "const": "clip-end", + "type": "string" + }, + { + "const": "ellipsis-start", + "type": "string" + }, + { + "const": "ellipsis-middle", + "type": "string" + }, + { + "const": "ellipsis-end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How truncate (or wrap) lines of text longer than the given **lineWidth**; one of:\n\n- null (default) - preserve overflowing characters (and wrap if needed)\n- *clip* or *clip-end* - remove characters from the end\n- *clip-start* - remove characters from the start\n- *ellipsis* or *ellipsis-end* - replace characters from the end with an ellipsis (…)\n- *ellipsis-start* - replace characters from the start with an ellipsis (…)\n- *ellipsis-middle* - replace characters from the middle with an ellipsis (…)\n\nIf no **title** was specified, if text requires truncation, a title containing the non-truncated text will be implicitly added." + }, + "tip": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/TipPointer" + }, + { + "properties": { + "anchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The tip anchor specifies how to orient the tip box relative to its anchor position; it refers to the part of the tip box that is attached to the anchor point. For example, the *top-left* anchor places the top-left corner of tip box near the anchor position, hence placing the tip box below and to the right of the anchor position." + }, + "fontFamily": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font-family][1]; a constant; defaults to the plot’s font family, which is typically [*system-ui*][2].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-family [2]: https://drafts.csswg.org/css-fonts-4/#valdef-font-family-system-ui" + }, + "fontSize": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font size][1] in pixels; either a constant or a channel; defaults to the plot’s font size, which is typically 10. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-size" + }, + "fontStyle": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font style][1]; a constant; defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-style" + }, + "fontVariant": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font variant][1]; a constant; if the **text** channel contains numbers or dates, defaults to *tabular-nums* to facilitate comparing numbers; otherwise defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant" + }, + "fontWeight": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font weight][1]; a constant; defaults to the plot’s font weight, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight" + }, + "format": { + "additionalProperties": false, + "description": "How channel values are formatted for display. If a format is a string, it is interpreted as a (UTC) time format for temporal channels, and otherwise a number format.", + "properties": { + "ariaLabel": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fill": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fillOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fontSize": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fx": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fy": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "geometry": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "height": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "href": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "length": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "opacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "path": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "r": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "rotate": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "src": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "stroke": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeWidth": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "symbol": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "text": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "title": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "weight": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "width": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "z": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + } + }, + "type": "object" + }, + "frameAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The frame anchor specifies defaults for **x** and **y** based on the plot’s frame; it may be one of the four sides (*top*, *right*, *bottom*, *left*), one of the four corners (*top-left*, *top-right*, *bottom-right*,\n*bottom-left*), or the *middle* of the frame. For example, for tips distributed horizontally at the top of the frame:\n\n```js Plot.tip(data, {x: \"date\", frameAnchor: \"top\"}) ```" + }, + "lineHeight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line height in ems; defaults to 1. The line height affects the (typically vertical) separation between adjacent baselines of text, as well as the separation between the text and its anchor point." + }, + "lineWidth": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line width in ems (e.g., 10 for about 20 characters); defaults to infinity, disabling wrapping and clipping.\n\nIf **textOverflow** is null, lines will be wrapped at the specified length. If a line is split at a soft hyphen (\\xad), a hyphen (-) will be displayed at the end of the line. If **textOverflow** is not null, lines will be clipped according to the given strategy." + }, + "monospace": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, changes the default **fontFamily** to *monospace*, and uses simplified monospaced text metrics calculations." + }, + "pathFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The image filter for the tip’s box; defaults to a drop shadow." + }, + "pointer": { + "$ref": "#/definitions/TipPointer" + }, + "pointerSize": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The size of the tip’s pointer in pixels; defaults to 12." + }, + "preferredAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If an explicit tip anchor is not specified, an anchor is chosen automatically such that the tip fits within the plot’s frame; if the preferred anchor fits, it is chosen." + }, + "textAnchor": { + "anyOf": [ + { + "const": "start", + "type": "string" + }, + { + "const": "middle", + "type": "string" + }, + { + "const": "end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [text anchor][1] controls how text is aligned (typically horizontally) relative to its anchor point; it is one of *start*, *end*, or *middle*. If the frame anchor is *left*, *top-left*, or *bottom-left*, the default text anchor is *start*; if the frame anchor is *right*, *top-right*, or\n*bottom-right*, the default is *end*; otherwise it is *middle*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/text-anchor" + }, + "textOverflow": { + "anyOf": [ + { + "type": "null" + }, + { + "const": "clip", + "type": "string" + }, + { + "const": "ellipsis", + "type": "string" + }, + { + "const": "clip-start", + "type": "string" + }, + { + "const": "clip-end", + "type": "string" + }, + { + "const": "ellipsis-start", + "type": "string" + }, + { + "const": "ellipsis-middle", + "type": "string" + }, + { + "const": "ellipsis-end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How truncate (or wrap) lines of text longer than the given **lineWidth**; one of:\n\n- null (default) - preserve overflowing characters (and wrap if needed)\n- *clip* or *clip-end* - remove characters from the end\n- *clip-start* - remove characters from the start\n- *ellipsis* or *ellipsis-end* - replace characters from the end with an ellipsis (…)\n- *ellipsis-start* - replace characters from the start with an ellipsis (…)\n- *ellipsis-middle* - replace characters from the middle with an ellipsis (…)\n\nIf no **title** was specified, if text requires truncation, a title containing the non-truncated text will be implicitly added." + }, + "textPadding": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The padding around the text in pixels; defaults to 8." + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + } + }, + "type": "object" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to generate a tooltip for this mark, and any tip options." + }, + "title": { + "$ref": "#/definitions/ChannelValue", + "description": "The title; a channel specifying accessible, short textual descriptions as strings (possibly with newlines). If the tip option is specified, the title will be displayed with an interactive tooltip instead of using the SVG [title element][1].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/title" + }, + "type": { + "description": "The basic mark type to use to render 1D density values. Defaults to an areaY mark; lineY, dot, and text marks are also supported.", + "enum": [ + "text", + "textY" + ], + "type": "string" + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel specifying the text’s anchor point, typically bound to the *x* scale." + }, + "z": { + "$ref": "#/definitions/ChannelValue", + "description": "An optional ordinal channel for grouping data into series." + } + }, + "required": [ + "data", + "mark", + "type" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "$schema": { + "description": "A [JSON schema](http://json-schema.org/) URL for this specification, such as https://uwdata.github.io/mosaic/schema/latest.json. This property enables validation and autocomplete in editors with JSON schema support.", + "format": "uri", + "type": "string" + }, + "ariaDescription": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-description][1]; a constant textual description.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-description" + }, + "ariaHidden": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-hidden][1] state; a constant indicating whether the element is exposed to an accessibility API.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-hidden" + }, + "ariaLabel": { + "$ref": "#/definitions/ChannelValue", + "description": "The [aria-label][1]; a channel specifying short textual labels representing the value in the accessibility tree.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-label" + }, + "clip": { + "anyOf": [ + { + "const": "frame", + "type": "string" + }, + { + "const": "sphere", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to clip the mark; one of:\n\n- *frame* or true - clip to the plot’s frame (inner area)\n- *sphere* - clip to the projected sphere (*e.g.*, front hemisphere)\n- null or false - do not clip\n\nThe *sphere* clip option requires a geographic projection." + }, + "config": { + "$ref": "#/definitions/Config", + "description": "Configuration options." + }, + "data": { + "$ref": "#/definitions/Data", + "description": "Dataset definitions." + }, + "dx": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The horizontal offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "dy": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The vertical offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "facet": { + "anyOf": [ + { + "const": "auto", + "type": "string" + }, + { + "const": "include", + "type": "string" + }, + { + "const": "exclude", + "type": "string" + }, + { + "const": "super", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to enable or disable faceting; one of:\n\n- *auto* (default) - automatically determine if this mark should be faceted\n- *include* (or true) - draw the subset of the mark’s data in the current facet\n- *exclude* - draw the subset of the mark’s data *not* in the current facet\n- *super* - draw this mark in a single frame that covers all facets\n- null (or false) - repeat this mark’s data across all facets (*i.e.*, no faceting)\n\nWhen a mark uses *super* faceting, it is not allowed to use position scales (*x*, *y*, *fx*, or *fy*); *super* faceting is intended for decorations, such as labels and legends.\n\nWhen top-level faceting is used, the default *auto* setting is equivalent to *include* when the mark data is strictly equal to the top-level facet data; otherwise it is equivalent to null. When the *include* or *exclude* facet mode is chosen, the mark data must be parallel to the top-level facet data: the data must have the same length and order. If the data are not parallel, then the wrong data may be shown in each facet. The default\n*auto* therefore requires strict equality (`===`) for safety, and using the facet data as mark data is recommended when using the *exclude* facet mode. (To construct parallel data safely, consider using [*array*.map][1] on the facet data.)\n\nWhen mark-level faceting is used, the default *auto* setting is equivalent to *include*: the mark will be faceted if either the **fx** or **fy** channel option (or both) is specified. The null or false option will disable faceting, while *exclude* draws the subset of the mark’s data *not* in the current facet.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map" + }, + "facetAnchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "right", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "const": "left", + "type": "string" + }, + { + "const": "top-left", + "type": "string" + }, + { + "const": "top-right", + "type": "string" + }, + { + "const": "bottom-left", + "type": "string" + }, + { + "const": "bottom-right", + "type": "string" + }, + { + "const": "top-empty", + "type": "string" + }, + { + "const": "right-empty", + "type": "string" + }, + { + "const": "bottom-empty", + "type": "string" + }, + { + "const": "left-empty", + "type": "string" + }, + { + "const": "empty", + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to place the mark with respect to facets; one of:\n\n- null (default for most marks) - display the mark in each non-empty facet\n- *top*, *right*, *bottom*, or *left* - display the mark only in facets on the given side\n- *top-empty*, *right-empty*, *bottom-empty*, or *left-empty* (default for axis marks) - display the mark only in facets that have empty space on the given side: either the margin, or an empty facet\n- *empty* - display the mark in empty facets only" + }, + "fill": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill" + }, + "fillOpacity": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill-opacity][1]; a constant number between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill-opacity" + }, + "filter": { + "$ref": "#/definitions/ChannelValue", + "description": "Applies a transform to filter the mark’s index according to the given channel values; only truthy values are retained.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "frameAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The frame anchor specifies defaults for **x** and **y** based on the plot’s frame; it may be one of the four sides (*top*, *right*, *bottom*, *left*), one of the four corners (*top-left*, *top-right*, *bottom-right*,\n*bottom-left*), or the *middle* of the frame. For example, for dots distributed horizontally at the top of the frame:\n\n```js Plot.dot(data, {x: \"date\", frameAnchor: \"top\"}) ```" + }, + "fx": { + "$ref": "#/definitions/ChannelValue", + "description": "The horizontal facet position channel, for mark-level faceting, bound to the *fx* scale." + }, + "fy": { + "$ref": "#/definitions/ChannelValue", + "description": "The vertical facet position channel, for mark-level faceting, bound to the\n*fy* scale." + }, + "href": { + "$ref": "#/definitions/ChannelValue", + "description": "The [href][1]; a channel specifying URLs for clickable links. May be used in conjunction with the **target** option to open links in another window.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/href" + }, + "imageFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A CSS [filter][1]; a constant string used to adjust the rendering of images, such as *blur(5px)*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/filter" + }, + "margin": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four mark margins: **marginTop**,\n**marginRight**, **marginBottom**, and **marginLeft**; typically defaults to 0, except for axis marks." + }, + "marginBottom": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s bottom margin; the minimum distance in pixels between the bottom edges of the inner and outer plot area." + }, + "marginLeft": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s left margin; the minimum distance in pixels between the left edges of the inner and outer plot area." + }, + "marginRight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s right margin; the minimum distance in pixels between the right edges of the mark’s inner and outer plot area." + }, + "marginTop": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s top margin; the minimum distance in pixels between the top edges of the inner and outer plot area." + }, + "mark": { + "const": "dot", + "description": "A dot mark that draws circles, or other symbols, as in a scatterplot.\n\nIf either **x** or **y** is not specified, the default is determined by the\n**frameAnchor** option. If none of **x**, **y**, and **frameAnchor** are specified, *data* is assumed to be an array of pairs [[*x₀*, *y₀*], [*x₁*,\n*y₁*], [*x₂*, *y₂*], …] such that **x** = [*x₀*, *x₁*, *x₂*, …] and **y** = [*y₀*, *y₁*, *y₂*, …].\n\nDots are sorted by descending radius **r** by default to mitigate overplotting; set the **sort** option to null to draw them in input order.", + "type": "string" + }, + "meta": { + "$ref": "#/definitions/Meta", + "description": "Specification metadata." + }, + "mixBlendMode": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [mix-blend-mode][1]; a constant string specifying how to blend content such as *multiply*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode" + }, + "opacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally. For faster rendering, prefer the **strokeOpacity** or **fillOpacity** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/opacity" + }, + "paintOrder": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [paint-order][1]; a constant string specifying the order in which the\n**fill**, **stroke**, and any markers are drawn; defaults to *normal*, which draws the fill, then stroke, then markers; defaults to *stroke* for the text mark to create a “halo” around text to improve legibility.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/paint-order" + }, + "params": { + "$ref": "#/definitions/Params", + "description": "Param and Selection definitions." + }, + "plotDefaults": { + "$ref": "#/definitions/PlotAttributes", + "description": "A default set of attributes to apply to all plot components." + }, + "pointerEvents": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [pointer-events][1] property; a constant string such as *none*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/pointer-events" + }, + "r": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The radius of dots; either a channel or constant. When a number, it is interpreted as a constant radius in pixels. Otherwise it is interpreted as a channel, typically bound to the *r* channel, which defaults to the *sqrt* type for proportional symbols. The radius defaults to 4.5 pixels when using the **symbol** channel, and otherwise 3 pixels. Dots with a nonpositive radius are not drawn." + }, + "reverse": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Applies a transform to reverse the order of the mark’s index, say for reverse input order." + }, + "rotate": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The rotation angle of dots in degrees clockwise; either a channel or a constant. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel. Defaults to 0°, pointing up." + }, + "select": { + "$ref": "#/definitions/SelectFilter", + "description": "Applies a filter transform after data is loaded to highlight selected values only. For example, `first` and `last` select the first or last values of series only (using the *z* channel to separate series). Meanwhile, `nearestX` and `nearestY` select the point nearest to the pointer along the *x* or *y* channel dimension. Unlike Mosaic selections, a mark level *select* is internal to the mark only, and does not populate a param or selection value to be shared across clients.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "shapeRendering": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [shape-rendering][1]; a constant string such as *crispEdges*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/shape-rendering" + }, + "sort": { + "anyOf": [ + { + "$ref": "#/definitions/SortOrder" + }, + { + "$ref": "#/definitions/ChannelDomainSort" + } + ], + "description": "Either applies a transform to sort the mark’s index by the specified channel values, or imputes ordinal scale domains from this mark’s channels.\n\nWhen imputing ordinal scale domains from channel values, the **sort** option is an object whose keys are ordinal scale names such as *x* or *fx*, and whose values are channel names such as *y*, *y1*, or *y2*. For example, to impute the *y* scale’s domain from the associated *x* channel values in ascending order:\n\n```js sort: {y: \"x\"} ```\n\nFor different sort options for different scales, replace the channel name with a *value* object and per-scale options:\n\n```js sort: {y: {value: \"-x\"}} ```\n\nWhen sorting the mark’s index, the **sort** option is instead one of:\n\n- a channel value definition for sorting given values in ascending order\n- a {value, order} object for sorting given values\n- a {channel, order} object for sorting the named channel’s values" + }, + "stroke": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke" + }, + "strokeDasharray": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dasharray][1]; a constant number indicating the length in pixels of alternating dashes and gaps, or a constant string of numbers separated by spaces or commas (_e.g._, *10 2* for dashes of 10 pixels separated by gaps of 2 pixels), or *none* (the default) for no dashing\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dasharray" + }, + "strokeDashoffset": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dashoffset][1]; a constant indicating the offset in pixels of the first dash along the stroke; defaults to zero.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dashoffset" + }, + "strokeLinecap": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linecap][1]; a constant specifying how to cap stroked paths, such as *butt*, *round*, or *square*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linecap" + }, + "strokeLinejoin": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linejoin][1]; a constant specifying how to join stroked paths, such as *bevel*, *miter*, *miter-clip*, or *round*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linejoin" + }, + "strokeMiterlimit": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-miterlimit][1]; a constant number specifying how to limit the length of *miter* joins on stroked paths.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-miterlimit" + }, + "strokeOpacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-opacity" + }, + "strokeWidth": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-width][1]; a constant number in pixels, or a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-width" + }, + "symbol": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/SymbolType" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The categorical symbol; either a channel or a constant. A constant symbol can be specified by a valid symbol name such as *star*, or a symbol object (implementing the draw method); otherwise it is interpreted as a channel. Defaults to *circle* for the **dot** mark, and *hexagon* for the\n**hexagon** mark.\n\nIf the **symbol** channel’s values are all symbols, symbol names, or nullish, the channel is unscaled (values are interpreted literally); otherwise, the channel is bound to the *symbol* scale." + }, + "target": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [target][1]; a constant string specifying the target window (_e.g._,\n*_blank*) for clickable links; used in conjunction with the **href** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/target" + }, + "tip": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/TipPointer" + }, + { + "properties": { + "anchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The tip anchor specifies how to orient the tip box relative to its anchor position; it refers to the part of the tip box that is attached to the anchor point. For example, the *top-left* anchor places the top-left corner of tip box near the anchor position, hence placing the tip box below and to the right of the anchor position." + }, + "fontFamily": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font-family][1]; a constant; defaults to the plot’s font family, which is typically [*system-ui*][2].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-family [2]: https://drafts.csswg.org/css-fonts-4/#valdef-font-family-system-ui" + }, + "fontSize": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font size][1] in pixels; either a constant or a channel; defaults to the plot’s font size, which is typically 10. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-size" + }, + "fontStyle": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font style][1]; a constant; defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-style" + }, + "fontVariant": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font variant][1]; a constant; if the **text** channel contains numbers or dates, defaults to *tabular-nums* to facilitate comparing numbers; otherwise defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant" + }, + "fontWeight": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font weight][1]; a constant; defaults to the plot’s font weight, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight" + }, + "format": { + "additionalProperties": false, + "description": "How channel values are formatted for display. If a format is a string, it is interpreted as a (UTC) time format for temporal channels, and otherwise a number format.", + "properties": { + "ariaLabel": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fill": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fillOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fontSize": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fx": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fy": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "geometry": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "height": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "href": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "length": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "opacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "path": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "r": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "rotate": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "src": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "stroke": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeWidth": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "symbol": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "text": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "title": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "weight": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "width": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "z": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + } + }, + "type": "object" + }, + "frameAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The frame anchor specifies defaults for **x** and **y** based on the plot’s frame; it may be one of the four sides (*top*, *right*, *bottom*, *left*), one of the four corners (*top-left*, *top-right*, *bottom-right*,\n*bottom-left*), or the *middle* of the frame. For example, for tips distributed horizontally at the top of the frame:\n\n```js Plot.tip(data, {x: \"date\", frameAnchor: \"top\"}) ```" + }, + "lineHeight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line height in ems; defaults to 1. The line height affects the (typically vertical) separation between adjacent baselines of text, as well as the separation between the text and its anchor point." + }, + "lineWidth": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line width in ems (e.g., 10 for about 20 characters); defaults to infinity, disabling wrapping and clipping.\n\nIf **textOverflow** is null, lines will be wrapped at the specified length. If a line is split at a soft hyphen (\\xad), a hyphen (-) will be displayed at the end of the line. If **textOverflow** is not null, lines will be clipped according to the given strategy." + }, + "monospace": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, changes the default **fontFamily** to *monospace*, and uses simplified monospaced text metrics calculations." + }, + "pathFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The image filter for the tip’s box; defaults to a drop shadow." + }, + "pointer": { + "$ref": "#/definitions/TipPointer" + }, + "pointerSize": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The size of the tip’s pointer in pixels; defaults to 12." + }, + "preferredAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If an explicit tip anchor is not specified, an anchor is chosen automatically such that the tip fits within the plot’s frame; if the preferred anchor fits, it is chosen." + }, + "textAnchor": { + "anyOf": [ + { + "const": "start", + "type": "string" + }, + { + "const": "middle", + "type": "string" + }, + { + "const": "end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [text anchor][1] controls how text is aligned (typically horizontally) relative to its anchor point; it is one of *start*, *end*, or *middle*. If the frame anchor is *left*, *top-left*, or *bottom-left*, the default text anchor is *start*; if the frame anchor is *right*, *top-right*, or\n*bottom-right*, the default is *end*; otherwise it is *middle*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/text-anchor" + }, + "textOverflow": { + "anyOf": [ + { + "type": "null" + }, + { + "const": "clip", + "type": "string" + }, + { + "const": "ellipsis", + "type": "string" + }, + { + "const": "clip-start", + "type": "string" + }, + { + "const": "clip-end", + "type": "string" + }, + { + "const": "ellipsis-start", + "type": "string" + }, + { + "const": "ellipsis-middle", + "type": "string" + }, + { + "const": "ellipsis-end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How truncate (or wrap) lines of text longer than the given **lineWidth**; one of:\n\n- null (default) - preserve overflowing characters (and wrap if needed)\n- *clip* or *clip-end* - remove characters from the end\n- *clip-start* - remove characters from the start\n- *ellipsis* or *ellipsis-end* - replace characters from the end with an ellipsis (…)\n- *ellipsis-start* - replace characters from the start with an ellipsis (…)\n- *ellipsis-middle* - replace characters from the middle with an ellipsis (…)\n\nIf no **title** was specified, if text requires truncation, a title containing the non-truncated text will be implicitly added." + }, + "textPadding": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The padding around the text in pixels; defaults to 8." + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + } + }, + "type": "object" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to generate a tooltip for this mark, and any tip options." + }, + "title": { + "$ref": "#/definitions/ChannelValue", + "description": "The title; a channel specifying accessible, short textual descriptions as strings (possibly with newlines). If the tip option is specified, the title will be displayed with an interactive tooltip instead of using the SVG [title element][1].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/title" + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel specifying the dot’s center, typically bound to the *x* scale." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel specifying the dot’s center, typically bound to the *y* scale." + }, + "z": { + "$ref": "#/definitions/ChannelValue", + "description": "An optional ordinal channel for grouping data into series." + } + }, + "required": [ + "data", + "mark" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "$schema": { + "description": "A [JSON schema](http://json-schema.org/) URL for this specification, such as https://uwdata.github.io/mosaic/schema/latest.json. This property enables validation and autocomplete in editors with JSON schema support.", + "format": "uri", + "type": "string" + }, + "ariaDescription": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-description][1]; a constant textual description.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-description" + }, + "ariaHidden": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-hidden][1] state; a constant indicating whether the element is exposed to an accessibility API.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-hidden" + }, + "ariaLabel": { + "$ref": "#/definitions/ChannelValue", + "description": "The [aria-label][1]; a channel specifying short textual labels representing the value in the accessibility tree.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-label" + }, + "clip": { + "anyOf": [ + { + "const": "frame", + "type": "string" + }, + { + "const": "sphere", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to clip the mark; one of:\n\n- *frame* or true - clip to the plot’s frame (inner area)\n- *sphere* - clip to the projected sphere (*e.g.*, front hemisphere)\n- null or false - do not clip\n\nThe *sphere* clip option requires a geographic projection." + }, + "config": { + "$ref": "#/definitions/Config", + "description": "Configuration options." + }, + "data": { + "$ref": "#/definitions/Data", + "description": "Dataset definitions." + }, + "dx": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The horizontal offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "dy": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The vertical offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "facet": { + "anyOf": [ + { + "const": "auto", + "type": "string" + }, + { + "const": "include", + "type": "string" + }, + { + "const": "exclude", + "type": "string" + }, + { + "const": "super", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to enable or disable faceting; one of:\n\n- *auto* (default) - automatically determine if this mark should be faceted\n- *include* (or true) - draw the subset of the mark’s data in the current facet\n- *exclude* - draw the subset of the mark’s data *not* in the current facet\n- *super* - draw this mark in a single frame that covers all facets\n- null (or false) - repeat this mark’s data across all facets (*i.e.*, no faceting)\n\nWhen a mark uses *super* faceting, it is not allowed to use position scales (*x*, *y*, *fx*, or *fy*); *super* faceting is intended for decorations, such as labels and legends.\n\nWhen top-level faceting is used, the default *auto* setting is equivalent to *include* when the mark data is strictly equal to the top-level facet data; otherwise it is equivalent to null. When the *include* or *exclude* facet mode is chosen, the mark data must be parallel to the top-level facet data: the data must have the same length and order. If the data are not parallel, then the wrong data may be shown in each facet. The default\n*auto* therefore requires strict equality (`===`) for safety, and using the facet data as mark data is recommended when using the *exclude* facet mode. (To construct parallel data safely, consider using [*array*.map][1] on the facet data.)\n\nWhen mark-level faceting is used, the default *auto* setting is equivalent to *include*: the mark will be faceted if either the **fx** or **fy** channel option (or both) is specified. The null or false option will disable faceting, while *exclude* draws the subset of the mark’s data *not* in the current facet.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map" + }, + "facetAnchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "right", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "const": "left", + "type": "string" + }, + { + "const": "top-left", + "type": "string" + }, + { + "const": "top-right", + "type": "string" + }, + { + "const": "bottom-left", + "type": "string" + }, + { + "const": "bottom-right", + "type": "string" + }, + { + "const": "top-empty", + "type": "string" + }, + { + "const": "right-empty", + "type": "string" + }, + { + "const": "bottom-empty", + "type": "string" + }, + { + "const": "left-empty", + "type": "string" + }, + { + "const": "empty", + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to place the mark with respect to facets; one of:\n\n- null (default for most marks) - display the mark in each non-empty facet\n- *top*, *right*, *bottom*, or *left* - display the mark only in facets on the given side\n- *top-empty*, *right-empty*, *bottom-empty*, or *left-empty* (default for axis marks) - display the mark only in facets that have empty space on the given side: either the margin, or an empty facet\n- *empty* - display the mark in empty facets only" + }, + "fill": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill" + }, + "fillOpacity": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill-opacity][1]; a constant number between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill-opacity" + }, + "filter": { + "$ref": "#/definitions/ChannelValue", + "description": "Applies a transform to filter the mark’s index according to the given channel values; only truthy values are retained.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "frameAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The frame anchor specifies defaults for **x** and **y** based on the plot’s frame; it may be one of the four sides (*top*, *right*, *bottom*, *left*), one of the four corners (*top-left*, *top-right*, *bottom-right*,\n*bottom-left*), or the *middle* of the frame. For example, for dots distributed horizontally at the top of the frame:\n\n```js Plot.dot(data, {x: \"date\", frameAnchor: \"top\"}) ```" + }, + "fx": { + "$ref": "#/definitions/ChannelValue", + "description": "The horizontal facet position channel, for mark-level faceting, bound to the *fx* scale." + }, + "fy": { + "$ref": "#/definitions/ChannelValue", + "description": "The vertical facet position channel, for mark-level faceting, bound to the\n*fy* scale." + }, + "href": { + "$ref": "#/definitions/ChannelValue", + "description": "The [href][1]; a channel specifying URLs for clickable links. May be used in conjunction with the **target** option to open links in another window.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/href" + }, + "imageFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A CSS [filter][1]; a constant string used to adjust the rendering of images, such as *blur(5px)*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/filter" + }, + "interval": { + "anyOf": [ + { + "$ref": "#/definitions/Interval" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "An interval (such as *day* or a number), to transform **y** values to the middle of the interval." + }, + "margin": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four mark margins: **marginTop**,\n**marginRight**, **marginBottom**, and **marginLeft**; typically defaults to 0, except for axis marks." + }, + "marginBottom": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s bottom margin; the minimum distance in pixels between the bottom edges of the inner and outer plot area." + }, + "marginLeft": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s left margin; the minimum distance in pixels between the left edges of the inner and outer plot area." + }, + "marginRight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s right margin; the minimum distance in pixels between the right edges of the mark’s inner and outer plot area." + }, + "marginTop": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s top margin; the minimum distance in pixels between the top edges of the inner and outer plot area." + }, + "mark": { + "const": "dotX", + "description": "Like dot, except that **x** defaults to the identity function, assuming that\n*data* = [*x₀*, *x₁*, *x₂*, …].\n\nIf an **interval** is specified, such as *day*, **y** is transformed to the middle of the interval.", + "type": "string" + }, + "meta": { + "$ref": "#/definitions/Meta", + "description": "Specification metadata." + }, + "mixBlendMode": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [mix-blend-mode][1]; a constant string specifying how to blend content such as *multiply*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode" + }, + "opacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally. For faster rendering, prefer the **strokeOpacity** or **fillOpacity** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/opacity" + }, + "paintOrder": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [paint-order][1]; a constant string specifying the order in which the\n**fill**, **stroke**, and any markers are drawn; defaults to *normal*, which draws the fill, then stroke, then markers; defaults to *stroke* for the text mark to create a “halo” around text to improve legibility.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/paint-order" + }, + "params": { + "$ref": "#/definitions/Params", + "description": "Param and Selection definitions." + }, + "plotDefaults": { + "$ref": "#/definitions/PlotAttributes", + "description": "A default set of attributes to apply to all plot components." + }, + "pointerEvents": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [pointer-events][1] property; a constant string such as *none*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/pointer-events" + }, + "r": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The radius of dots; either a channel or constant. When a number, it is interpreted as a constant radius in pixels. Otherwise it is interpreted as a channel, typically bound to the *r* channel, which defaults to the *sqrt* type for proportional symbols. The radius defaults to 4.5 pixels when using the **symbol** channel, and otherwise 3 pixels. Dots with a nonpositive radius are not drawn." + }, + "reverse": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Applies a transform to reverse the order of the mark’s index, say for reverse input order." + }, + "rotate": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The rotation angle of dots in degrees clockwise; either a channel or a constant. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel. Defaults to 0°, pointing up." + }, + "select": { + "$ref": "#/definitions/SelectFilter", + "description": "Applies a filter transform after data is loaded to highlight selected values only. For example, `first` and `last` select the first or last values of series only (using the *z* channel to separate series). Meanwhile, `nearestX` and `nearestY` select the point nearest to the pointer along the *x* or *y* channel dimension. Unlike Mosaic selections, a mark level *select* is internal to the mark only, and does not populate a param or selection value to be shared across clients.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "shapeRendering": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [shape-rendering][1]; a constant string such as *crispEdges*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/shape-rendering" + }, + "sort": { + "anyOf": [ + { + "$ref": "#/definitions/SortOrder" + }, + { + "$ref": "#/definitions/ChannelDomainSort" + } + ], + "description": "Either applies a transform to sort the mark’s index by the specified channel values, or imputes ordinal scale domains from this mark’s channels.\n\nWhen imputing ordinal scale domains from channel values, the **sort** option is an object whose keys are ordinal scale names such as *x* or *fx*, and whose values are channel names such as *y*, *y1*, or *y2*. For example, to impute the *y* scale’s domain from the associated *x* channel values in ascending order:\n\n```js sort: {y: \"x\"} ```\n\nFor different sort options for different scales, replace the channel name with a *value* object and per-scale options:\n\n```js sort: {y: {value: \"-x\"}} ```\n\nWhen sorting the mark’s index, the **sort** option is instead one of:\n\n- a channel value definition for sorting given values in ascending order\n- a {value, order} object for sorting given values\n- a {channel, order} object for sorting the named channel’s values" + }, + "stroke": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke" + }, + "strokeDasharray": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dasharray][1]; a constant number indicating the length in pixels of alternating dashes and gaps, or a constant string of numbers separated by spaces or commas (_e.g._, *10 2* for dashes of 10 pixels separated by gaps of 2 pixels), or *none* (the default) for no dashing\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dasharray" + }, + "strokeDashoffset": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dashoffset][1]; a constant indicating the offset in pixels of the first dash along the stroke; defaults to zero.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dashoffset" + }, + "strokeLinecap": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linecap][1]; a constant specifying how to cap stroked paths, such as *butt*, *round*, or *square*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linecap" + }, + "strokeLinejoin": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linejoin][1]; a constant specifying how to join stroked paths, such as *bevel*, *miter*, *miter-clip*, or *round*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linejoin" + }, + "strokeMiterlimit": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-miterlimit][1]; a constant number specifying how to limit the length of *miter* joins on stroked paths.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-miterlimit" + }, + "strokeOpacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-opacity" + }, + "strokeWidth": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-width][1]; a constant number in pixels, or a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-width" + }, + "symbol": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/SymbolType" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The categorical symbol; either a channel or a constant. A constant symbol can be specified by a valid symbol name such as *star*, or a symbol object (implementing the draw method); otherwise it is interpreted as a channel. Defaults to *circle* for the **dot** mark, and *hexagon* for the\n**hexagon** mark.\n\nIf the **symbol** channel’s values are all symbols, symbol names, or nullish, the channel is unscaled (values are interpreted literally); otherwise, the channel is bound to the *symbol* scale." + }, + "target": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [target][1]; a constant string specifying the target window (_e.g._,\n*_blank*) for clickable links; used in conjunction with the **href** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/target" + }, + "tip": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/TipPointer" + }, + { + "properties": { + "anchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The tip anchor specifies how to orient the tip box relative to its anchor position; it refers to the part of the tip box that is attached to the anchor point. For example, the *top-left* anchor places the top-left corner of tip box near the anchor position, hence placing the tip box below and to the right of the anchor position." + }, + "fontFamily": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font-family][1]; a constant; defaults to the plot’s font family, which is typically [*system-ui*][2].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-family [2]: https://drafts.csswg.org/css-fonts-4/#valdef-font-family-system-ui" + }, + "fontSize": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font size][1] in pixels; either a constant or a channel; defaults to the plot’s font size, which is typically 10. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-size" + }, + "fontStyle": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font style][1]; a constant; defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-style" + }, + "fontVariant": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font variant][1]; a constant; if the **text** channel contains numbers or dates, defaults to *tabular-nums* to facilitate comparing numbers; otherwise defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant" + }, + "fontWeight": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font weight][1]; a constant; defaults to the plot’s font weight, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight" + }, + "format": { + "additionalProperties": false, + "description": "How channel values are formatted for display. If a format is a string, it is interpreted as a (UTC) time format for temporal channels, and otherwise a number format.", + "properties": { + "ariaLabel": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fill": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fillOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fontSize": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fx": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fy": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "geometry": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "height": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "href": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "length": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "opacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "path": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "r": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "rotate": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "src": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "stroke": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeWidth": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "symbol": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "text": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "title": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "weight": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "width": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "z": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + } + }, + "type": "object" + }, + "frameAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The frame anchor specifies defaults for **x** and **y** based on the plot’s frame; it may be one of the four sides (*top*, *right*, *bottom*, *left*), one of the four corners (*top-left*, *top-right*, *bottom-right*,\n*bottom-left*), or the *middle* of the frame. For example, for tips distributed horizontally at the top of the frame:\n\n```js Plot.tip(data, {x: \"date\", frameAnchor: \"top\"}) ```" + }, + "lineHeight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line height in ems; defaults to 1. The line height affects the (typically vertical) separation between adjacent baselines of text, as well as the separation between the text and its anchor point." + }, + "lineWidth": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line width in ems (e.g., 10 for about 20 characters); defaults to infinity, disabling wrapping and clipping.\n\nIf **textOverflow** is null, lines will be wrapped at the specified length. If a line is split at a soft hyphen (\\xad), a hyphen (-) will be displayed at the end of the line. If **textOverflow** is not null, lines will be clipped according to the given strategy." + }, + "monospace": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, changes the default **fontFamily** to *monospace*, and uses simplified monospaced text metrics calculations." + }, + "pathFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The image filter for the tip’s box; defaults to a drop shadow." + }, + "pointer": { + "$ref": "#/definitions/TipPointer" + }, + "pointerSize": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The size of the tip’s pointer in pixels; defaults to 12." + }, + "preferredAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If an explicit tip anchor is not specified, an anchor is chosen automatically such that the tip fits within the plot’s frame; if the preferred anchor fits, it is chosen." + }, + "textAnchor": { + "anyOf": [ + { + "const": "start", + "type": "string" + }, + { + "const": "middle", + "type": "string" + }, + { + "const": "end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [text anchor][1] controls how text is aligned (typically horizontally) relative to its anchor point; it is one of *start*, *end*, or *middle*. If the frame anchor is *left*, *top-left*, or *bottom-left*, the default text anchor is *start*; if the frame anchor is *right*, *top-right*, or\n*bottom-right*, the default is *end*; otherwise it is *middle*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/text-anchor" + }, + "textOverflow": { + "anyOf": [ + { + "type": "null" + }, + { + "const": "clip", + "type": "string" + }, + { + "const": "ellipsis", + "type": "string" + }, + { + "const": "clip-start", + "type": "string" + }, + { + "const": "clip-end", + "type": "string" + }, + { + "const": "ellipsis-start", + "type": "string" + }, + { + "const": "ellipsis-middle", + "type": "string" + }, + { + "const": "ellipsis-end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How truncate (or wrap) lines of text longer than the given **lineWidth**; one of:\n\n- null (default) - preserve overflowing characters (and wrap if needed)\n- *clip* or *clip-end* - remove characters from the end\n- *clip-start* - remove characters from the start\n- *ellipsis* or *ellipsis-end* - replace characters from the end with an ellipsis (…)\n- *ellipsis-start* - replace characters from the start with an ellipsis (…)\n- *ellipsis-middle* - replace characters from the middle with an ellipsis (…)\n\nIf no **title** was specified, if text requires truncation, a title containing the non-truncated text will be implicitly added." + }, + "textPadding": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The padding around the text in pixels; defaults to 8." + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + } + }, + "type": "object" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to generate a tooltip for this mark, and any tip options." + }, + "title": { + "$ref": "#/definitions/ChannelValue", + "description": "The title; a channel specifying accessible, short textual descriptions as strings (possibly with newlines). If the tip option is specified, the title will be displayed with an interactive tooltip instead of using the SVG [title element][1].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/title" + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel specifying the dot’s center, typically bound to the *x* scale." + }, + "y": { + "$ref": "#/definitions/ChannelValueIntervalSpec", + "description": "The vertical position of the dot’s center, typically bound to the *y* scale." + }, + "z": { + "$ref": "#/definitions/ChannelValue", + "description": "An optional ordinal channel for grouping data into series." + } + }, + "required": [ + "data", + "mark" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "$schema": { + "description": "A [JSON schema](http://json-schema.org/) URL for this specification, such as https://uwdata.github.io/mosaic/schema/latest.json. This property enables validation and autocomplete in editors with JSON schema support.", + "format": "uri", + "type": "string" + }, + "ariaDescription": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-description][1]; a constant textual description.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-description" + }, + "ariaHidden": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-hidden][1] state; a constant indicating whether the element is exposed to an accessibility API.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-hidden" + }, + "ariaLabel": { + "$ref": "#/definitions/ChannelValue", + "description": "The [aria-label][1]; a channel specifying short textual labels representing the value in the accessibility tree.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-label" + }, + "clip": { + "anyOf": [ + { + "const": "frame", + "type": "string" + }, + { + "const": "sphere", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to clip the mark; one of:\n\n- *frame* or true - clip to the plot’s frame (inner area)\n- *sphere* - clip to the projected sphere (*e.g.*, front hemisphere)\n- null or false - do not clip\n\nThe *sphere* clip option requires a geographic projection." + }, + "config": { + "$ref": "#/definitions/Config", + "description": "Configuration options." + }, + "data": { + "$ref": "#/definitions/Data", + "description": "Dataset definitions." + }, + "dx": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The horizontal offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "dy": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The vertical offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "facet": { + "anyOf": [ + { + "const": "auto", + "type": "string" + }, + { + "const": "include", + "type": "string" + }, + { + "const": "exclude", + "type": "string" + }, + { + "const": "super", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to enable or disable faceting; one of:\n\n- *auto* (default) - automatically determine if this mark should be faceted\n- *include* (or true) - draw the subset of the mark’s data in the current facet\n- *exclude* - draw the subset of the mark’s data *not* in the current facet\n- *super* - draw this mark in a single frame that covers all facets\n- null (or false) - repeat this mark’s data across all facets (*i.e.*, no faceting)\n\nWhen a mark uses *super* faceting, it is not allowed to use position scales (*x*, *y*, *fx*, or *fy*); *super* faceting is intended for decorations, such as labels and legends.\n\nWhen top-level faceting is used, the default *auto* setting is equivalent to *include* when the mark data is strictly equal to the top-level facet data; otherwise it is equivalent to null. When the *include* or *exclude* facet mode is chosen, the mark data must be parallel to the top-level facet data: the data must have the same length and order. If the data are not parallel, then the wrong data may be shown in each facet. The default\n*auto* therefore requires strict equality (`===`) for safety, and using the facet data as mark data is recommended when using the *exclude* facet mode. (To construct parallel data safely, consider using [*array*.map][1] on the facet data.)\n\nWhen mark-level faceting is used, the default *auto* setting is equivalent to *include*: the mark will be faceted if either the **fx** or **fy** channel option (or both) is specified. The null or false option will disable faceting, while *exclude* draws the subset of the mark’s data *not* in the current facet.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map" + }, + "facetAnchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "right", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "const": "left", + "type": "string" + }, + { + "const": "top-left", + "type": "string" + }, + { + "const": "top-right", + "type": "string" + }, + { + "const": "bottom-left", + "type": "string" + }, + { + "const": "bottom-right", + "type": "string" + }, + { + "const": "top-empty", + "type": "string" + }, + { + "const": "right-empty", + "type": "string" + }, + { + "const": "bottom-empty", + "type": "string" + }, + { + "const": "left-empty", + "type": "string" + }, + { + "const": "empty", + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to place the mark with respect to facets; one of:\n\n- null (default for most marks) - display the mark in each non-empty facet\n- *top*, *right*, *bottom*, or *left* - display the mark only in facets on the given side\n- *top-empty*, *right-empty*, *bottom-empty*, or *left-empty* (default for axis marks) - display the mark only in facets that have empty space on the given side: either the margin, or an empty facet\n- *empty* - display the mark in empty facets only" + }, + "fill": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill" + }, + "fillOpacity": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill-opacity][1]; a constant number between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill-opacity" + }, + "filter": { + "$ref": "#/definitions/ChannelValue", + "description": "Applies a transform to filter the mark’s index according to the given channel values; only truthy values are retained.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "frameAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The frame anchor specifies defaults for **x** and **y** based on the plot’s frame; it may be one of the four sides (*top*, *right*, *bottom*, *left*), one of the four corners (*top-left*, *top-right*, *bottom-right*,\n*bottom-left*), or the *middle* of the frame. For example, for dots distributed horizontally at the top of the frame:\n\n```js Plot.dot(data, {x: \"date\", frameAnchor: \"top\"}) ```" + }, + "fx": { + "$ref": "#/definitions/ChannelValue", + "description": "The horizontal facet position channel, for mark-level faceting, bound to the *fx* scale." + }, + "fy": { + "$ref": "#/definitions/ChannelValue", + "description": "The vertical facet position channel, for mark-level faceting, bound to the\n*fy* scale." + }, + "href": { + "$ref": "#/definitions/ChannelValue", + "description": "The [href][1]; a channel specifying URLs for clickable links. May be used in conjunction with the **target** option to open links in another window.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/href" + }, + "imageFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A CSS [filter][1]; a constant string used to adjust the rendering of images, such as *blur(5px)*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/filter" + }, + "interval": { + "anyOf": [ + { + "$ref": "#/definitions/Interval" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "An interval (such as *day* or a number), to transform **x** values to the middle of the interval." + }, + "margin": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four mark margins: **marginTop**,\n**marginRight**, **marginBottom**, and **marginLeft**; typically defaults to 0, except for axis marks." + }, + "marginBottom": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s bottom margin; the minimum distance in pixels between the bottom edges of the inner and outer plot area." + }, + "marginLeft": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s left margin; the minimum distance in pixels between the left edges of the inner and outer plot area." + }, + "marginRight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s right margin; the minimum distance in pixels between the right edges of the mark’s inner and outer plot area." + }, + "marginTop": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s top margin; the minimum distance in pixels between the top edges of the inner and outer plot area." + }, + "mark": { + "const": "dotY", + "description": "Like dot, except that **y** defaults to the identity function, assuming that\n*data* = [*y₀*, *y₁*, *y₂*, …].\n\nIf an **interval** is specified, such as *day*, **x** is transformed to the middle of the interval.", + "type": "string" + }, + "meta": { + "$ref": "#/definitions/Meta", + "description": "Specification metadata." + }, + "mixBlendMode": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [mix-blend-mode][1]; a constant string specifying how to blend content such as *multiply*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode" + }, + "opacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally. For faster rendering, prefer the **strokeOpacity** or **fillOpacity** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/opacity" + }, + "paintOrder": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [paint-order][1]; a constant string specifying the order in which the\n**fill**, **stroke**, and any markers are drawn; defaults to *normal*, which draws the fill, then stroke, then markers; defaults to *stroke* for the text mark to create a “halo” around text to improve legibility.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/paint-order" + }, + "params": { + "$ref": "#/definitions/Params", + "description": "Param and Selection definitions." + }, + "plotDefaults": { + "$ref": "#/definitions/PlotAttributes", + "description": "A default set of attributes to apply to all plot components." + }, + "pointerEvents": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [pointer-events][1] property; a constant string such as *none*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/pointer-events" + }, + "r": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The radius of dots; either a channel or constant. When a number, it is interpreted as a constant radius in pixels. Otherwise it is interpreted as a channel, typically bound to the *r* channel, which defaults to the *sqrt* type for proportional symbols. The radius defaults to 4.5 pixels when using the **symbol** channel, and otherwise 3 pixels. Dots with a nonpositive radius are not drawn." + }, + "reverse": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Applies a transform to reverse the order of the mark’s index, say for reverse input order." + }, + "rotate": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The rotation angle of dots in degrees clockwise; either a channel or a constant. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel. Defaults to 0°, pointing up." + }, + "select": { + "$ref": "#/definitions/SelectFilter", + "description": "Applies a filter transform after data is loaded to highlight selected values only. For example, `first` and `last` select the first or last values of series only (using the *z* channel to separate series). Meanwhile, `nearestX` and `nearestY` select the point nearest to the pointer along the *x* or *y* channel dimension. Unlike Mosaic selections, a mark level *select* is internal to the mark only, and does not populate a param or selection value to be shared across clients.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "shapeRendering": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [shape-rendering][1]; a constant string such as *crispEdges*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/shape-rendering" + }, + "sort": { + "anyOf": [ + { + "$ref": "#/definitions/SortOrder" + }, + { + "$ref": "#/definitions/ChannelDomainSort" + } + ], + "description": "Either applies a transform to sort the mark’s index by the specified channel values, or imputes ordinal scale domains from this mark’s channels.\n\nWhen imputing ordinal scale domains from channel values, the **sort** option is an object whose keys are ordinal scale names such as *x* or *fx*, and whose values are channel names such as *y*, *y1*, or *y2*. For example, to impute the *y* scale’s domain from the associated *x* channel values in ascending order:\n\n```js sort: {y: \"x\"} ```\n\nFor different sort options for different scales, replace the channel name with a *value* object and per-scale options:\n\n```js sort: {y: {value: \"-x\"}} ```\n\nWhen sorting the mark’s index, the **sort** option is instead one of:\n\n- a channel value definition for sorting given values in ascending order\n- a {value, order} object for sorting given values\n- a {channel, order} object for sorting the named channel’s values" + }, + "stroke": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke" + }, + "strokeDasharray": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dasharray][1]; a constant number indicating the length in pixels of alternating dashes and gaps, or a constant string of numbers separated by spaces or commas (_e.g._, *10 2* for dashes of 10 pixels separated by gaps of 2 pixels), or *none* (the default) for no dashing\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dasharray" + }, + "strokeDashoffset": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dashoffset][1]; a constant indicating the offset in pixels of the first dash along the stroke; defaults to zero.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dashoffset" + }, + "strokeLinecap": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linecap][1]; a constant specifying how to cap stroked paths, such as *butt*, *round*, or *square*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linecap" + }, + "strokeLinejoin": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linejoin][1]; a constant specifying how to join stroked paths, such as *bevel*, *miter*, *miter-clip*, or *round*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linejoin" + }, + "strokeMiterlimit": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-miterlimit][1]; a constant number specifying how to limit the length of *miter* joins on stroked paths.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-miterlimit" + }, + "strokeOpacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-opacity" + }, + "strokeWidth": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-width][1]; a constant number in pixels, or a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-width" + }, + "symbol": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/SymbolType" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The categorical symbol; either a channel or a constant. A constant symbol can be specified by a valid symbol name such as *star*, or a symbol object (implementing the draw method); otherwise it is interpreted as a channel. Defaults to *circle* for the **dot** mark, and *hexagon* for the\n**hexagon** mark.\n\nIf the **symbol** channel’s values are all symbols, symbol names, or nullish, the channel is unscaled (values are interpreted literally); otherwise, the channel is bound to the *symbol* scale." + }, + "target": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [target][1]; a constant string specifying the target window (_e.g._,\n*_blank*) for clickable links; used in conjunction with the **href** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/target" + }, + "tip": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/TipPointer" + }, + { + "properties": { + "anchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The tip anchor specifies how to orient the tip box relative to its anchor position; it refers to the part of the tip box that is attached to the anchor point. For example, the *top-left* anchor places the top-left corner of tip box near the anchor position, hence placing the tip box below and to the right of the anchor position." + }, + "fontFamily": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font-family][1]; a constant; defaults to the plot’s font family, which is typically [*system-ui*][2].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-family [2]: https://drafts.csswg.org/css-fonts-4/#valdef-font-family-system-ui" + }, + "fontSize": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font size][1] in pixels; either a constant or a channel; defaults to the plot’s font size, which is typically 10. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-size" + }, + "fontStyle": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font style][1]; a constant; defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-style" + }, + "fontVariant": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font variant][1]; a constant; if the **text** channel contains numbers or dates, defaults to *tabular-nums* to facilitate comparing numbers; otherwise defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant" + }, + "fontWeight": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font weight][1]; a constant; defaults to the plot’s font weight, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight" + }, + "format": { + "additionalProperties": false, + "description": "How channel values are formatted for display. If a format is a string, it is interpreted as a (UTC) time format for temporal channels, and otherwise a number format.", + "properties": { + "ariaLabel": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fill": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fillOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fontSize": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fx": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fy": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "geometry": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "height": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "href": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "length": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "opacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "path": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "r": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "rotate": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "src": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "stroke": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeWidth": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "symbol": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "text": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "title": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "weight": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "width": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "z": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + } + }, + "type": "object" + }, + "frameAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The frame anchor specifies defaults for **x** and **y** based on the plot’s frame; it may be one of the four sides (*top*, *right*, *bottom*, *left*), one of the four corners (*top-left*, *top-right*, *bottom-right*,\n*bottom-left*), or the *middle* of the frame. For example, for tips distributed horizontally at the top of the frame:\n\n```js Plot.tip(data, {x: \"date\", frameAnchor: \"top\"}) ```" + }, + "lineHeight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line height in ems; defaults to 1. The line height affects the (typically vertical) separation between adjacent baselines of text, as well as the separation between the text and its anchor point." + }, + "lineWidth": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line width in ems (e.g., 10 for about 20 characters); defaults to infinity, disabling wrapping and clipping.\n\nIf **textOverflow** is null, lines will be wrapped at the specified length. If a line is split at a soft hyphen (\\xad), a hyphen (-) will be displayed at the end of the line. If **textOverflow** is not null, lines will be clipped according to the given strategy." + }, + "monospace": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, changes the default **fontFamily** to *monospace*, and uses simplified monospaced text metrics calculations." + }, + "pathFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The image filter for the tip’s box; defaults to a drop shadow." + }, + "pointer": { + "$ref": "#/definitions/TipPointer" + }, + "pointerSize": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The size of the tip’s pointer in pixels; defaults to 12." + }, + "preferredAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If an explicit tip anchor is not specified, an anchor is chosen automatically such that the tip fits within the plot’s frame; if the preferred anchor fits, it is chosen." + }, + "textAnchor": { + "anyOf": [ + { + "const": "start", + "type": "string" + }, + { + "const": "middle", + "type": "string" + }, + { + "const": "end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [text anchor][1] controls how text is aligned (typically horizontally) relative to its anchor point; it is one of *start*, *end*, or *middle*. If the frame anchor is *left*, *top-left*, or *bottom-left*, the default text anchor is *start*; if the frame anchor is *right*, *top-right*, or\n*bottom-right*, the default is *end*; otherwise it is *middle*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/text-anchor" + }, + "textOverflow": { + "anyOf": [ + { + "type": "null" + }, + { + "const": "clip", + "type": "string" + }, + { + "const": "ellipsis", + "type": "string" + }, + { + "const": "clip-start", + "type": "string" + }, + { + "const": "clip-end", + "type": "string" + }, + { + "const": "ellipsis-start", + "type": "string" + }, + { + "const": "ellipsis-middle", + "type": "string" + }, + { + "const": "ellipsis-end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How truncate (or wrap) lines of text longer than the given **lineWidth**; one of:\n\n- null (default) - preserve overflowing characters (and wrap if needed)\n- *clip* or *clip-end* - remove characters from the end\n- *clip-start* - remove characters from the start\n- *ellipsis* or *ellipsis-end* - replace characters from the end with an ellipsis (…)\n- *ellipsis-start* - replace characters from the start with an ellipsis (…)\n- *ellipsis-middle* - replace characters from the middle with an ellipsis (…)\n\nIf no **title** was specified, if text requires truncation, a title containing the non-truncated text will be implicitly added." + }, + "textPadding": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The padding around the text in pixels; defaults to 8." + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + } + }, + "type": "object" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to generate a tooltip for this mark, and any tip options." + }, + "title": { + "$ref": "#/definitions/ChannelValue", + "description": "The title; a channel specifying accessible, short textual descriptions as strings (possibly with newlines). If the tip option is specified, the title will be displayed with an interactive tooltip instead of using the SVG [title element][1].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/title" + }, + "x": { + "$ref": "#/definitions/ChannelValueIntervalSpec", + "description": "The horizontal position of the dot’s center, typically bound to the *x* scale." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel specifying the dot’s center, typically bound to the *y* scale." + }, + "z": { + "$ref": "#/definitions/ChannelValue", + "description": "An optional ordinal channel for grouping data into series." + } + }, + "required": [ + "data", + "mark" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "$schema": { + "description": "A [JSON schema](http://json-schema.org/) URL for this specification, such as https://uwdata.github.io/mosaic/schema/latest.json. This property enables validation and autocomplete in editors with JSON schema support.", + "format": "uri", + "type": "string" + }, + "ariaDescription": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-description][1]; a constant textual description.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-description" + }, + "ariaHidden": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-hidden][1] state; a constant indicating whether the element is exposed to an accessibility API.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-hidden" + }, + "ariaLabel": { + "$ref": "#/definitions/ChannelValue", + "description": "The [aria-label][1]; a channel specifying short textual labels representing the value in the accessibility tree.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-label" + }, + "clip": { + "anyOf": [ + { + "const": "frame", + "type": "string" + }, + { + "const": "sphere", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to clip the mark; one of:\n\n- *frame* or true - clip to the plot’s frame (inner area)\n- *sphere* - clip to the projected sphere (*e.g.*, front hemisphere)\n- null or false - do not clip\n\nThe *sphere* clip option requires a geographic projection." + }, + "config": { + "$ref": "#/definitions/Config", + "description": "Configuration options." + }, + "data": { + "$ref": "#/definitions/Data", + "description": "Dataset definitions." + }, + "dx": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The horizontal offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "dy": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The vertical offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "facet": { + "anyOf": [ + { + "const": "auto", + "type": "string" + }, + { + "const": "include", + "type": "string" + }, + { + "const": "exclude", + "type": "string" + }, + { + "const": "super", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to enable or disable faceting; one of:\n\n- *auto* (default) - automatically determine if this mark should be faceted\n- *include* (or true) - draw the subset of the mark’s data in the current facet\n- *exclude* - draw the subset of the mark’s data *not* in the current facet\n- *super* - draw this mark in a single frame that covers all facets\n- null (or false) - repeat this mark’s data across all facets (*i.e.*, no faceting)\n\nWhen a mark uses *super* faceting, it is not allowed to use position scales (*x*, *y*, *fx*, or *fy*); *super* faceting is intended for decorations, such as labels and legends.\n\nWhen top-level faceting is used, the default *auto* setting is equivalent to *include* when the mark data is strictly equal to the top-level facet data; otherwise it is equivalent to null. When the *include* or *exclude* facet mode is chosen, the mark data must be parallel to the top-level facet data: the data must have the same length and order. If the data are not parallel, then the wrong data may be shown in each facet. The default\n*auto* therefore requires strict equality (`===`) for safety, and using the facet data as mark data is recommended when using the *exclude* facet mode. (To construct parallel data safely, consider using [*array*.map][1] on the facet data.)\n\nWhen mark-level faceting is used, the default *auto* setting is equivalent to *include*: the mark will be faceted if either the **fx** or **fy** channel option (or both) is specified. The null or false option will disable faceting, while *exclude* draws the subset of the mark’s data *not* in the current facet.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map" + }, + "facetAnchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "right", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "const": "left", + "type": "string" + }, + { + "const": "top-left", + "type": "string" + }, + { + "const": "top-right", + "type": "string" + }, + { + "const": "bottom-left", + "type": "string" + }, + { + "const": "bottom-right", + "type": "string" + }, + { + "const": "top-empty", + "type": "string" + }, + { + "const": "right-empty", + "type": "string" + }, + { + "const": "bottom-empty", + "type": "string" + }, + { + "const": "left-empty", + "type": "string" + }, + { + "const": "empty", + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to place the mark with respect to facets; one of:\n\n- null (default for most marks) - display the mark in each non-empty facet\n- *top*, *right*, *bottom*, or *left* - display the mark only in facets on the given side\n- *top-empty*, *right-empty*, *bottom-empty*, or *left-empty* (default for axis marks) - display the mark only in facets that have empty space on the given side: either the margin, or an empty facet\n- *empty* - display the mark in empty facets only" + }, + "fill": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill" + }, + "fillOpacity": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill-opacity][1]; a constant number between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill-opacity" + }, + "filter": { + "$ref": "#/definitions/ChannelValue", + "description": "Applies a transform to filter the mark’s index according to the given channel values; only truthy values are retained.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "frameAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The frame anchor specifies defaults for **x** and **y** based on the plot’s frame; it may be one of the four sides (*top*, *right*, *bottom*, *left*), one of the four corners (*top-left*, *top-right*, *bottom-right*,\n*bottom-left*), or the *middle* of the frame. For example, for dots distributed horizontally at the top of the frame:\n\n```js Plot.dot(data, {x: \"date\", frameAnchor: \"top\"}) ```" + }, + "fx": { + "$ref": "#/definitions/ChannelValue", + "description": "The horizontal facet position channel, for mark-level faceting, bound to the *fx* scale." + }, + "fy": { + "$ref": "#/definitions/ChannelValue", + "description": "The vertical facet position channel, for mark-level faceting, bound to the\n*fy* scale." + }, + "href": { + "$ref": "#/definitions/ChannelValue", + "description": "The [href][1]; a channel specifying URLs for clickable links. May be used in conjunction with the **target** option to open links in another window.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/href" + }, + "imageFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A CSS [filter][1]; a constant string used to adjust the rendering of images, such as *blur(5px)*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/filter" + }, + "margin": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four mark margins: **marginTop**,\n**marginRight**, **marginBottom**, and **marginLeft**; typically defaults to 0, except for axis marks." + }, + "marginBottom": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s bottom margin; the minimum distance in pixels between the bottom edges of the inner and outer plot area." + }, + "marginLeft": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s left margin; the minimum distance in pixels between the left edges of the inner and outer plot area." + }, + "marginRight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s right margin; the minimum distance in pixels between the right edges of the mark’s inner and outer plot area." + }, + "marginTop": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s top margin; the minimum distance in pixels between the top edges of the inner and outer plot area." + }, + "mark": { + "const": "circle", + "description": "Like dot, except that the **symbol** option is set to *circle*.", + "type": "string" + }, + "meta": { + "$ref": "#/definitions/Meta", + "description": "Specification metadata." + }, + "mixBlendMode": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [mix-blend-mode][1]; a constant string specifying how to blend content such as *multiply*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode" + }, + "opacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally. For faster rendering, prefer the **strokeOpacity** or **fillOpacity** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/opacity" + }, + "paintOrder": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [paint-order][1]; a constant string specifying the order in which the\n**fill**, **stroke**, and any markers are drawn; defaults to *normal*, which draws the fill, then stroke, then markers; defaults to *stroke* for the text mark to create a “halo” around text to improve legibility.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/paint-order" + }, + "params": { + "$ref": "#/definitions/Params", + "description": "Param and Selection definitions." + }, + "plotDefaults": { + "$ref": "#/definitions/PlotAttributes", + "description": "A default set of attributes to apply to all plot components." + }, + "pointerEvents": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [pointer-events][1] property; a constant string such as *none*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/pointer-events" + }, + "r": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The radius of dots; either a channel or constant. When a number, it is interpreted as a constant radius in pixels. Otherwise it is interpreted as a channel, typically bound to the *r* channel, which defaults to the *sqrt* type for proportional symbols. The radius defaults to 4.5 pixels when using the **symbol** channel, and otherwise 3 pixels. Dots with a nonpositive radius are not drawn." + }, + "reverse": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Applies a transform to reverse the order of the mark’s index, say for reverse input order." + }, + "rotate": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The rotation angle of dots in degrees clockwise; either a channel or a constant. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel. Defaults to 0°, pointing up." + }, + "select": { + "$ref": "#/definitions/SelectFilter", + "description": "Applies a filter transform after data is loaded to highlight selected values only. For example, `first` and `last` select the first or last values of series only (using the *z* channel to separate series). Meanwhile, `nearestX` and `nearestY` select the point nearest to the pointer along the *x* or *y* channel dimension. Unlike Mosaic selections, a mark level *select* is internal to the mark only, and does not populate a param or selection value to be shared across clients.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "shapeRendering": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [shape-rendering][1]; a constant string such as *crispEdges*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/shape-rendering" + }, + "sort": { + "anyOf": [ + { + "$ref": "#/definitions/SortOrder" + }, + { + "$ref": "#/definitions/ChannelDomainSort" + } + ], + "description": "Either applies a transform to sort the mark’s index by the specified channel values, or imputes ordinal scale domains from this mark’s channels.\n\nWhen imputing ordinal scale domains from channel values, the **sort** option is an object whose keys are ordinal scale names such as *x* or *fx*, and whose values are channel names such as *y*, *y1*, or *y2*. For example, to impute the *y* scale’s domain from the associated *x* channel values in ascending order:\n\n```js sort: {y: \"x\"} ```\n\nFor different sort options for different scales, replace the channel name with a *value* object and per-scale options:\n\n```js sort: {y: {value: \"-x\"}} ```\n\nWhen sorting the mark’s index, the **sort** option is instead one of:\n\n- a channel value definition for sorting given values in ascending order\n- a {value, order} object for sorting given values\n- a {channel, order} object for sorting the named channel’s values" + }, + "stroke": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke" + }, + "strokeDasharray": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dasharray][1]; a constant number indicating the length in pixels of alternating dashes and gaps, or a constant string of numbers separated by spaces or commas (_e.g._, *10 2* for dashes of 10 pixels separated by gaps of 2 pixels), or *none* (the default) for no dashing\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dasharray" + }, + "strokeDashoffset": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dashoffset][1]; a constant indicating the offset in pixels of the first dash along the stroke; defaults to zero.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dashoffset" + }, + "strokeLinecap": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linecap][1]; a constant specifying how to cap stroked paths, such as *butt*, *round*, or *square*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linecap" + }, + "strokeLinejoin": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linejoin][1]; a constant specifying how to join stroked paths, such as *bevel*, *miter*, *miter-clip*, or *round*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linejoin" + }, + "strokeMiterlimit": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-miterlimit][1]; a constant number specifying how to limit the length of *miter* joins on stroked paths.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-miterlimit" + }, + "strokeOpacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-opacity" + }, + "strokeWidth": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-width][1]; a constant number in pixels, or a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-width" + }, + "symbol": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/SymbolType" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The categorical symbol; either a channel or a constant. A constant symbol can be specified by a valid symbol name such as *star*, or a symbol object (implementing the draw method); otherwise it is interpreted as a channel. Defaults to *circle* for the **dot** mark, and *hexagon* for the\n**hexagon** mark.\n\nIf the **symbol** channel’s values are all symbols, symbol names, or nullish, the channel is unscaled (values are interpreted literally); otherwise, the channel is bound to the *symbol* scale." + }, + "target": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [target][1]; a constant string specifying the target window (_e.g._,\n*_blank*) for clickable links; used in conjunction with the **href** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/target" + }, + "tip": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/TipPointer" + }, + { + "properties": { + "anchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The tip anchor specifies how to orient the tip box relative to its anchor position; it refers to the part of the tip box that is attached to the anchor point. For example, the *top-left* anchor places the top-left corner of tip box near the anchor position, hence placing the tip box below and to the right of the anchor position." + }, + "fontFamily": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font-family][1]; a constant; defaults to the plot’s font family, which is typically [*system-ui*][2].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-family [2]: https://drafts.csswg.org/css-fonts-4/#valdef-font-family-system-ui" + }, + "fontSize": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font size][1] in pixels; either a constant or a channel; defaults to the plot’s font size, which is typically 10. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-size" + }, + "fontStyle": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font style][1]; a constant; defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-style" + }, + "fontVariant": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font variant][1]; a constant; if the **text** channel contains numbers or dates, defaults to *tabular-nums* to facilitate comparing numbers; otherwise defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant" + }, + "fontWeight": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font weight][1]; a constant; defaults to the plot’s font weight, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight" + }, + "format": { + "additionalProperties": false, + "description": "How channel values are formatted for display. If a format is a string, it is interpreted as a (UTC) time format for temporal channels, and otherwise a number format.", + "properties": { + "ariaLabel": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fill": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fillOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fontSize": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fx": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fy": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "geometry": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "height": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "href": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "length": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "opacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "path": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "r": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "rotate": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "src": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "stroke": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeWidth": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "symbol": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "text": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "title": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "weight": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "width": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "z": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + } + }, + "type": "object" + }, + "frameAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The frame anchor specifies defaults for **x** and **y** based on the plot’s frame; it may be one of the four sides (*top*, *right*, *bottom*, *left*), one of the four corners (*top-left*, *top-right*, *bottom-right*,\n*bottom-left*), or the *middle* of the frame. For example, for tips distributed horizontally at the top of the frame:\n\n```js Plot.tip(data, {x: \"date\", frameAnchor: \"top\"}) ```" + }, + "lineHeight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line height in ems; defaults to 1. The line height affects the (typically vertical) separation between adjacent baselines of text, as well as the separation between the text and its anchor point." + }, + "lineWidth": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line width in ems (e.g., 10 for about 20 characters); defaults to infinity, disabling wrapping and clipping.\n\nIf **textOverflow** is null, lines will be wrapped at the specified length. If a line is split at a soft hyphen (\\xad), a hyphen (-) will be displayed at the end of the line. If **textOverflow** is not null, lines will be clipped according to the given strategy." + }, + "monospace": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, changes the default **fontFamily** to *monospace*, and uses simplified monospaced text metrics calculations." + }, + "pathFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The image filter for the tip’s box; defaults to a drop shadow." + }, + "pointer": { + "$ref": "#/definitions/TipPointer" + }, + "pointerSize": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The size of the tip’s pointer in pixels; defaults to 12." + }, + "preferredAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If an explicit tip anchor is not specified, an anchor is chosen automatically such that the tip fits within the plot’s frame; if the preferred anchor fits, it is chosen." + }, + "textAnchor": { + "anyOf": [ + { + "const": "start", + "type": "string" + }, + { + "const": "middle", + "type": "string" + }, + { + "const": "end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [text anchor][1] controls how text is aligned (typically horizontally) relative to its anchor point; it is one of *start*, *end*, or *middle*. If the frame anchor is *left*, *top-left*, or *bottom-left*, the default text anchor is *start*; if the frame anchor is *right*, *top-right*, or\n*bottom-right*, the default is *end*; otherwise it is *middle*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/text-anchor" + }, + "textOverflow": { + "anyOf": [ + { + "type": "null" + }, + { + "const": "clip", + "type": "string" + }, + { + "const": "ellipsis", + "type": "string" + }, + { + "const": "clip-start", + "type": "string" + }, + { + "const": "clip-end", + "type": "string" + }, + { + "const": "ellipsis-start", + "type": "string" + }, + { + "const": "ellipsis-middle", + "type": "string" + }, + { + "const": "ellipsis-end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How truncate (or wrap) lines of text longer than the given **lineWidth**; one of:\n\n- null (default) - preserve overflowing characters (and wrap if needed)\n- *clip* or *clip-end* - remove characters from the end\n- *clip-start* - remove characters from the start\n- *ellipsis* or *ellipsis-end* - replace characters from the end with an ellipsis (…)\n- *ellipsis-start* - replace characters from the start with an ellipsis (…)\n- *ellipsis-middle* - replace characters from the middle with an ellipsis (…)\n\nIf no **title** was specified, if text requires truncation, a title containing the non-truncated text will be implicitly added." + }, + "textPadding": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The padding around the text in pixels; defaults to 8." + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + } + }, + "type": "object" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to generate a tooltip for this mark, and any tip options." + }, + "title": { + "$ref": "#/definitions/ChannelValue", + "description": "The title; a channel specifying accessible, short textual descriptions as strings (possibly with newlines). If the tip option is specified, the title will be displayed with an interactive tooltip instead of using the SVG [title element][1].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/title" + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel specifying the dot’s center, typically bound to the *x* scale." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel specifying the dot’s center, typically bound to the *y* scale." + }, + "z": { + "$ref": "#/definitions/ChannelValue", + "description": "An optional ordinal channel for grouping data into series." + } + }, + "required": [ + "data", + "mark" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "$schema": { + "description": "A [JSON schema](http://json-schema.org/) URL for this specification, such as https://uwdata.github.io/mosaic/schema/latest.json. This property enables validation and autocomplete in editors with JSON schema support.", + "format": "uri", + "type": "string" + }, + "ariaDescription": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-description][1]; a constant textual description.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-description" + }, + "ariaHidden": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-hidden][1] state; a constant indicating whether the element is exposed to an accessibility API.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-hidden" + }, + "ariaLabel": { + "$ref": "#/definitions/ChannelValue", + "description": "The [aria-label][1]; a channel specifying short textual labels representing the value in the accessibility tree.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-label" + }, + "clip": { + "anyOf": [ + { + "const": "frame", + "type": "string" + }, + { + "const": "sphere", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to clip the mark; one of:\n\n- *frame* or true - clip to the plot’s frame (inner area)\n- *sphere* - clip to the projected sphere (*e.g.*, front hemisphere)\n- null or false - do not clip\n\nThe *sphere* clip option requires a geographic projection." + }, + "config": { + "$ref": "#/definitions/Config", + "description": "Configuration options." + }, + "data": { + "$ref": "#/definitions/Data", + "description": "Dataset definitions." + }, + "dx": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The horizontal offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "dy": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The vertical offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "facet": { + "anyOf": [ + { + "const": "auto", + "type": "string" + }, + { + "const": "include", + "type": "string" + }, + { + "const": "exclude", + "type": "string" + }, + { + "const": "super", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to enable or disable faceting; one of:\n\n- *auto* (default) - automatically determine if this mark should be faceted\n- *include* (or true) - draw the subset of the mark’s data in the current facet\n- *exclude* - draw the subset of the mark’s data *not* in the current facet\n- *super* - draw this mark in a single frame that covers all facets\n- null (or false) - repeat this mark’s data across all facets (*i.e.*, no faceting)\n\nWhen a mark uses *super* faceting, it is not allowed to use position scales (*x*, *y*, *fx*, or *fy*); *super* faceting is intended for decorations, such as labels and legends.\n\nWhen top-level faceting is used, the default *auto* setting is equivalent to *include* when the mark data is strictly equal to the top-level facet data; otherwise it is equivalent to null. When the *include* or *exclude* facet mode is chosen, the mark data must be parallel to the top-level facet data: the data must have the same length and order. If the data are not parallel, then the wrong data may be shown in each facet. The default\n*auto* therefore requires strict equality (`===`) for safety, and using the facet data as mark data is recommended when using the *exclude* facet mode. (To construct parallel data safely, consider using [*array*.map][1] on the facet data.)\n\nWhen mark-level faceting is used, the default *auto* setting is equivalent to *include*: the mark will be faceted if either the **fx** or **fy** channel option (or both) is specified. The null or false option will disable faceting, while *exclude* draws the subset of the mark’s data *not* in the current facet.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map" + }, + "facetAnchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "right", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "const": "left", + "type": "string" + }, + { + "const": "top-left", + "type": "string" + }, + { + "const": "top-right", + "type": "string" + }, + { + "const": "bottom-left", + "type": "string" + }, + { + "const": "bottom-right", + "type": "string" + }, + { + "const": "top-empty", + "type": "string" + }, + { + "const": "right-empty", + "type": "string" + }, + { + "const": "bottom-empty", + "type": "string" + }, + { + "const": "left-empty", + "type": "string" + }, + { + "const": "empty", + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to place the mark with respect to facets; one of:\n\n- null (default for most marks) - display the mark in each non-empty facet\n- *top*, *right*, *bottom*, or *left* - display the mark only in facets on the given side\n- *top-empty*, *right-empty*, *bottom-empty*, or *left-empty* (default for axis marks) - display the mark only in facets that have empty space on the given side: either the margin, or an empty facet\n- *empty* - display the mark in empty facets only" + }, + "fill": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill" + }, + "fillOpacity": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill-opacity][1]; a constant number between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill-opacity" + }, + "filter": { + "$ref": "#/definitions/ChannelValue", + "description": "Applies a transform to filter the mark’s index according to the given channel values; only truthy values are retained.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "frameAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The frame anchor specifies defaults for **x** and **y** based on the plot’s frame; it may be one of the four sides (*top*, *right*, *bottom*, *left*), one of the four corners (*top-left*, *top-right*, *bottom-right*,\n*bottom-left*), or the *middle* of the frame. For example, for dots distributed horizontally at the top of the frame:\n\n```js Plot.dot(data, {x: \"date\", frameAnchor: \"top\"}) ```" + }, + "fx": { + "$ref": "#/definitions/ChannelValue", + "description": "The horizontal facet position channel, for mark-level faceting, bound to the *fx* scale." + }, + "fy": { + "$ref": "#/definitions/ChannelValue", + "description": "The vertical facet position channel, for mark-level faceting, bound to the\n*fy* scale." + }, + "href": { + "$ref": "#/definitions/ChannelValue", + "description": "The [href][1]; a channel specifying URLs for clickable links. May be used in conjunction with the **target** option to open links in another window.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/href" + }, + "imageFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A CSS [filter][1]; a constant string used to adjust the rendering of images, such as *blur(5px)*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/filter" + }, + "margin": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four mark margins: **marginTop**,\n**marginRight**, **marginBottom**, and **marginLeft**; typically defaults to 0, except for axis marks." + }, + "marginBottom": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s bottom margin; the minimum distance in pixels between the bottom edges of the inner and outer plot area." + }, + "marginLeft": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s left margin; the minimum distance in pixels between the left edges of the inner and outer plot area." + }, + "marginRight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s right margin; the minimum distance in pixels between the right edges of the mark’s inner and outer plot area." + }, + "marginTop": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s top margin; the minimum distance in pixels between the top edges of the inner and outer plot area." + }, + "mark": { + "const": "hexagon", + "description": "Like dot, except that the **symbol** option is set to *hexagon*.", + "type": "string" + }, + "meta": { + "$ref": "#/definitions/Meta", + "description": "Specification metadata." + }, + "mixBlendMode": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [mix-blend-mode][1]; a constant string specifying how to blend content such as *multiply*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode" + }, + "opacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally. For faster rendering, prefer the **strokeOpacity** or **fillOpacity** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/opacity" + }, + "paintOrder": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [paint-order][1]; a constant string specifying the order in which the\n**fill**, **stroke**, and any markers are drawn; defaults to *normal*, which draws the fill, then stroke, then markers; defaults to *stroke* for the text mark to create a “halo” around text to improve legibility.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/paint-order" + }, + "params": { + "$ref": "#/definitions/Params", + "description": "Param and Selection definitions." + }, + "plotDefaults": { + "$ref": "#/definitions/PlotAttributes", + "description": "A default set of attributes to apply to all plot components." + }, + "pointerEvents": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [pointer-events][1] property; a constant string such as *none*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/pointer-events" + }, + "r": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The radius of dots; either a channel or constant. When a number, it is interpreted as a constant radius in pixels. Otherwise it is interpreted as a channel, typically bound to the *r* channel, which defaults to the *sqrt* type for proportional symbols. The radius defaults to 4.5 pixels when using the **symbol** channel, and otherwise 3 pixels. Dots with a nonpositive radius are not drawn." + }, + "reverse": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Applies a transform to reverse the order of the mark’s index, say for reverse input order." + }, + "rotate": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The rotation angle of dots in degrees clockwise; either a channel or a constant. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel. Defaults to 0°, pointing up." + }, + "select": { + "$ref": "#/definitions/SelectFilter", + "description": "Applies a filter transform after data is loaded to highlight selected values only. For example, `first` and `last` select the first or last values of series only (using the *z* channel to separate series). Meanwhile, `nearestX` and `nearestY` select the point nearest to the pointer along the *x* or *y* channel dimension. Unlike Mosaic selections, a mark level *select* is internal to the mark only, and does not populate a param or selection value to be shared across clients.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "shapeRendering": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [shape-rendering][1]; a constant string such as *crispEdges*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/shape-rendering" + }, + "sort": { + "anyOf": [ + { + "$ref": "#/definitions/SortOrder" + }, + { + "$ref": "#/definitions/ChannelDomainSort" + } + ], + "description": "Either applies a transform to sort the mark’s index by the specified channel values, or imputes ordinal scale domains from this mark’s channels.\n\nWhen imputing ordinal scale domains from channel values, the **sort** option is an object whose keys are ordinal scale names such as *x* or *fx*, and whose values are channel names such as *y*, *y1*, or *y2*. For example, to impute the *y* scale’s domain from the associated *x* channel values in ascending order:\n\n```js sort: {y: \"x\"} ```\n\nFor different sort options for different scales, replace the channel name with a *value* object and per-scale options:\n\n```js sort: {y: {value: \"-x\"}} ```\n\nWhen sorting the mark’s index, the **sort** option is instead one of:\n\n- a channel value definition for sorting given values in ascending order\n- a {value, order} object for sorting given values\n- a {channel, order} object for sorting the named channel’s values" + }, + "stroke": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke" + }, + "strokeDasharray": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dasharray][1]; a constant number indicating the length in pixels of alternating dashes and gaps, or a constant string of numbers separated by spaces or commas (_e.g._, *10 2* for dashes of 10 pixels separated by gaps of 2 pixels), or *none* (the default) for no dashing\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dasharray" + }, + "strokeDashoffset": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dashoffset][1]; a constant indicating the offset in pixels of the first dash along the stroke; defaults to zero.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dashoffset" + }, + "strokeLinecap": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linecap][1]; a constant specifying how to cap stroked paths, such as *butt*, *round*, or *square*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linecap" + }, + "strokeLinejoin": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linejoin][1]; a constant specifying how to join stroked paths, such as *bevel*, *miter*, *miter-clip*, or *round*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linejoin" + }, + "strokeMiterlimit": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-miterlimit][1]; a constant number specifying how to limit the length of *miter* joins on stroked paths.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-miterlimit" + }, + "strokeOpacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-opacity" + }, + "strokeWidth": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-width][1]; a constant number in pixels, or a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-width" + }, + "symbol": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/SymbolType" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The categorical symbol; either a channel or a constant. A constant symbol can be specified by a valid symbol name such as *star*, or a symbol object (implementing the draw method); otherwise it is interpreted as a channel. Defaults to *circle* for the **dot** mark, and *hexagon* for the\n**hexagon** mark.\n\nIf the **symbol** channel’s values are all symbols, symbol names, or nullish, the channel is unscaled (values are interpreted literally); otherwise, the channel is bound to the *symbol* scale." + }, + "target": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [target][1]; a constant string specifying the target window (_e.g._,\n*_blank*) for clickable links; used in conjunction with the **href** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/target" + }, + "tip": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/TipPointer" + }, + { + "properties": { + "anchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The tip anchor specifies how to orient the tip box relative to its anchor position; it refers to the part of the tip box that is attached to the anchor point. For example, the *top-left* anchor places the top-left corner of tip box near the anchor position, hence placing the tip box below and to the right of the anchor position." + }, + "fontFamily": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font-family][1]; a constant; defaults to the plot’s font family, which is typically [*system-ui*][2].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-family [2]: https://drafts.csswg.org/css-fonts-4/#valdef-font-family-system-ui" + }, + "fontSize": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font size][1] in pixels; either a constant or a channel; defaults to the plot’s font size, which is typically 10. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-size" + }, + "fontStyle": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font style][1]; a constant; defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-style" + }, + "fontVariant": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font variant][1]; a constant; if the **text** channel contains numbers or dates, defaults to *tabular-nums* to facilitate comparing numbers; otherwise defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant" + }, + "fontWeight": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font weight][1]; a constant; defaults to the plot’s font weight, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight" + }, + "format": { + "additionalProperties": false, + "description": "How channel values are formatted for display. If a format is a string, it is interpreted as a (UTC) time format for temporal channels, and otherwise a number format.", + "properties": { + "ariaLabel": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fill": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fillOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fontSize": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fx": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fy": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "geometry": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "height": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "href": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "length": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "opacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "path": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "r": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "rotate": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "src": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "stroke": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeWidth": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "symbol": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "text": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "title": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "weight": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "width": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "z": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + } + }, + "type": "object" + }, + "frameAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The frame anchor specifies defaults for **x** and **y** based on the plot’s frame; it may be one of the four sides (*top*, *right*, *bottom*, *left*), one of the four corners (*top-left*, *top-right*, *bottom-right*,\n*bottom-left*), or the *middle* of the frame. For example, for tips distributed horizontally at the top of the frame:\n\n```js Plot.tip(data, {x: \"date\", frameAnchor: \"top\"}) ```" + }, + "lineHeight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line height in ems; defaults to 1. The line height affects the (typically vertical) separation between adjacent baselines of text, as well as the separation between the text and its anchor point." + }, + "lineWidth": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line width in ems (e.g., 10 for about 20 characters); defaults to infinity, disabling wrapping and clipping.\n\nIf **textOverflow** is null, lines will be wrapped at the specified length. If a line is split at a soft hyphen (\\xad), a hyphen (-) will be displayed at the end of the line. If **textOverflow** is not null, lines will be clipped according to the given strategy." + }, + "monospace": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, changes the default **fontFamily** to *monospace*, and uses simplified monospaced text metrics calculations." + }, + "pathFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The image filter for the tip’s box; defaults to a drop shadow." + }, + "pointer": { + "$ref": "#/definitions/TipPointer" + }, + "pointerSize": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The size of the tip’s pointer in pixels; defaults to 12." + }, + "preferredAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If an explicit tip anchor is not specified, an anchor is chosen automatically such that the tip fits within the plot’s frame; if the preferred anchor fits, it is chosen." + }, + "textAnchor": { + "anyOf": [ + { + "const": "start", + "type": "string" + }, + { + "const": "middle", + "type": "string" + }, + { + "const": "end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [text anchor][1] controls how text is aligned (typically horizontally) relative to its anchor point; it is one of *start*, *end*, or *middle*. If the frame anchor is *left*, *top-left*, or *bottom-left*, the default text anchor is *start*; if the frame anchor is *right*, *top-right*, or\n*bottom-right*, the default is *end*; otherwise it is *middle*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/text-anchor" + }, + "textOverflow": { + "anyOf": [ + { + "type": "null" + }, + { + "const": "clip", + "type": "string" + }, + { + "const": "ellipsis", + "type": "string" + }, + { + "const": "clip-start", + "type": "string" + }, + { + "const": "clip-end", + "type": "string" + }, + { + "const": "ellipsis-start", + "type": "string" + }, + { + "const": "ellipsis-middle", + "type": "string" + }, + { + "const": "ellipsis-end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How truncate (or wrap) lines of text longer than the given **lineWidth**; one of:\n\n- null (default) - preserve overflowing characters (and wrap if needed)\n- *clip* or *clip-end* - remove characters from the end\n- *clip-start* - remove characters from the start\n- *ellipsis* or *ellipsis-end* - replace characters from the end with an ellipsis (…)\n- *ellipsis-start* - replace characters from the start with an ellipsis (…)\n- *ellipsis-middle* - replace characters from the middle with an ellipsis (…)\n\nIf no **title** was specified, if text requires truncation, a title containing the non-truncated text will be implicitly added." + }, + "textPadding": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The padding around the text in pixels; defaults to 8." + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + } + }, + "type": "object" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to generate a tooltip for this mark, and any tip options." + }, + "title": { + "$ref": "#/definitions/ChannelValue", + "description": "The title; a channel specifying accessible, short textual descriptions as strings (possibly with newlines). If the tip option is specified, the title will be displayed with an interactive tooltip instead of using the SVG [title element][1].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/title" + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel specifying the dot’s center, typically bound to the *x* scale." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel specifying the dot’s center, typically bound to the *y* scale." + }, + "z": { + "$ref": "#/definitions/ChannelValue", + "description": "An optional ordinal channel for grouping data into series." + } + }, + "required": [ + "data", + "mark" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "$schema": { + "description": "A [JSON schema](http://json-schema.org/) URL for this specification, such as https://uwdata.github.io/mosaic/schema/latest.json. This property enables validation and autocomplete in editors with JSON schema support.", + "format": "uri", + "type": "string" + }, + "ariaDescription": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-description][1]; a constant textual description.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-description" + }, + "ariaHidden": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-hidden][1] state; a constant indicating whether the element is exposed to an accessibility API.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-hidden" + }, + "ariaLabel": { + "$ref": "#/definitions/ChannelValue", + "description": "The [aria-label][1]; a channel specifying short textual labels representing the value in the accessibility tree.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-label" + }, + "ci": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The confidence interval in (0, 1); defaults to 0.95." + }, + "clip": { + "anyOf": [ + { + "const": "frame", + "type": "string" + }, + { + "const": "sphere", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to clip the mark; one of:\n\n- *frame* or true - clip to the plot’s frame (inner area)\n- *sphere* - clip to the projected sphere (*e.g.*, front hemisphere)\n- null or false - do not clip\n\nThe *sphere* clip option requires a geographic projection." + }, + "config": { + "$ref": "#/definitions/Config", + "description": "Configuration options." + }, + "data": { + "$ref": "#/definitions/Data", + "description": "Dataset definitions." + }, + "dx": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The horizontal offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "dy": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The vertical offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "facet": { + "anyOf": [ + { + "const": "auto", + "type": "string" + }, + { + "const": "include", + "type": "string" + }, + { + "const": "exclude", + "type": "string" + }, + { + "const": "super", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to enable or disable faceting; one of:\n\n- *auto* (default) - automatically determine if this mark should be faceted\n- *include* (or true) - draw the subset of the mark’s data in the current facet\n- *exclude* - draw the subset of the mark’s data *not* in the current facet\n- *super* - draw this mark in a single frame that covers all facets\n- null (or false) - repeat this mark’s data across all facets (*i.e.*, no faceting)\n\nWhen a mark uses *super* faceting, it is not allowed to use position scales (*x*, *y*, *fx*, or *fy*); *super* faceting is intended for decorations, such as labels and legends.\n\nWhen top-level faceting is used, the default *auto* setting is equivalent to *include* when the mark data is strictly equal to the top-level facet data; otherwise it is equivalent to null. When the *include* or *exclude* facet mode is chosen, the mark data must be parallel to the top-level facet data: the data must have the same length and order. If the data are not parallel, then the wrong data may be shown in each facet. The default\n*auto* therefore requires strict equality (`===`) for safety, and using the facet data as mark data is recommended when using the *exclude* facet mode. (To construct parallel data safely, consider using [*array*.map][1] on the facet data.)\n\nWhen mark-level faceting is used, the default *auto* setting is equivalent to *include*: the mark will be faceted if either the **fx** or **fy** channel option (or both) is specified. The null or false option will disable faceting, while *exclude* draws the subset of the mark’s data *not* in the current facet.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map" + }, + "facetAnchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "right", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "const": "left", + "type": "string" + }, + { + "const": "top-left", + "type": "string" + }, + { + "const": "top-right", + "type": "string" + }, + { + "const": "bottom-left", + "type": "string" + }, + { + "const": "bottom-right", + "type": "string" + }, + { + "const": "top-empty", + "type": "string" + }, + { + "const": "right-empty", + "type": "string" + }, + { + "const": "bottom-empty", + "type": "string" + }, + { + "const": "left-empty", + "type": "string" + }, + { + "const": "empty", + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to place the mark with respect to facets; one of:\n\n- null (default for most marks) - display the mark in each non-empty facet\n- *top*, *right*, *bottom*, or *left* - display the mark only in facets on the given side\n- *top-empty*, *right-empty*, *bottom-empty*, or *left-empty* (default for axis marks) - display the mark only in facets that have empty space on the given side: either the margin, or an empty facet\n- *empty* - display the mark in empty facets only" + }, + "fill": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill" + }, + "fillOpacity": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill-opacity][1]; a constant number between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill-opacity" + }, + "filter": { + "$ref": "#/definitions/ChannelValue", + "description": "Applies a transform to filter the mark’s index according to the given channel values; only truthy values are retained.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "fx": { + "$ref": "#/definitions/ChannelValue", + "description": "The horizontal facet position channel, for mark-level faceting, bound to the *fx* scale." + }, + "fy": { + "$ref": "#/definitions/ChannelValue", + "description": "The vertical facet position channel, for mark-level faceting, bound to the\n*fy* scale." + }, + "href": { + "$ref": "#/definitions/ChannelValue", + "description": "The [href][1]; a channel specifying URLs for clickable links. May be used in conjunction with the **target** option to open links in another window.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/href" + }, + "imageFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A CSS [filter][1]; a constant string used to adjust the rendering of images, such as *blur(5px)*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/filter" + }, + "margin": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four mark margins: **marginTop**,\n**marginRight**, **marginBottom**, and **marginLeft**; typically defaults to 0, except for axis marks." + }, + "marginBottom": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s bottom margin; the minimum distance in pixels between the bottom edges of the inner and outer plot area." + }, + "marginLeft": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s left margin; the minimum distance in pixels between the left edges of the inner and outer plot area." + }, + "marginRight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s right margin; the minimum distance in pixels between the right edges of the mark’s inner and outer plot area." + }, + "marginTop": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s top margin; the minimum distance in pixels between the top edges of the inner and outer plot area." + }, + "mark": { + "const": "errorbarX", + "description": "A mark that draws error bars for a calculated parametric confidence interval for a dependent variable (*x*), potentially grouped by an independent variable (*y*).\n\nThis mark aggregates raw values to produce a [parametric confidence interval][1] of the mean, assuming a normal distribution. To instead visualize pre-computeted interval values or custom aggregations, use a **ruleY** mark with specified **x1** and **x2** channels.\n\nMultiple error bars can be produced by specifying a **z** or **stroke** channel. Set the **marker** option to `'tick'` to add small perpendicular lines at the start and end of the error interval.\n\n[1]: https://en.wikipedia.org/wiki/Normal_distribution#Confidence_intervals", + "type": "string" + }, + "marker": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for markerStart, markerMid, and markerEnd; one of:\n\n- a marker name such as *arrow* or *circle*\n- *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*" + }, + "markerEnd": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The marker for the ending point of a line segment; one of:\n\n- a marker name such as *arrow* or *circle*\n* *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*" + }, + "markerMid": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The marker for any middle (interior) points of a line segment. If the line segment only has a start and end point, this option has no effect. One of:\n\n- a marker name such as *arrow* or *circle*\n* *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*\n* a function - a custom marker function; see below" + }, + "markerStart": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The marker for the starting point of a line segment; one of:\n\n- a marker name such as *arrow* or *circle*\n* *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*" + }, + "meta": { + "$ref": "#/definitions/Meta", + "description": "Specification metadata." + }, + "mixBlendMode": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [mix-blend-mode][1]; a constant string specifying how to blend content such as *multiply*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode" + }, + "opacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally. For faster rendering, prefer the **strokeOpacity** or **fillOpacity** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/opacity" + }, + "paintOrder": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [paint-order][1]; a constant string specifying the order in which the\n**fill**, **stroke**, and any markers are drawn; defaults to *normal*, which draws the fill, then stroke, then markers; defaults to *stroke* for the text mark to create a “halo” around text to improve legibility.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/paint-order" + }, + "params": { + "$ref": "#/definitions/Params", + "description": "Param and Selection definitions." + }, + "plotDefaults": { + "$ref": "#/definitions/PlotAttributes", + "description": "A default set of attributes to apply to all plot components." + }, + "pointerEvents": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [pointer-events][1] property; a constant string such as *none*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/pointer-events" + }, + "reverse": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Applies a transform to reverse the order of the mark’s index, say for reverse input order." + }, + "select": { + "$ref": "#/definitions/SelectFilter", + "description": "Applies a filter transform after data is loaded to highlight selected values only. For example, `first` and `last` select the first or last values of series only (using the *z* channel to separate series). Meanwhile, `nearestX` and `nearestY` select the point nearest to the pointer along the *x* or *y* channel dimension. Unlike Mosaic selections, a mark level *select* is internal to the mark only, and does not populate a param or selection value to be shared across clients.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "shapeRendering": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [shape-rendering][1]; a constant string such as *crispEdges*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/shape-rendering" + }, + "sort": { + "anyOf": [ + { + "$ref": "#/definitions/SortOrder" + }, + { + "$ref": "#/definitions/ChannelDomainSort" + } + ], + "description": "Either applies a transform to sort the mark’s index by the specified channel values, or imputes ordinal scale domains from this mark’s channels.\n\nWhen imputing ordinal scale domains from channel values, the **sort** option is an object whose keys are ordinal scale names such as *x* or *fx*, and whose values are channel names such as *y*, *y1*, or *y2*. For example, to impute the *y* scale’s domain from the associated *x* channel values in ascending order:\n\n```js sort: {y: \"x\"} ```\n\nFor different sort options for different scales, replace the channel name with a *value* object and per-scale options:\n\n```js sort: {y: {value: \"-x\"}} ```\n\nWhen sorting the mark’s index, the **sort** option is instead one of:\n\n- a channel value definition for sorting given values in ascending order\n- a {value, order} object for sorting given values\n- a {channel, order} object for sorting the named channel’s values" + }, + "stroke": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke" + }, + "strokeDasharray": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dasharray][1]; a constant number indicating the length in pixels of alternating dashes and gaps, or a constant string of numbers separated by spaces or commas (_e.g._, *10 2* for dashes of 10 pixels separated by gaps of 2 pixels), or *none* (the default) for no dashing\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dasharray" + }, + "strokeDashoffset": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dashoffset][1]; a constant indicating the offset in pixels of the first dash along the stroke; defaults to zero.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dashoffset" + }, + "strokeLinecap": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linecap][1]; a constant specifying how to cap stroked paths, such as *butt*, *round*, or *square*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linecap" + }, + "strokeLinejoin": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linejoin][1]; a constant specifying how to join stroked paths, such as *bevel*, *miter*, *miter-clip*, or *round*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linejoin" + }, + "strokeMiterlimit": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-miterlimit][1]; a constant number specifying how to limit the length of *miter* joins on stroked paths.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-miterlimit" + }, + "strokeOpacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-opacity" + }, + "strokeWidth": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-width][1]; a constant number in pixels, or a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-width" + }, + "target": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [target][1]; a constant string specifying the target window (_e.g._,\n*_blank*) for clickable links; used in conjunction with the **href** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/target" + }, + "tip": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/TipPointer" + }, + { + "properties": { + "anchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The tip anchor specifies how to orient the tip box relative to its anchor position; it refers to the part of the tip box that is attached to the anchor point. For example, the *top-left* anchor places the top-left corner of tip box near the anchor position, hence placing the tip box below and to the right of the anchor position." + }, + "fontFamily": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font-family][1]; a constant; defaults to the plot’s font family, which is typically [*system-ui*][2].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-family [2]: https://drafts.csswg.org/css-fonts-4/#valdef-font-family-system-ui" + }, + "fontSize": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font size][1] in pixels; either a constant or a channel; defaults to the plot’s font size, which is typically 10. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-size" + }, + "fontStyle": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font style][1]; a constant; defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-style" + }, + "fontVariant": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font variant][1]; a constant; if the **text** channel contains numbers or dates, defaults to *tabular-nums* to facilitate comparing numbers; otherwise defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant" + }, + "fontWeight": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font weight][1]; a constant; defaults to the plot’s font weight, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight" + }, + "format": { + "additionalProperties": false, + "description": "How channel values are formatted for display. If a format is a string, it is interpreted as a (UTC) time format for temporal channels, and otherwise a number format.", + "properties": { + "ariaLabel": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fill": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fillOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fontSize": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fx": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fy": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "geometry": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "height": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "href": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "length": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "opacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "path": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "r": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "rotate": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "src": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "stroke": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeWidth": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "symbol": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "text": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "title": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "weight": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "width": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "z": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + } + }, + "type": "object" + }, + "frameAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The frame anchor specifies defaults for **x** and **y** based on the plot’s frame; it may be one of the four sides (*top*, *right*, *bottom*, *left*), one of the four corners (*top-left*, *top-right*, *bottom-right*,\n*bottom-left*), or the *middle* of the frame. For example, for tips distributed horizontally at the top of the frame:\n\n```js Plot.tip(data, {x: \"date\", frameAnchor: \"top\"}) ```" + }, + "lineHeight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line height in ems; defaults to 1. The line height affects the (typically vertical) separation between adjacent baselines of text, as well as the separation between the text and its anchor point." + }, + "lineWidth": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line width in ems (e.g., 10 for about 20 characters); defaults to infinity, disabling wrapping and clipping.\n\nIf **textOverflow** is null, lines will be wrapped at the specified length. If a line is split at a soft hyphen (\\xad), a hyphen (-) will be displayed at the end of the line. If **textOverflow** is not null, lines will be clipped according to the given strategy." + }, + "monospace": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, changes the default **fontFamily** to *monospace*, and uses simplified monospaced text metrics calculations." + }, + "pathFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The image filter for the tip’s box; defaults to a drop shadow." + }, + "pointer": { + "$ref": "#/definitions/TipPointer" + }, + "pointerSize": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The size of the tip’s pointer in pixels; defaults to 12." + }, + "preferredAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If an explicit tip anchor is not specified, an anchor is chosen automatically such that the tip fits within the plot’s frame; if the preferred anchor fits, it is chosen." + }, + "textAnchor": { + "anyOf": [ + { + "const": "start", + "type": "string" + }, + { + "const": "middle", + "type": "string" + }, + { + "const": "end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [text anchor][1] controls how text is aligned (typically horizontally) relative to its anchor point; it is one of *start*, *end*, or *middle*. If the frame anchor is *left*, *top-left*, or *bottom-left*, the default text anchor is *start*; if the frame anchor is *right*, *top-right*, or\n*bottom-right*, the default is *end*; otherwise it is *middle*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/text-anchor" + }, + "textOverflow": { + "anyOf": [ + { + "type": "null" + }, + { + "const": "clip", + "type": "string" + }, + { + "const": "ellipsis", + "type": "string" + }, + { + "const": "clip-start", + "type": "string" + }, + { + "const": "clip-end", + "type": "string" + }, + { + "const": "ellipsis-start", + "type": "string" + }, + { + "const": "ellipsis-middle", + "type": "string" + }, + { + "const": "ellipsis-end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How truncate (or wrap) lines of text longer than the given **lineWidth**; one of:\n\n- null (default) - preserve overflowing characters (and wrap if needed)\n- *clip* or *clip-end* - remove characters from the end\n- *clip-start* - remove characters from the start\n- *ellipsis* or *ellipsis-end* - replace characters from the end with an ellipsis (…)\n- *ellipsis-start* - replace characters from the start with an ellipsis (…)\n- *ellipsis-middle* - replace characters from the middle with an ellipsis (…)\n\nIf no **title** was specified, if text requires truncation, a title containing the non-truncated text will be implicitly added." + }, + "textPadding": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The padding around the text in pixels; defaults to 8." + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + } + }, + "type": "object" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to generate a tooltip for this mark, and any tip options." + }, + "title": { + "$ref": "#/definitions/ChannelValue", + "description": "The title; a channel specifying accessible, short textual descriptions as strings (possibly with newlines). If the tip option is specified, the title will be displayed with an interactive tooltip instead of using the SVG [title element][1].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/title" + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The dependent variable horizontal position channel, typically bound to the\n*x* scale." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The independent variable vertical position channel, typically bound to the *y* scale; defaults to the zero-based index of the data [0, 1, 2, …]." + }, + "z": { + "$ref": "#/definitions/ChannelValue", + "description": "An optional ordinal channel for grouping data, producing an independent error bar for each group. If not specified, it defaults to **stroke** if a channel." + } + }, + "required": [ + "data", + "mark", + "x" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "$schema": { + "description": "A [JSON schema](http://json-schema.org/) URL for this specification, such as https://uwdata.github.io/mosaic/schema/latest.json. This property enables validation and autocomplete in editors with JSON schema support.", + "format": "uri", + "type": "string" + }, + "ariaDescription": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-description][1]; a constant textual description.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-description" + }, + "ariaHidden": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-hidden][1] state; a constant indicating whether the element is exposed to an accessibility API.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-hidden" + }, + "ariaLabel": { + "$ref": "#/definitions/ChannelValue", + "description": "The [aria-label][1]; a channel specifying short textual labels representing the value in the accessibility tree.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-label" + }, + "ci": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The confidence interval in (0, 1); defaults to 0.95." + }, + "clip": { + "anyOf": [ + { + "const": "frame", + "type": "string" + }, + { + "const": "sphere", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to clip the mark; one of:\n\n- *frame* or true - clip to the plot’s frame (inner area)\n- *sphere* - clip to the projected sphere (*e.g.*, front hemisphere)\n- null or false - do not clip\n\nThe *sphere* clip option requires a geographic projection." + }, + "config": { + "$ref": "#/definitions/Config", + "description": "Configuration options." + }, + "data": { + "$ref": "#/definitions/Data", + "description": "Dataset definitions." + }, + "dx": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The horizontal offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "dy": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The vertical offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "facet": { + "anyOf": [ + { + "const": "auto", + "type": "string" + }, + { + "const": "include", + "type": "string" + }, + { + "const": "exclude", + "type": "string" + }, + { + "const": "super", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to enable or disable faceting; one of:\n\n- *auto* (default) - automatically determine if this mark should be faceted\n- *include* (or true) - draw the subset of the mark’s data in the current facet\n- *exclude* - draw the subset of the mark’s data *not* in the current facet\n- *super* - draw this mark in a single frame that covers all facets\n- null (or false) - repeat this mark’s data across all facets (*i.e.*, no faceting)\n\nWhen a mark uses *super* faceting, it is not allowed to use position scales (*x*, *y*, *fx*, or *fy*); *super* faceting is intended for decorations, such as labels and legends.\n\nWhen top-level faceting is used, the default *auto* setting is equivalent to *include* when the mark data is strictly equal to the top-level facet data; otherwise it is equivalent to null. When the *include* or *exclude* facet mode is chosen, the mark data must be parallel to the top-level facet data: the data must have the same length and order. If the data are not parallel, then the wrong data may be shown in each facet. The default\n*auto* therefore requires strict equality (`===`) for safety, and using the facet data as mark data is recommended when using the *exclude* facet mode. (To construct parallel data safely, consider using [*array*.map][1] on the facet data.)\n\nWhen mark-level faceting is used, the default *auto* setting is equivalent to *include*: the mark will be faceted if either the **fx** or **fy** channel option (or both) is specified. The null or false option will disable faceting, while *exclude* draws the subset of the mark’s data *not* in the current facet.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map" + }, + "facetAnchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "right", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "const": "left", + "type": "string" + }, + { + "const": "top-left", + "type": "string" + }, + { + "const": "top-right", + "type": "string" + }, + { + "const": "bottom-left", + "type": "string" + }, + { + "const": "bottom-right", + "type": "string" + }, + { + "const": "top-empty", + "type": "string" + }, + { + "const": "right-empty", + "type": "string" + }, + { + "const": "bottom-empty", + "type": "string" + }, + { + "const": "left-empty", + "type": "string" + }, + { + "const": "empty", + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to place the mark with respect to facets; one of:\n\n- null (default for most marks) - display the mark in each non-empty facet\n- *top*, *right*, *bottom*, or *left* - display the mark only in facets on the given side\n- *top-empty*, *right-empty*, *bottom-empty*, or *left-empty* (default for axis marks) - display the mark only in facets that have empty space on the given side: either the margin, or an empty facet\n- *empty* - display the mark in empty facets only" + }, + "fill": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill" + }, + "fillOpacity": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill-opacity][1]; a constant number between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill-opacity" + }, + "filter": { + "$ref": "#/definitions/ChannelValue", + "description": "Applies a transform to filter the mark’s index according to the given channel values; only truthy values are retained.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "fx": { + "$ref": "#/definitions/ChannelValue", + "description": "The horizontal facet position channel, for mark-level faceting, bound to the *fx* scale." + }, + "fy": { + "$ref": "#/definitions/ChannelValue", + "description": "The vertical facet position channel, for mark-level faceting, bound to the\n*fy* scale." + }, + "href": { + "$ref": "#/definitions/ChannelValue", + "description": "The [href][1]; a channel specifying URLs for clickable links. May be used in conjunction with the **target** option to open links in another window.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/href" + }, + "imageFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A CSS [filter][1]; a constant string used to adjust the rendering of images, such as *blur(5px)*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/filter" + }, + "margin": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four mark margins: **marginTop**,\n**marginRight**, **marginBottom**, and **marginLeft**; typically defaults to 0, except for axis marks." + }, + "marginBottom": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s bottom margin; the minimum distance in pixels between the bottom edges of the inner and outer plot area." + }, + "marginLeft": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s left margin; the minimum distance in pixels between the left edges of the inner and outer plot area." + }, + "marginRight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s right margin; the minimum distance in pixels between the right edges of the mark’s inner and outer plot area." + }, + "marginTop": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s top margin; the minimum distance in pixels between the top edges of the inner and outer plot area." + }, + "mark": { + "const": "errorbarY", + "description": "A mark that draws error bars for a calculated parametric confidence interval for a dependent variable (*y*), potentially grouped by an independent variable (*x*).\n\nThis mark aggregates raw values to produce a [parametric confidence interval][1] of the mean, assuming a normal distribution. To instead visualize pre-computeted interval values or custom aggregations, use a **ruleX** mark with specified **y1** and **y2** channels.\n\nMultiple error bars can be produced by specifying a **z** or **stroke** channel. Set the **marker** option to `'tick'` to add small perpendicular lines at the start and end of the error interval.\n\n[1]: https://en.wikipedia.org/wiki/Normal_distribution#Confidence_intervals", + "type": "string" + }, + "marker": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for markerStart, markerMid, and markerEnd; one of:\n\n- a marker name such as *arrow* or *circle*\n- *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*" + }, + "markerEnd": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The marker for the ending point of a line segment; one of:\n\n- a marker name such as *arrow* or *circle*\n* *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*" + }, + "markerMid": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The marker for any middle (interior) points of a line segment. If the line segment only has a start and end point, this option has no effect. One of:\n\n- a marker name such as *arrow* or *circle*\n* *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*\n* a function - a custom marker function; see below" + }, + "markerStart": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The marker for the starting point of a line segment; one of:\n\n- a marker name such as *arrow* or *circle*\n* *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*" + }, + "meta": { + "$ref": "#/definitions/Meta", + "description": "Specification metadata." + }, + "mixBlendMode": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [mix-blend-mode][1]; a constant string specifying how to blend content such as *multiply*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode" + }, + "opacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally. For faster rendering, prefer the **strokeOpacity** or **fillOpacity** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/opacity" + }, + "paintOrder": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [paint-order][1]; a constant string specifying the order in which the\n**fill**, **stroke**, and any markers are drawn; defaults to *normal*, which draws the fill, then stroke, then markers; defaults to *stroke* for the text mark to create a “halo” around text to improve legibility.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/paint-order" + }, + "params": { + "$ref": "#/definitions/Params", + "description": "Param and Selection definitions." + }, + "plotDefaults": { + "$ref": "#/definitions/PlotAttributes", + "description": "A default set of attributes to apply to all plot components." + }, + "pointerEvents": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [pointer-events][1] property; a constant string such as *none*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/pointer-events" + }, + "reverse": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Applies a transform to reverse the order of the mark’s index, say for reverse input order." + }, + "select": { + "$ref": "#/definitions/SelectFilter", + "description": "Applies a filter transform after data is loaded to highlight selected values only. For example, `first` and `last` select the first or last values of series only (using the *z* channel to separate series). Meanwhile, `nearestX` and `nearestY` select the point nearest to the pointer along the *x* or *y* channel dimension. Unlike Mosaic selections, a mark level *select* is internal to the mark only, and does not populate a param or selection value to be shared across clients.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "shapeRendering": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [shape-rendering][1]; a constant string such as *crispEdges*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/shape-rendering" + }, + "sort": { + "anyOf": [ + { + "$ref": "#/definitions/SortOrder" + }, + { + "$ref": "#/definitions/ChannelDomainSort" + } + ], + "description": "Either applies a transform to sort the mark’s index by the specified channel values, or imputes ordinal scale domains from this mark’s channels.\n\nWhen imputing ordinal scale domains from channel values, the **sort** option is an object whose keys are ordinal scale names such as *x* or *fx*, and whose values are channel names such as *y*, *y1*, or *y2*. For example, to impute the *y* scale’s domain from the associated *x* channel values in ascending order:\n\n```js sort: {y: \"x\"} ```\n\nFor different sort options for different scales, replace the channel name with a *value* object and per-scale options:\n\n```js sort: {y: {value: \"-x\"}} ```\n\nWhen sorting the mark’s index, the **sort** option is instead one of:\n\n- a channel value definition for sorting given values in ascending order\n- a {value, order} object for sorting given values\n- a {channel, order} object for sorting the named channel’s values" + }, + "stroke": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke" + }, + "strokeDasharray": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dasharray][1]; a constant number indicating the length in pixels of alternating dashes and gaps, or a constant string of numbers separated by spaces or commas (_e.g._, *10 2* for dashes of 10 pixels separated by gaps of 2 pixels), or *none* (the default) for no dashing\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dasharray" + }, + "strokeDashoffset": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dashoffset][1]; a constant indicating the offset in pixels of the first dash along the stroke; defaults to zero.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dashoffset" + }, + "strokeLinecap": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linecap][1]; a constant specifying how to cap stroked paths, such as *butt*, *round*, or *square*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linecap" + }, + "strokeLinejoin": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linejoin][1]; a constant specifying how to join stroked paths, such as *bevel*, *miter*, *miter-clip*, or *round*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linejoin" + }, + "strokeMiterlimit": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-miterlimit][1]; a constant number specifying how to limit the length of *miter* joins on stroked paths.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-miterlimit" + }, + "strokeOpacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-opacity" + }, + "strokeWidth": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-width][1]; a constant number in pixels, or a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-width" + }, + "target": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [target][1]; a constant string specifying the target window (_e.g._,\n*_blank*) for clickable links; used in conjunction with the **href** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/target" + }, + "tip": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/TipPointer" + }, + { + "properties": { + "anchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The tip anchor specifies how to orient the tip box relative to its anchor position; it refers to the part of the tip box that is attached to the anchor point. For example, the *top-left* anchor places the top-left corner of tip box near the anchor position, hence placing the tip box below and to the right of the anchor position." + }, + "fontFamily": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font-family][1]; a constant; defaults to the plot’s font family, which is typically [*system-ui*][2].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-family [2]: https://drafts.csswg.org/css-fonts-4/#valdef-font-family-system-ui" + }, + "fontSize": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font size][1] in pixels; either a constant or a channel; defaults to the plot’s font size, which is typically 10. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-size" + }, + "fontStyle": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font style][1]; a constant; defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-style" + }, + "fontVariant": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font variant][1]; a constant; if the **text** channel contains numbers or dates, defaults to *tabular-nums* to facilitate comparing numbers; otherwise defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant" + }, + "fontWeight": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font weight][1]; a constant; defaults to the plot’s font weight, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight" + }, + "format": { + "additionalProperties": false, + "description": "How channel values are formatted for display. If a format is a string, it is interpreted as a (UTC) time format for temporal channels, and otherwise a number format.", + "properties": { + "ariaLabel": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fill": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fillOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fontSize": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fx": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fy": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "geometry": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "height": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "href": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "length": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "opacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "path": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "r": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "rotate": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "src": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "stroke": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeWidth": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "symbol": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "text": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "title": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "weight": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "width": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "z": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + } + }, + "type": "object" + }, + "frameAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The frame anchor specifies defaults for **x** and **y** based on the plot’s frame; it may be one of the four sides (*top*, *right*, *bottom*, *left*), one of the four corners (*top-left*, *top-right*, *bottom-right*,\n*bottom-left*), or the *middle* of the frame. For example, for tips distributed horizontally at the top of the frame:\n\n```js Plot.tip(data, {x: \"date\", frameAnchor: \"top\"}) ```" + }, + "lineHeight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line height in ems; defaults to 1. The line height affects the (typically vertical) separation between adjacent baselines of text, as well as the separation between the text and its anchor point." + }, + "lineWidth": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line width in ems (e.g., 10 for about 20 characters); defaults to infinity, disabling wrapping and clipping.\n\nIf **textOverflow** is null, lines will be wrapped at the specified length. If a line is split at a soft hyphen (\\xad), a hyphen (-) will be displayed at the end of the line. If **textOverflow** is not null, lines will be clipped according to the given strategy." + }, + "monospace": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, changes the default **fontFamily** to *monospace*, and uses simplified monospaced text metrics calculations." + }, + "pathFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The image filter for the tip’s box; defaults to a drop shadow." + }, + "pointer": { + "$ref": "#/definitions/TipPointer" + }, + "pointerSize": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The size of the tip’s pointer in pixels; defaults to 12." + }, + "preferredAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If an explicit tip anchor is not specified, an anchor is chosen automatically such that the tip fits within the plot’s frame; if the preferred anchor fits, it is chosen." + }, + "textAnchor": { + "anyOf": [ + { + "const": "start", + "type": "string" + }, + { + "const": "middle", + "type": "string" + }, + { + "const": "end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [text anchor][1] controls how text is aligned (typically horizontally) relative to its anchor point; it is one of *start*, *end*, or *middle*. If the frame anchor is *left*, *top-left*, or *bottom-left*, the default text anchor is *start*; if the frame anchor is *right*, *top-right*, or\n*bottom-right*, the default is *end*; otherwise it is *middle*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/text-anchor" + }, + "textOverflow": { + "anyOf": [ + { + "type": "null" + }, + { + "const": "clip", + "type": "string" + }, + { + "const": "ellipsis", + "type": "string" + }, + { + "const": "clip-start", + "type": "string" + }, + { + "const": "clip-end", + "type": "string" + }, + { + "const": "ellipsis-start", + "type": "string" + }, + { + "const": "ellipsis-middle", + "type": "string" + }, + { + "const": "ellipsis-end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How truncate (or wrap) lines of text longer than the given **lineWidth**; one of:\n\n- null (default) - preserve overflowing characters (and wrap if needed)\n- *clip* or *clip-end* - remove characters from the end\n- *clip-start* - remove characters from the start\n- *ellipsis* or *ellipsis-end* - replace characters from the end with an ellipsis (…)\n- *ellipsis-start* - replace characters from the start with an ellipsis (…)\n- *ellipsis-middle* - replace characters from the middle with an ellipsis (…)\n\nIf no **title** was specified, if text requires truncation, a title containing the non-truncated text will be implicitly added." + }, + "textPadding": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The padding around the text in pixels; defaults to 8." + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + } + }, + "type": "object" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to generate a tooltip for this mark, and any tip options." + }, + "title": { + "$ref": "#/definitions/ChannelValue", + "description": "The title; a channel specifying accessible, short textual descriptions as strings (possibly with newlines). If the tip option is specified, the title will be displayed with an interactive tooltip instead of using the SVG [title element][1].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/title" + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The independent variable horizontal position channel, typically bound to the *x* scale; defaults to the zero-based index of the data [0, 1, 2, …]." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The dependent variable vertical position channel, typically bound to the\n*y* scale." + }, + "z": { + "$ref": "#/definitions/ChannelValue", + "description": "An optional ordinal channel for grouping data, producing an independent error bar for each group. If not specified, it defaults to **stroke** if a channel." + } + }, + "required": [ + "data", + "mark", + "y" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "$schema": { + "description": "A [JSON schema](http://json-schema.org/) URL for this specification, such as https://uwdata.github.io/mosaic/schema/latest.json. This property enables validation and autocomplete in editors with JSON schema support.", + "format": "uri", + "type": "string" + }, + "anchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "right", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "const": "left", + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If null (default), the rectangular outline of the frame is drawn; otherwise the frame is drawn as a line only on the given side, and the\n**rx**, **ry**, **fill**, and **fillOpacity** options are ignored." + }, + "ariaDescription": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-description][1]; a constant textual description.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-description" + }, + "ariaHidden": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-hidden][1] state; a constant indicating whether the element is exposed to an accessibility API.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-hidden" + }, + "ariaLabel": { + "$ref": "#/definitions/ChannelValue", + "description": "The [aria-label][1]; a channel specifying short textual labels representing the value in the accessibility tree.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-label" + }, + "clip": { + "anyOf": [ + { + "const": "frame", + "type": "string" + }, + { + "const": "sphere", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to clip the mark; one of:\n\n- *frame* or true - clip to the plot’s frame (inner area)\n- *sphere* - clip to the projected sphere (*e.g.*, front hemisphere)\n- null or false - do not clip\n\nThe *sphere* clip option requires a geographic projection." + }, + "config": { + "$ref": "#/definitions/Config", + "description": "Configuration options." + }, + "data": { + "$ref": "#/definitions/Data", + "description": "Dataset definitions." + }, + "dx": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The horizontal offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "dy": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The vertical offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "facet": { + "anyOf": [ + { + "const": "auto", + "type": "string" + }, + { + "const": "include", + "type": "string" + }, + { + "const": "exclude", + "type": "string" + }, + { + "const": "super", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to enable or disable faceting; one of:\n\n- *auto* (default) - automatically determine if this mark should be faceted\n- *include* (or true) - draw the subset of the mark’s data in the current facet\n- *exclude* - draw the subset of the mark’s data *not* in the current facet\n- *super* - draw this mark in a single frame that covers all facets\n- null (or false) - repeat this mark’s data across all facets (*i.e.*, no faceting)\n\nWhen a mark uses *super* faceting, it is not allowed to use position scales (*x*, *y*, *fx*, or *fy*); *super* faceting is intended for decorations, such as labels and legends.\n\nWhen top-level faceting is used, the default *auto* setting is equivalent to *include* when the mark data is strictly equal to the top-level facet data; otherwise it is equivalent to null. When the *include* or *exclude* facet mode is chosen, the mark data must be parallel to the top-level facet data: the data must have the same length and order. If the data are not parallel, then the wrong data may be shown in each facet. The default\n*auto* therefore requires strict equality (`===`) for safety, and using the facet data as mark data is recommended when using the *exclude* facet mode. (To construct parallel data safely, consider using [*array*.map][1] on the facet data.)\n\nWhen mark-level faceting is used, the default *auto* setting is equivalent to *include*: the mark will be faceted if either the **fx** or **fy** channel option (or both) is specified. The null or false option will disable faceting, while *exclude* draws the subset of the mark’s data *not* in the current facet.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map" + }, + "facetAnchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "right", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "const": "left", + "type": "string" + }, + { + "const": "top-left", + "type": "string" + }, + { + "const": "top-right", + "type": "string" + }, + { + "const": "bottom-left", + "type": "string" + }, + { + "const": "bottom-right", + "type": "string" + }, + { + "const": "top-empty", + "type": "string" + }, + { + "const": "right-empty", + "type": "string" + }, + { + "const": "bottom-empty", + "type": "string" + }, + { + "const": "left-empty", + "type": "string" + }, + { + "const": "empty", + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to place the mark with respect to facets; one of:\n\n- null (default for most marks) - display the mark in each non-empty facet\n- *top*, *right*, *bottom*, or *left* - display the mark only in facets on the given side\n- *top-empty*, *right-empty*, *bottom-empty*, or *left-empty* (default for axis marks) - display the mark only in facets that have empty space on the given side: either the margin, or an empty facet\n- *empty* - display the mark in empty facets only" + }, + "fill": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill" + }, + "fillOpacity": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill-opacity][1]; a constant number between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill-opacity" + }, + "filter": { + "$ref": "#/definitions/ChannelValue", + "description": "Applies a transform to filter the mark’s index according to the given channel values; only truthy values are retained.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "fx": { + "$ref": "#/definitions/ChannelValue", + "description": "The horizontal facet position channel, for mark-level faceting, bound to the *fx* scale." + }, + "fy": { + "$ref": "#/definitions/ChannelValue", + "description": "The vertical facet position channel, for mark-level faceting, bound to the\n*fy* scale." + }, + "href": { + "$ref": "#/definitions/ChannelValue", + "description": "The [href][1]; a channel specifying URLs for clickable links. May be used in conjunction with the **target** option to open links in another window.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/href" + }, + "imageFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A CSS [filter][1]; a constant string used to adjust the rendering of images, such as *blur(5px)*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/filter" + }, + "inset": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four insets: **insetTop**,\n**insetRight**, **insetBottom**, and **insetLeft**. All insets typically default to zero, though not always (say when using bin transform). A positive inset reduces effective area, while a negative inset increases it." + }, + "insetBottom": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Insets the bottom edge by the specified number of pixels. A positive value insets towards the top edge (reducing effective area), while a negative value insets away from the top edge (increasing it)." + }, + "insetLeft": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Insets the left edge by the specified number of pixels. A positive value insets towards the right edge (reducing effective area), while a negative value insets away from the right edge (increasing it)." + }, + "insetRight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Insets the right edge by the specified number of pixels. A positive value insets towards the left edge (reducing effective area), while a negative value insets away from the left edge (increasing it)." + }, + "insetTop": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Insets the top edge by the specified number of pixels. A positive value insets towards the bottom edge (reducing effective area), while a negative value insets away from the bottom edge (increasing it)." + }, + "margin": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four mark margins: **marginTop**,\n**marginRight**, **marginBottom**, and **marginLeft**; typically defaults to 0, except for axis marks." + }, + "marginBottom": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s bottom margin; the minimum distance in pixels between the bottom edges of the inner and outer plot area." + }, + "marginLeft": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s left margin; the minimum distance in pixels between the left edges of the inner and outer plot area." + }, + "marginRight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s right margin; the minimum distance in pixels between the right edges of the mark’s inner and outer plot area." + }, + "marginTop": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s top margin; the minimum distance in pixels between the top edges of the inner and outer plot area." + }, + "mark": { + "const": "frame", + "description": "Draws a rectangle around the plot’s frame, or if an **anchor** is given, a line on the given side. Useful for visual separation of facets, or in conjunction with axes and grids to fill the frame’s background.", + "type": "string" + }, + "meta": { + "$ref": "#/definitions/Meta", + "description": "Specification metadata." + }, + "mixBlendMode": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [mix-blend-mode][1]; a constant string specifying how to blend content such as *multiply*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode" + }, + "opacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally. For faster rendering, prefer the **strokeOpacity** or **fillOpacity** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/opacity" + }, + "paintOrder": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [paint-order][1]; a constant string specifying the order in which the\n**fill**, **stroke**, and any markers are drawn; defaults to *normal*, which draws the fill, then stroke, then markers; defaults to *stroke* for the text mark to create a “halo” around text to improve legibility.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/paint-order" + }, + "params": { + "$ref": "#/definitions/Params", + "description": "Param and Selection definitions." + }, + "plotDefaults": { + "$ref": "#/definitions/PlotAttributes", + "description": "A default set of attributes to apply to all plot components." + }, + "pointerEvents": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [pointer-events][1] property; a constant string such as *none*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/pointer-events" + }, + "reverse": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Applies a transform to reverse the order of the mark’s index, say for reverse input order." + }, + "rx": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The rounded corner [*x*-radius][1], either in pixels or as a percentage of the rect width. If **rx** is not specified, it defaults to **ry** if present, and otherwise draws square corners.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/rx" + }, + "ry": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The rounded corner [*y*-radius][1], either in pixels or as a percentage of the rect height. If **ry** is not specified, it defaults to **rx** if present, and otherwise draws square corners.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/ry" + }, + "select": { + "$ref": "#/definitions/SelectFilter", + "description": "Applies a filter transform after data is loaded to highlight selected values only. For example, `first` and `last` select the first or last values of series only (using the *z* channel to separate series). Meanwhile, `nearestX` and `nearestY` select the point nearest to the pointer along the *x* or *y* channel dimension. Unlike Mosaic selections, a mark level *select* is internal to the mark only, and does not populate a param or selection value to be shared across clients.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "shapeRendering": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [shape-rendering][1]; a constant string such as *crispEdges*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/shape-rendering" + }, + "sort": { + "anyOf": [ + { + "$ref": "#/definitions/SortOrder" + }, + { + "$ref": "#/definitions/ChannelDomainSort" + } + ], + "description": "Either applies a transform to sort the mark’s index by the specified channel values, or imputes ordinal scale domains from this mark’s channels.\n\nWhen imputing ordinal scale domains from channel values, the **sort** option is an object whose keys are ordinal scale names such as *x* or *fx*, and whose values are channel names such as *y*, *y1*, or *y2*. For example, to impute the *y* scale’s domain from the associated *x* channel values in ascending order:\n\n```js sort: {y: \"x\"} ```\n\nFor different sort options for different scales, replace the channel name with a *value* object and per-scale options:\n\n```js sort: {y: {value: \"-x\"}} ```\n\nWhen sorting the mark’s index, the **sort** option is instead one of:\n\n- a channel value definition for sorting given values in ascending order\n- a {value, order} object for sorting given values\n- a {channel, order} object for sorting the named channel’s values" + }, + "stroke": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke" + }, + "strokeDasharray": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dasharray][1]; a constant number indicating the length in pixels of alternating dashes and gaps, or a constant string of numbers separated by spaces or commas (_e.g._, *10 2* for dashes of 10 pixels separated by gaps of 2 pixels), or *none* (the default) for no dashing\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dasharray" + }, + "strokeDashoffset": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dashoffset][1]; a constant indicating the offset in pixels of the first dash along the stroke; defaults to zero.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dashoffset" + }, + "strokeLinecap": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linecap][1]; a constant specifying how to cap stroked paths, such as *butt*, *round*, or *square*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linecap" + }, + "strokeLinejoin": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linejoin][1]; a constant specifying how to join stroked paths, such as *bevel*, *miter*, *miter-clip*, or *round*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linejoin" + }, + "strokeMiterlimit": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-miterlimit][1]; a constant number specifying how to limit the length of *miter* joins on stroked paths.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-miterlimit" + }, + "strokeOpacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-opacity" + }, + "strokeWidth": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-width][1]; a constant number in pixels, or a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-width" + }, + "target": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [target][1]; a constant string specifying the target window (_e.g._,\n*_blank*) for clickable links; used in conjunction with the **href** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/target" + }, + "tip": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/TipPointer" + }, + { + "properties": { + "anchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The tip anchor specifies how to orient the tip box relative to its anchor position; it refers to the part of the tip box that is attached to the anchor point. For example, the *top-left* anchor places the top-left corner of tip box near the anchor position, hence placing the tip box below and to the right of the anchor position." + }, + "fontFamily": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font-family][1]; a constant; defaults to the plot’s font family, which is typically [*system-ui*][2].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-family [2]: https://drafts.csswg.org/css-fonts-4/#valdef-font-family-system-ui" + }, + "fontSize": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font size][1] in pixels; either a constant or a channel; defaults to the plot’s font size, which is typically 10. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-size" + }, + "fontStyle": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font style][1]; a constant; defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-style" + }, + "fontVariant": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font variant][1]; a constant; if the **text** channel contains numbers or dates, defaults to *tabular-nums* to facilitate comparing numbers; otherwise defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant" + }, + "fontWeight": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font weight][1]; a constant; defaults to the plot’s font weight, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight" + }, + "format": { + "additionalProperties": false, + "description": "How channel values are formatted for display. If a format is a string, it is interpreted as a (UTC) time format for temporal channels, and otherwise a number format.", + "properties": { + "ariaLabel": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fill": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fillOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fontSize": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fx": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fy": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "geometry": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "height": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "href": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "length": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "opacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "path": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "r": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "rotate": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "src": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "stroke": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeWidth": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "symbol": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "text": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "title": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "weight": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "width": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "z": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + } + }, + "type": "object" + }, + "frameAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The frame anchor specifies defaults for **x** and **y** based on the plot’s frame; it may be one of the four sides (*top*, *right*, *bottom*, *left*), one of the four corners (*top-left*, *top-right*, *bottom-right*,\n*bottom-left*), or the *middle* of the frame. For example, for tips distributed horizontally at the top of the frame:\n\n```js Plot.tip(data, {x: \"date\", frameAnchor: \"top\"}) ```" + }, + "lineHeight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line height in ems; defaults to 1. The line height affects the (typically vertical) separation between adjacent baselines of text, as well as the separation between the text and its anchor point." + }, + "lineWidth": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line width in ems (e.g., 10 for about 20 characters); defaults to infinity, disabling wrapping and clipping.\n\nIf **textOverflow** is null, lines will be wrapped at the specified length. If a line is split at a soft hyphen (\\xad), a hyphen (-) will be displayed at the end of the line. If **textOverflow** is not null, lines will be clipped according to the given strategy." + }, + "monospace": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, changes the default **fontFamily** to *monospace*, and uses simplified monospaced text metrics calculations." + }, + "pathFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The image filter for the tip’s box; defaults to a drop shadow." + }, + "pointer": { + "$ref": "#/definitions/TipPointer" + }, + "pointerSize": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The size of the tip’s pointer in pixels; defaults to 12." + }, + "preferredAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If an explicit tip anchor is not specified, an anchor is chosen automatically such that the tip fits within the plot’s frame; if the preferred anchor fits, it is chosen." + }, + "textAnchor": { + "anyOf": [ + { + "const": "start", + "type": "string" + }, + { + "const": "middle", + "type": "string" + }, + { + "const": "end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [text anchor][1] controls how text is aligned (typically horizontally) relative to its anchor point; it is one of *start*, *end*, or *middle*. If the frame anchor is *left*, *top-left*, or *bottom-left*, the default text anchor is *start*; if the frame anchor is *right*, *top-right*, or\n*bottom-right*, the default is *end*; otherwise it is *middle*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/text-anchor" + }, + "textOverflow": { + "anyOf": [ + { + "type": "null" + }, + { + "const": "clip", + "type": "string" + }, + { + "const": "ellipsis", + "type": "string" + }, + { + "const": "clip-start", + "type": "string" + }, + { + "const": "clip-end", + "type": "string" + }, + { + "const": "ellipsis-start", + "type": "string" + }, + { + "const": "ellipsis-middle", + "type": "string" + }, + { + "const": "ellipsis-end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How truncate (or wrap) lines of text longer than the given **lineWidth**; one of:\n\n- null (default) - preserve overflowing characters (and wrap if needed)\n- *clip* or *clip-end* - remove characters from the end\n- *clip-start* - remove characters from the start\n- *ellipsis* or *ellipsis-end* - replace characters from the end with an ellipsis (…)\n- *ellipsis-start* - replace characters from the start with an ellipsis (…)\n- *ellipsis-middle* - replace characters from the middle with an ellipsis (…)\n\nIf no **title** was specified, if text requires truncation, a title containing the non-truncated text will be implicitly added." + }, + "textPadding": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The padding around the text in pixels; defaults to 8." + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + } + }, + "type": "object" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to generate a tooltip for this mark, and any tip options." + }, + "title": { + "$ref": "#/definitions/ChannelValue", + "description": "The title; a channel specifying accessible, short textual descriptions as strings (possibly with newlines). If the tip option is specified, the title will be displayed with an interactive tooltip instead of using the SVG [title element][1].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/title" + } + }, + "required": [ + "mark" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "$schema": { + "description": "A [JSON schema](http://json-schema.org/) URL for this specification, such as https://uwdata.github.io/mosaic/schema/latest.json. This property enables validation and autocomplete in editors with JSON schema support.", + "format": "uri", + "type": "string" + }, + "ariaDescription": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-description][1]; a constant textual description.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-description" + }, + "ariaHidden": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-hidden][1] state; a constant indicating whether the element is exposed to an accessibility API.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-hidden" + }, + "ariaLabel": { + "$ref": "#/definitions/ChannelValue", + "description": "The [aria-label][1]; a channel specifying short textual labels representing the value in the accessibility tree.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-label" + }, + "clip": { + "anyOf": [ + { + "const": "frame", + "type": "string" + }, + { + "const": "sphere", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to clip the mark; one of:\n\n- *frame* or true - clip to the plot’s frame (inner area)\n- *sphere* - clip to the projected sphere (*e.g.*, front hemisphere)\n- null or false - do not clip\n\nThe *sphere* clip option requires a geographic projection." + }, + "config": { + "$ref": "#/definitions/Config", + "description": "Configuration options." + }, + "data": { + "$ref": "#/definitions/Data", + "description": "Dataset definitions." + }, + "dx": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The horizontal offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "dy": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The vertical offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "facet": { + "anyOf": [ + { + "const": "auto", + "type": "string" + }, + { + "const": "include", + "type": "string" + }, + { + "const": "exclude", + "type": "string" + }, + { + "const": "super", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to enable or disable faceting; one of:\n\n- *auto* (default) - automatically determine if this mark should be faceted\n- *include* (or true) - draw the subset of the mark’s data in the current facet\n- *exclude* - draw the subset of the mark’s data *not* in the current facet\n- *super* - draw this mark in a single frame that covers all facets\n- null (or false) - repeat this mark’s data across all facets (*i.e.*, no faceting)\n\nWhen a mark uses *super* faceting, it is not allowed to use position scales (*x*, *y*, *fx*, or *fy*); *super* faceting is intended for decorations, such as labels and legends.\n\nWhen top-level faceting is used, the default *auto* setting is equivalent to *include* when the mark data is strictly equal to the top-level facet data; otherwise it is equivalent to null. When the *include* or *exclude* facet mode is chosen, the mark data must be parallel to the top-level facet data: the data must have the same length and order. If the data are not parallel, then the wrong data may be shown in each facet. The default\n*auto* therefore requires strict equality (`===`) for safety, and using the facet data as mark data is recommended when using the *exclude* facet mode. (To construct parallel data safely, consider using [*array*.map][1] on the facet data.)\n\nWhen mark-level faceting is used, the default *auto* setting is equivalent to *include*: the mark will be faceted if either the **fx** or **fy** channel option (or both) is specified. The null or false option will disable faceting, while *exclude* draws the subset of the mark’s data *not* in the current facet.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map" + }, + "facetAnchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "right", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "const": "left", + "type": "string" + }, + { + "const": "top-left", + "type": "string" + }, + { + "const": "top-right", + "type": "string" + }, + { + "const": "bottom-left", + "type": "string" + }, + { + "const": "bottom-right", + "type": "string" + }, + { + "const": "top-empty", + "type": "string" + }, + { + "const": "right-empty", + "type": "string" + }, + { + "const": "bottom-empty", + "type": "string" + }, + { + "const": "left-empty", + "type": "string" + }, + { + "const": "empty", + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to place the mark with respect to facets; one of:\n\n- null (default for most marks) - display the mark in each non-empty facet\n- *top*, *right*, *bottom*, or *left* - display the mark only in facets on the given side\n- *top-empty*, *right-empty*, *bottom-empty*, or *left-empty* (default for axis marks) - display the mark only in facets that have empty space on the given side: either the margin, or an empty facet\n- *empty* - display the mark in empty facets only" + }, + "fill": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill" + }, + "fillOpacity": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill-opacity][1]; a constant number between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill-opacity" + }, + "filter": { + "$ref": "#/definitions/ChannelValue", + "description": "Applies a transform to filter the mark’s index according to the given channel values; only truthy values are retained.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "fx": { + "$ref": "#/definitions/ChannelValue", + "description": "The horizontal facet position channel, for mark-level faceting, bound to the *fx* scale." + }, + "fy": { + "$ref": "#/definitions/ChannelValue", + "description": "The vertical facet position channel, for mark-level faceting, bound to the\n*fy* scale." + }, + "geometry": { + "$ref": "#/definitions/ChannelValue", + "description": "A required channel for the geometry to render; defaults to identity, assuming *data* is a GeoJSON object or an iterable of GeoJSON objects." + }, + "href": { + "$ref": "#/definitions/ChannelValue", + "description": "The [href][1]; a channel specifying URLs for clickable links. May be used in conjunction with the **target** option to open links in another window.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/href" + }, + "imageFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A CSS [filter][1]; a constant string used to adjust the rendering of images, such as *blur(5px)*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/filter" + }, + "margin": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four mark margins: **marginTop**,\n**marginRight**, **marginBottom**, and **marginLeft**; typically defaults to 0, except for axis marks." + }, + "marginBottom": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s bottom margin; the minimum distance in pixels between the bottom edges of the inner and outer plot area." + }, + "marginLeft": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s left margin; the minimum distance in pixels between the left edges of the inner and outer plot area." + }, + "marginRight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s right margin; the minimum distance in pixels between the right edges of the mark’s inner and outer plot area." + }, + "marginTop": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s top margin; the minimum distance in pixels between the top edges of the inner and outer plot area." + }, + "mark": { + "const": "geo", + "description": "A geo mark. The **geometry** channel, which defaults to the identity function assuming that *data* is a GeoJSON object or an iterable of GeoJSON objects, is projected to the plane using the plot’s top-level\n**projection**.\n\nIf *data* is a GeoJSON feature collection, then the mark’s data is\n*data*.features; if *data* is a GeoJSON geometry collection, then the mark’s data is *data*.geometries; if *data* is some other GeoJSON object, then the mark’s data is the single-element array [*data*].", + "type": "string" + }, + "meta": { + "$ref": "#/definitions/Meta", + "description": "Specification metadata." + }, + "mixBlendMode": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [mix-blend-mode][1]; a constant string specifying how to blend content such as *multiply*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode" + }, + "opacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally. For faster rendering, prefer the **strokeOpacity** or **fillOpacity** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/opacity" + }, + "paintOrder": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [paint-order][1]; a constant string specifying the order in which the\n**fill**, **stroke**, and any markers are drawn; defaults to *normal*, which draws the fill, then stroke, then markers; defaults to *stroke* for the text mark to create a “halo” around text to improve legibility.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/paint-order" + }, + "params": { + "$ref": "#/definitions/Params", + "description": "Param and Selection definitions." + }, + "plotDefaults": { + "$ref": "#/definitions/PlotAttributes", + "description": "A default set of attributes to apply to all plot components." + }, + "pointerEvents": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [pointer-events][1] property; a constant string such as *none*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/pointer-events" + }, + "r": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The size of Point and MultiPoint geometries, defaulting to a constant 3 pixels. If **r** is a number, it is interpreted as a constant radius in pixels; otherwise it is interpreted as a channel and the effective radius is controlled by the *r* scale, which defaults to a *sqrt* scale such that the visual area of a point is proportional to its associated value.\n\nIf **r** is a channel, geometries will be sorted by descending radius by default, to limit occlusion; use the **sort** transform to control render order. Geometries with a nonpositive radius are not drawn." + }, + "reverse": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Applies a transform to reverse the order of the mark’s index, say for reverse input order." + }, + "select": { + "$ref": "#/definitions/SelectFilter", + "description": "Applies a filter transform after data is loaded to highlight selected values only. For example, `first` and `last` select the first or last values of series only (using the *z* channel to separate series). Meanwhile, `nearestX` and `nearestY` select the point nearest to the pointer along the *x* or *y* channel dimension. Unlike Mosaic selections, a mark level *select* is internal to the mark only, and does not populate a param or selection value to be shared across clients.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "shapeRendering": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [shape-rendering][1]; a constant string such as *crispEdges*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/shape-rendering" + }, + "sort": { + "anyOf": [ + { + "$ref": "#/definitions/SortOrder" + }, + { + "$ref": "#/definitions/ChannelDomainSort" + } + ], + "description": "Either applies a transform to sort the mark’s index by the specified channel values, or imputes ordinal scale domains from this mark’s channels.\n\nWhen imputing ordinal scale domains from channel values, the **sort** option is an object whose keys are ordinal scale names such as *x* or *fx*, and whose values are channel names such as *y*, *y1*, or *y2*. For example, to impute the *y* scale’s domain from the associated *x* channel values in ascending order:\n\n```js sort: {y: \"x\"} ```\n\nFor different sort options for different scales, replace the channel name with a *value* object and per-scale options:\n\n```js sort: {y: {value: \"-x\"}} ```\n\nWhen sorting the mark’s index, the **sort** option is instead one of:\n\n- a channel value definition for sorting given values in ascending order\n- a {value, order} object for sorting given values\n- a {channel, order} object for sorting the named channel’s values" + }, + "stroke": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke" + }, + "strokeDasharray": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dasharray][1]; a constant number indicating the length in pixels of alternating dashes and gaps, or a constant string of numbers separated by spaces or commas (_e.g._, *10 2* for dashes of 10 pixels separated by gaps of 2 pixels), or *none* (the default) for no dashing\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dasharray" + }, + "strokeDashoffset": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dashoffset][1]; a constant indicating the offset in pixels of the first dash along the stroke; defaults to zero.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dashoffset" + }, + "strokeLinecap": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linecap][1]; a constant specifying how to cap stroked paths, such as *butt*, *round*, or *square*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linecap" + }, + "strokeLinejoin": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linejoin][1]; a constant specifying how to join stroked paths, such as *bevel*, *miter*, *miter-clip*, or *round*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linejoin" + }, + "strokeMiterlimit": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-miterlimit][1]; a constant number specifying how to limit the length of *miter* joins on stroked paths.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-miterlimit" + }, + "strokeOpacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-opacity" + }, + "strokeWidth": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-width][1]; a constant number in pixels, or a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-width" + }, + "target": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [target][1]; a constant string specifying the target window (_e.g._,\n*_blank*) for clickable links; used in conjunction with the **href** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/target" + }, + "tip": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/TipPointer" + }, + { + "properties": { + "anchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The tip anchor specifies how to orient the tip box relative to its anchor position; it refers to the part of the tip box that is attached to the anchor point. For example, the *top-left* anchor places the top-left corner of tip box near the anchor position, hence placing the tip box below and to the right of the anchor position." + }, + "fontFamily": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font-family][1]; a constant; defaults to the plot’s font family, which is typically [*system-ui*][2].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-family [2]: https://drafts.csswg.org/css-fonts-4/#valdef-font-family-system-ui" + }, + "fontSize": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font size][1] in pixels; either a constant or a channel; defaults to the plot’s font size, which is typically 10. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-size" + }, + "fontStyle": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font style][1]; a constant; defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-style" + }, + "fontVariant": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font variant][1]; a constant; if the **text** channel contains numbers or dates, defaults to *tabular-nums* to facilitate comparing numbers; otherwise defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant" + }, + "fontWeight": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font weight][1]; a constant; defaults to the plot’s font weight, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight" + }, + "format": { + "additionalProperties": false, + "description": "How channel values are formatted for display. If a format is a string, it is interpreted as a (UTC) time format for temporal channels, and otherwise a number format.", + "properties": { + "ariaLabel": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fill": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fillOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fontSize": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fx": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fy": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "geometry": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "height": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "href": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "length": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "opacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "path": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "r": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "rotate": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "src": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "stroke": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeWidth": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "symbol": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "text": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "title": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "weight": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "width": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "z": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + } + }, + "type": "object" + }, + "frameAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The frame anchor specifies defaults for **x** and **y** based on the plot’s frame; it may be one of the four sides (*top*, *right*, *bottom*, *left*), one of the four corners (*top-left*, *top-right*, *bottom-right*,\n*bottom-left*), or the *middle* of the frame. For example, for tips distributed horizontally at the top of the frame:\n\n```js Plot.tip(data, {x: \"date\", frameAnchor: \"top\"}) ```" + }, + "lineHeight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line height in ems; defaults to 1. The line height affects the (typically vertical) separation between adjacent baselines of text, as well as the separation between the text and its anchor point." + }, + "lineWidth": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line width in ems (e.g., 10 for about 20 characters); defaults to infinity, disabling wrapping and clipping.\n\nIf **textOverflow** is null, lines will be wrapped at the specified length. If a line is split at a soft hyphen (\\xad), a hyphen (-) will be displayed at the end of the line. If **textOverflow** is not null, lines will be clipped according to the given strategy." + }, + "monospace": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, changes the default **fontFamily** to *monospace*, and uses simplified monospaced text metrics calculations." + }, + "pathFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The image filter for the tip’s box; defaults to a drop shadow." + }, + "pointer": { + "$ref": "#/definitions/TipPointer" + }, + "pointerSize": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The size of the tip’s pointer in pixels; defaults to 12." + }, + "preferredAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If an explicit tip anchor is not specified, an anchor is chosen automatically such that the tip fits within the plot’s frame; if the preferred anchor fits, it is chosen." + }, + "textAnchor": { + "anyOf": [ + { + "const": "start", + "type": "string" + }, + { + "const": "middle", + "type": "string" + }, + { + "const": "end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [text anchor][1] controls how text is aligned (typically horizontally) relative to its anchor point; it is one of *start*, *end*, or *middle*. If the frame anchor is *left*, *top-left*, or *bottom-left*, the default text anchor is *start*; if the frame anchor is *right*, *top-right*, or\n*bottom-right*, the default is *end*; otherwise it is *middle*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/text-anchor" + }, + "textOverflow": { + "anyOf": [ + { + "type": "null" + }, + { + "const": "clip", + "type": "string" + }, + { + "const": "ellipsis", + "type": "string" + }, + { + "const": "clip-start", + "type": "string" + }, + { + "const": "clip-end", + "type": "string" + }, + { + "const": "ellipsis-start", + "type": "string" + }, + { + "const": "ellipsis-middle", + "type": "string" + }, + { + "const": "ellipsis-end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How truncate (or wrap) lines of text longer than the given **lineWidth**; one of:\n\n- null (default) - preserve overflowing characters (and wrap if needed)\n- *clip* or *clip-end* - remove characters from the end\n- *clip-start* - remove characters from the start\n- *ellipsis* or *ellipsis-end* - replace characters from the end with an ellipsis (…)\n- *ellipsis-start* - replace characters from the start with an ellipsis (…)\n- *ellipsis-middle* - replace characters from the middle with an ellipsis (…)\n\nIf no **title** was specified, if text requires truncation, a title containing the non-truncated text will be implicitly added." + }, + "textPadding": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The padding around the text in pixels; defaults to 8." + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + } + }, + "type": "object" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to generate a tooltip for this mark, and any tip options." + }, + "title": { + "$ref": "#/definitions/ChannelValue", + "description": "The title; a channel specifying accessible, short textual descriptions as strings (possibly with newlines). If the tip option is specified, the title will be displayed with an interactive tooltip instead of using the SVG [title element][1].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/title" + } + }, + "required": [ + "data", + "mark" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "$schema": { + "description": "A [JSON schema](http://json-schema.org/) URL for this specification, such as https://uwdata.github.io/mosaic/schema/latest.json. This property enables validation and autocomplete in editors with JSON schema support.", + "format": "uri", + "type": "string" + }, + "ariaDescription": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-description][1]; a constant textual description.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-description" + }, + "ariaHidden": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-hidden][1] state; a constant indicating whether the element is exposed to an accessibility API.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-hidden" + }, + "ariaLabel": { + "$ref": "#/definitions/ChannelValue", + "description": "The [aria-label][1]; a channel specifying short textual labels representing the value in the accessibility tree.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-label" + }, + "clip": { + "anyOf": [ + { + "const": "frame", + "type": "string" + }, + { + "const": "sphere", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to clip the mark; one of:\n\n- *frame* or true - clip to the plot’s frame (inner area)\n- *sphere* - clip to the projected sphere (*e.g.*, front hemisphere)\n- null or false - do not clip\n\nThe *sphere* clip option requires a geographic projection." + }, + "config": { + "$ref": "#/definitions/Config", + "description": "Configuration options." + }, + "data": { + "$ref": "#/definitions/Data", + "description": "Dataset definitions." + }, + "dx": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The horizontal offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "dy": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The vertical offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "facet": { + "anyOf": [ + { + "const": "auto", + "type": "string" + }, + { + "const": "include", + "type": "string" + }, + { + "const": "exclude", + "type": "string" + }, + { + "const": "super", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to enable or disable faceting; one of:\n\n- *auto* (default) - automatically determine if this mark should be faceted\n- *include* (or true) - draw the subset of the mark’s data in the current facet\n- *exclude* - draw the subset of the mark’s data *not* in the current facet\n- *super* - draw this mark in a single frame that covers all facets\n- null (or false) - repeat this mark’s data across all facets (*i.e.*, no faceting)\n\nWhen a mark uses *super* faceting, it is not allowed to use position scales (*x*, *y*, *fx*, or *fy*); *super* faceting is intended for decorations, such as labels and legends.\n\nWhen top-level faceting is used, the default *auto* setting is equivalent to *include* when the mark data is strictly equal to the top-level facet data; otherwise it is equivalent to null. When the *include* or *exclude* facet mode is chosen, the mark data must be parallel to the top-level facet data: the data must have the same length and order. If the data are not parallel, then the wrong data may be shown in each facet. The default\n*auto* therefore requires strict equality (`===`) for safety, and using the facet data as mark data is recommended when using the *exclude* facet mode. (To construct parallel data safely, consider using [*array*.map][1] on the facet data.)\n\nWhen mark-level faceting is used, the default *auto* setting is equivalent to *include*: the mark will be faceted if either the **fx** or **fy** channel option (or both) is specified. The null or false option will disable faceting, while *exclude* draws the subset of the mark’s data *not* in the current facet.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map" + }, + "facetAnchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "right", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "const": "left", + "type": "string" + }, + { + "const": "top-left", + "type": "string" + }, + { + "const": "top-right", + "type": "string" + }, + { + "const": "bottom-left", + "type": "string" + }, + { + "const": "bottom-right", + "type": "string" + }, + { + "const": "top-empty", + "type": "string" + }, + { + "const": "right-empty", + "type": "string" + }, + { + "const": "bottom-empty", + "type": "string" + }, + { + "const": "left-empty", + "type": "string" + }, + { + "const": "empty", + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to place the mark with respect to facets; one of:\n\n- null (default for most marks) - display the mark in each non-empty facet\n- *top*, *right*, *bottom*, or *left* - display the mark only in facets on the given side\n- *top-empty*, *right-empty*, *bottom-empty*, or *left-empty* (default for axis marks) - display the mark only in facets that have empty space on the given side: either the margin, or an empty facet\n- *empty* - display the mark in empty facets only" + }, + "fill": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill" + }, + "fillOpacity": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill-opacity][1]; a constant number between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill-opacity" + }, + "filter": { + "$ref": "#/definitions/ChannelValue", + "description": "Applies a transform to filter the mark’s index according to the given channel values; only truthy values are retained.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "fx": { + "$ref": "#/definitions/ChannelValue", + "description": "The horizontal facet position channel, for mark-level faceting, bound to the *fx* scale." + }, + "fy": { + "$ref": "#/definitions/ChannelValue", + "description": "The vertical facet position channel, for mark-level faceting, bound to the\n*fy* scale." + }, + "href": { + "$ref": "#/definitions/ChannelValue", + "description": "The [href][1]; a channel specifying URLs for clickable links. May be used in conjunction with the **target** option to open links in another window.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/href" + }, + "imageFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A CSS [filter][1]; a constant string used to adjust the rendering of images, such as *blur(5px)*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/filter" + }, + "margin": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four mark margins: **marginTop**,\n**marginRight**, **marginBottom**, and **marginLeft**; typically defaults to 0, except for axis marks." + }, + "marginBottom": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s bottom margin; the minimum distance in pixels between the bottom edges of the inner and outer plot area." + }, + "marginLeft": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s left margin; the minimum distance in pixels between the left edges of the inner and outer plot area." + }, + "marginRight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s right margin; the minimum distance in pixels between the right edges of the mark’s inner and outer plot area." + }, + "marginTop": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s top margin; the minimum distance in pixels between the top edges of the inner and outer plot area." + }, + "mark": { + "const": "graticule", + "description": "A geo mark whose *data* is a 10° global graticule. (For use with a spherical **projection** only.)", + "type": "string" + }, + "meta": { + "$ref": "#/definitions/Meta", + "description": "Specification metadata." + }, + "mixBlendMode": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [mix-blend-mode][1]; a constant string specifying how to blend content such as *multiply*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode" + }, + "opacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally. For faster rendering, prefer the **strokeOpacity** or **fillOpacity** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/opacity" + }, + "paintOrder": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [paint-order][1]; a constant string specifying the order in which the\n**fill**, **stroke**, and any markers are drawn; defaults to *normal*, which draws the fill, then stroke, then markers; defaults to *stroke* for the text mark to create a “halo” around text to improve legibility.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/paint-order" + }, + "params": { + "$ref": "#/definitions/Params", + "description": "Param and Selection definitions." + }, + "plotDefaults": { + "$ref": "#/definitions/PlotAttributes", + "description": "A default set of attributes to apply to all plot components." + }, + "pointerEvents": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [pointer-events][1] property; a constant string such as *none*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/pointer-events" + }, + "reverse": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Applies a transform to reverse the order of the mark’s index, say for reverse input order." + }, + "select": { + "$ref": "#/definitions/SelectFilter", + "description": "Applies a filter transform after data is loaded to highlight selected values only. For example, `first` and `last` select the first or last values of series only (using the *z* channel to separate series). Meanwhile, `nearestX` and `nearestY` select the point nearest to the pointer along the *x* or *y* channel dimension. Unlike Mosaic selections, a mark level *select* is internal to the mark only, and does not populate a param or selection value to be shared across clients.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "shapeRendering": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [shape-rendering][1]; a constant string such as *crispEdges*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/shape-rendering" + }, + "sort": { + "anyOf": [ + { + "$ref": "#/definitions/SortOrder" + }, + { + "$ref": "#/definitions/ChannelDomainSort" + } + ], + "description": "Either applies a transform to sort the mark’s index by the specified channel values, or imputes ordinal scale domains from this mark’s channels.\n\nWhen imputing ordinal scale domains from channel values, the **sort** option is an object whose keys are ordinal scale names such as *x* or *fx*, and whose values are channel names such as *y*, *y1*, or *y2*. For example, to impute the *y* scale’s domain from the associated *x* channel values in ascending order:\n\n```js sort: {y: \"x\"} ```\n\nFor different sort options for different scales, replace the channel name with a *value* object and per-scale options:\n\n```js sort: {y: {value: \"-x\"}} ```\n\nWhen sorting the mark’s index, the **sort** option is instead one of:\n\n- a channel value definition for sorting given values in ascending order\n- a {value, order} object for sorting given values\n- a {channel, order} object for sorting the named channel’s values" + }, + "stroke": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke" + }, + "strokeDasharray": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dasharray][1]; a constant number indicating the length in pixels of alternating dashes and gaps, or a constant string of numbers separated by spaces or commas (_e.g._, *10 2* for dashes of 10 pixels separated by gaps of 2 pixels), or *none* (the default) for no dashing\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dasharray" + }, + "strokeDashoffset": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dashoffset][1]; a constant indicating the offset in pixels of the first dash along the stroke; defaults to zero.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dashoffset" + }, + "strokeLinecap": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linecap][1]; a constant specifying how to cap stroked paths, such as *butt*, *round*, or *square*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linecap" + }, + "strokeLinejoin": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linejoin][1]; a constant specifying how to join stroked paths, such as *bevel*, *miter*, *miter-clip*, or *round*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linejoin" + }, + "strokeMiterlimit": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-miterlimit][1]; a constant number specifying how to limit the length of *miter* joins on stroked paths.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-miterlimit" + }, + "strokeOpacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-opacity" + }, + "strokeWidth": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-width][1]; a constant number in pixels, or a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-width" + }, + "target": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [target][1]; a constant string specifying the target window (_e.g._,\n*_blank*) for clickable links; used in conjunction with the **href** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/target" + }, + "tip": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/TipPointer" + }, + { + "properties": { + "anchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The tip anchor specifies how to orient the tip box relative to its anchor position; it refers to the part of the tip box that is attached to the anchor point. For example, the *top-left* anchor places the top-left corner of tip box near the anchor position, hence placing the tip box below and to the right of the anchor position." + }, + "fontFamily": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font-family][1]; a constant; defaults to the plot’s font family, which is typically [*system-ui*][2].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-family [2]: https://drafts.csswg.org/css-fonts-4/#valdef-font-family-system-ui" + }, + "fontSize": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font size][1] in pixels; either a constant or a channel; defaults to the plot’s font size, which is typically 10. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-size" + }, + "fontStyle": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font style][1]; a constant; defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-style" + }, + "fontVariant": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font variant][1]; a constant; if the **text** channel contains numbers or dates, defaults to *tabular-nums* to facilitate comparing numbers; otherwise defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant" + }, + "fontWeight": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font weight][1]; a constant; defaults to the plot’s font weight, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight" + }, + "format": { + "additionalProperties": false, + "description": "How channel values are formatted for display. If a format is a string, it is interpreted as a (UTC) time format for temporal channels, and otherwise a number format.", + "properties": { + "ariaLabel": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fill": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fillOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fontSize": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fx": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fy": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "geometry": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "height": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "href": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "length": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "opacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "path": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "r": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "rotate": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "src": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "stroke": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeWidth": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "symbol": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "text": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "title": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "weight": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "width": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "z": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + } + }, + "type": "object" + }, + "frameAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The frame anchor specifies defaults for **x** and **y** based on the plot’s frame; it may be one of the four sides (*top*, *right*, *bottom*, *left*), one of the four corners (*top-left*, *top-right*, *bottom-right*,\n*bottom-left*), or the *middle* of the frame. For example, for tips distributed horizontally at the top of the frame:\n\n```js Plot.tip(data, {x: \"date\", frameAnchor: \"top\"}) ```" + }, + "lineHeight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line height in ems; defaults to 1. The line height affects the (typically vertical) separation between adjacent baselines of text, as well as the separation between the text and its anchor point." + }, + "lineWidth": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line width in ems (e.g., 10 for about 20 characters); defaults to infinity, disabling wrapping and clipping.\n\nIf **textOverflow** is null, lines will be wrapped at the specified length. If a line is split at a soft hyphen (\\xad), a hyphen (-) will be displayed at the end of the line. If **textOverflow** is not null, lines will be clipped according to the given strategy." + }, + "monospace": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, changes the default **fontFamily** to *monospace*, and uses simplified monospaced text metrics calculations." + }, + "pathFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The image filter for the tip’s box; defaults to a drop shadow." + }, + "pointer": { + "$ref": "#/definitions/TipPointer" + }, + "pointerSize": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The size of the tip’s pointer in pixels; defaults to 12." + }, + "preferredAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If an explicit tip anchor is not specified, an anchor is chosen automatically such that the tip fits within the plot’s frame; if the preferred anchor fits, it is chosen." + }, + "textAnchor": { + "anyOf": [ + { + "const": "start", + "type": "string" + }, + { + "const": "middle", + "type": "string" + }, + { + "const": "end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [text anchor][1] controls how text is aligned (typically horizontally) relative to its anchor point; it is one of *start*, *end*, or *middle*. If the frame anchor is *left*, *top-left*, or *bottom-left*, the default text anchor is *start*; if the frame anchor is *right*, *top-right*, or\n*bottom-right*, the default is *end*; otherwise it is *middle*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/text-anchor" + }, + "textOverflow": { + "anyOf": [ + { + "type": "null" + }, + { + "const": "clip", + "type": "string" + }, + { + "const": "ellipsis", + "type": "string" + }, + { + "const": "clip-start", + "type": "string" + }, + { + "const": "clip-end", + "type": "string" + }, + { + "const": "ellipsis-start", + "type": "string" + }, + { + "const": "ellipsis-middle", + "type": "string" + }, + { + "const": "ellipsis-end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How truncate (or wrap) lines of text longer than the given **lineWidth**; one of:\n\n- null (default) - preserve overflowing characters (and wrap if needed)\n- *clip* or *clip-end* - remove characters from the end\n- *clip-start* - remove characters from the start\n- *ellipsis* or *ellipsis-end* - replace characters from the end with an ellipsis (…)\n- *ellipsis-start* - replace characters from the start with an ellipsis (…)\n- *ellipsis-middle* - replace characters from the middle with an ellipsis (…)\n\nIf no **title** was specified, if text requires truncation, a title containing the non-truncated text will be implicitly added." + }, + "textPadding": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The padding around the text in pixels; defaults to 8." + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + } + }, + "type": "object" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to generate a tooltip for this mark, and any tip options." + }, + "title": { + "$ref": "#/definitions/ChannelValue", + "description": "The title; a channel specifying accessible, short textual descriptions as strings (possibly with newlines). If the tip option is specified, the title will be displayed with an interactive tooltip instead of using the SVG [title element][1].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/title" + } + }, + "required": [ + "mark" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "$schema": { + "description": "A [JSON schema](http://json-schema.org/) URL for this specification, such as https://uwdata.github.io/mosaic/schema/latest.json. This property enables validation and autocomplete in editors with JSON schema support.", + "format": "uri", + "type": "string" + }, + "ariaDescription": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-description][1]; a constant textual description.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-description" + }, + "ariaHidden": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-hidden][1] state; a constant indicating whether the element is exposed to an accessibility API.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-hidden" + }, + "ariaLabel": { + "$ref": "#/definitions/ChannelValue", + "description": "The [aria-label][1]; a channel specifying short textual labels representing the value in the accessibility tree.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-label" + }, + "clip": { + "anyOf": [ + { + "const": "frame", + "type": "string" + }, + { + "const": "sphere", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to clip the mark; one of:\n\n- *frame* or true - clip to the plot’s frame (inner area)\n- *sphere* - clip to the projected sphere (*e.g.*, front hemisphere)\n- null or false - do not clip\n\nThe *sphere* clip option requires a geographic projection." + }, + "config": { + "$ref": "#/definitions/Config", + "description": "Configuration options." + }, + "data": { + "$ref": "#/definitions/Data", + "description": "Dataset definitions." + }, + "dx": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The horizontal offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "dy": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The vertical offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "facet": { + "anyOf": [ + { + "const": "auto", + "type": "string" + }, + { + "const": "include", + "type": "string" + }, + { + "const": "exclude", + "type": "string" + }, + { + "const": "super", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to enable or disable faceting; one of:\n\n- *auto* (default) - automatically determine if this mark should be faceted\n- *include* (or true) - draw the subset of the mark’s data in the current facet\n- *exclude* - draw the subset of the mark’s data *not* in the current facet\n- *super* - draw this mark in a single frame that covers all facets\n- null (or false) - repeat this mark’s data across all facets (*i.e.*, no faceting)\n\nWhen a mark uses *super* faceting, it is not allowed to use position scales (*x*, *y*, *fx*, or *fy*); *super* faceting is intended for decorations, such as labels and legends.\n\nWhen top-level faceting is used, the default *auto* setting is equivalent to *include* when the mark data is strictly equal to the top-level facet data; otherwise it is equivalent to null. When the *include* or *exclude* facet mode is chosen, the mark data must be parallel to the top-level facet data: the data must have the same length and order. If the data are not parallel, then the wrong data may be shown in each facet. The default\n*auto* therefore requires strict equality (`===`) for safety, and using the facet data as mark data is recommended when using the *exclude* facet mode. (To construct parallel data safely, consider using [*array*.map][1] on the facet data.)\n\nWhen mark-level faceting is used, the default *auto* setting is equivalent to *include*: the mark will be faceted if either the **fx** or **fy** channel option (or both) is specified. The null or false option will disable faceting, while *exclude* draws the subset of the mark’s data *not* in the current facet.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map" + }, + "facetAnchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "right", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "const": "left", + "type": "string" + }, + { + "const": "top-left", + "type": "string" + }, + { + "const": "top-right", + "type": "string" + }, + { + "const": "bottom-left", + "type": "string" + }, + { + "const": "bottom-right", + "type": "string" + }, + { + "const": "top-empty", + "type": "string" + }, + { + "const": "right-empty", + "type": "string" + }, + { + "const": "bottom-empty", + "type": "string" + }, + { + "const": "left-empty", + "type": "string" + }, + { + "const": "empty", + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to place the mark with respect to facets; one of:\n\n- null (default for most marks) - display the mark in each non-empty facet\n- *top*, *right*, *bottom*, or *left* - display the mark only in facets on the given side\n- *top-empty*, *right-empty*, *bottom-empty*, or *left-empty* (default for axis marks) - display the mark only in facets that have empty space on the given side: either the margin, or an empty facet\n- *empty* - display the mark in empty facets only" + }, + "fill": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill" + }, + "fillOpacity": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill-opacity][1]; a constant number between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill-opacity" + }, + "filter": { + "$ref": "#/definitions/ChannelValue", + "description": "Applies a transform to filter the mark’s index according to the given channel values; only truthy values are retained.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "fx": { + "$ref": "#/definitions/ChannelValue", + "description": "The horizontal facet position channel, for mark-level faceting, bound to the *fx* scale." + }, + "fy": { + "$ref": "#/definitions/ChannelValue", + "description": "The vertical facet position channel, for mark-level faceting, bound to the\n*fy* scale." + }, + "href": { + "$ref": "#/definitions/ChannelValue", + "description": "The [href][1]; a channel specifying URLs for clickable links. May be used in conjunction with the **target** option to open links in another window.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/href" + }, + "imageFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A CSS [filter][1]; a constant string used to adjust the rendering of images, such as *blur(5px)*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/filter" + }, + "margin": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four mark margins: **marginTop**,\n**marginRight**, **marginBottom**, and **marginLeft**; typically defaults to 0, except for axis marks." + }, + "marginBottom": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s bottom margin; the minimum distance in pixels between the bottom edges of the inner and outer plot area." + }, + "marginLeft": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s left margin; the minimum distance in pixels between the left edges of the inner and outer plot area." + }, + "marginRight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s right margin; the minimum distance in pixels between the right edges of the mark’s inner and outer plot area." + }, + "marginTop": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s top margin; the minimum distance in pixels between the top edges of the inner and outer plot area." + }, + "mark": { + "const": "sphere", + "description": "A geo mark whose *data* is the outline of the sphere on the projection’s plane. (For use with a spherical **projection** only.)", + "type": "string" + }, + "meta": { + "$ref": "#/definitions/Meta", + "description": "Specification metadata." + }, + "mixBlendMode": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [mix-blend-mode][1]; a constant string specifying how to blend content such as *multiply*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode" + }, + "opacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally. For faster rendering, prefer the **strokeOpacity** or **fillOpacity** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/opacity" + }, + "paintOrder": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [paint-order][1]; a constant string specifying the order in which the\n**fill**, **stroke**, and any markers are drawn; defaults to *normal*, which draws the fill, then stroke, then markers; defaults to *stroke* for the text mark to create a “halo” around text to improve legibility.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/paint-order" + }, + "params": { + "$ref": "#/definitions/Params", + "description": "Param and Selection definitions." + }, + "plotDefaults": { + "$ref": "#/definitions/PlotAttributes", + "description": "A default set of attributes to apply to all plot components." + }, + "pointerEvents": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [pointer-events][1] property; a constant string such as *none*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/pointer-events" + }, + "reverse": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Applies a transform to reverse the order of the mark’s index, say for reverse input order." + }, + "select": { + "$ref": "#/definitions/SelectFilter", + "description": "Applies a filter transform after data is loaded to highlight selected values only. For example, `first` and `last` select the first or last values of series only (using the *z* channel to separate series). Meanwhile, `nearestX` and `nearestY` select the point nearest to the pointer along the *x* or *y* channel dimension. Unlike Mosaic selections, a mark level *select* is internal to the mark only, and does not populate a param or selection value to be shared across clients.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "shapeRendering": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [shape-rendering][1]; a constant string such as *crispEdges*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/shape-rendering" + }, + "sort": { + "anyOf": [ + { + "$ref": "#/definitions/SortOrder" + }, + { + "$ref": "#/definitions/ChannelDomainSort" + } + ], + "description": "Either applies a transform to sort the mark’s index by the specified channel values, or imputes ordinal scale domains from this mark’s channels.\n\nWhen imputing ordinal scale domains from channel values, the **sort** option is an object whose keys are ordinal scale names such as *x* or *fx*, and whose values are channel names such as *y*, *y1*, or *y2*. For example, to impute the *y* scale’s domain from the associated *x* channel values in ascending order:\n\n```js sort: {y: \"x\"} ```\n\nFor different sort options for different scales, replace the channel name with a *value* object and per-scale options:\n\n```js sort: {y: {value: \"-x\"}} ```\n\nWhen sorting the mark’s index, the **sort** option is instead one of:\n\n- a channel value definition for sorting given values in ascending order\n- a {value, order} object for sorting given values\n- a {channel, order} object for sorting the named channel’s values" + }, + "stroke": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke" + }, + "strokeDasharray": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dasharray][1]; a constant number indicating the length in pixels of alternating dashes and gaps, or a constant string of numbers separated by spaces or commas (_e.g._, *10 2* for dashes of 10 pixels separated by gaps of 2 pixels), or *none* (the default) for no dashing\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dasharray" + }, + "strokeDashoffset": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dashoffset][1]; a constant indicating the offset in pixels of the first dash along the stroke; defaults to zero.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dashoffset" + }, + "strokeLinecap": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linecap][1]; a constant specifying how to cap stroked paths, such as *butt*, *round*, or *square*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linecap" + }, + "strokeLinejoin": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linejoin][1]; a constant specifying how to join stroked paths, such as *bevel*, *miter*, *miter-clip*, or *round*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linejoin" + }, + "strokeMiterlimit": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-miterlimit][1]; a constant number specifying how to limit the length of *miter* joins on stroked paths.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-miterlimit" + }, + "strokeOpacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-opacity" + }, + "strokeWidth": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-width][1]; a constant number in pixels, or a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-width" + }, + "target": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [target][1]; a constant string specifying the target window (_e.g._,\n*_blank*) for clickable links; used in conjunction with the **href** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/target" + }, + "tip": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/TipPointer" + }, + { + "properties": { + "anchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The tip anchor specifies how to orient the tip box relative to its anchor position; it refers to the part of the tip box that is attached to the anchor point. For example, the *top-left* anchor places the top-left corner of tip box near the anchor position, hence placing the tip box below and to the right of the anchor position." + }, + "fontFamily": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font-family][1]; a constant; defaults to the plot’s font family, which is typically [*system-ui*][2].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-family [2]: https://drafts.csswg.org/css-fonts-4/#valdef-font-family-system-ui" + }, + "fontSize": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font size][1] in pixels; either a constant or a channel; defaults to the plot’s font size, which is typically 10. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-size" + }, + "fontStyle": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font style][1]; a constant; defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-style" + }, + "fontVariant": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font variant][1]; a constant; if the **text** channel contains numbers or dates, defaults to *tabular-nums* to facilitate comparing numbers; otherwise defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant" + }, + "fontWeight": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font weight][1]; a constant; defaults to the plot’s font weight, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight" + }, + "format": { + "additionalProperties": false, + "description": "How channel values are formatted for display. If a format is a string, it is interpreted as a (UTC) time format for temporal channels, and otherwise a number format.", + "properties": { + "ariaLabel": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fill": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fillOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fontSize": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fx": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fy": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "geometry": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "height": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "href": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "length": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "opacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "path": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "r": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "rotate": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "src": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "stroke": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeWidth": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "symbol": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "text": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "title": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "weight": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "width": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "z": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + } + }, + "type": "object" + }, + "frameAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The frame anchor specifies defaults for **x** and **y** based on the plot’s frame; it may be one of the four sides (*top*, *right*, *bottom*, *left*), one of the four corners (*top-left*, *top-right*, *bottom-right*,\n*bottom-left*), or the *middle* of the frame. For example, for tips distributed horizontally at the top of the frame:\n\n```js Plot.tip(data, {x: \"date\", frameAnchor: \"top\"}) ```" + }, + "lineHeight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line height in ems; defaults to 1. The line height affects the (typically vertical) separation between adjacent baselines of text, as well as the separation between the text and its anchor point." + }, + "lineWidth": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line width in ems (e.g., 10 for about 20 characters); defaults to infinity, disabling wrapping and clipping.\n\nIf **textOverflow** is null, lines will be wrapped at the specified length. If a line is split at a soft hyphen (\\xad), a hyphen (-) will be displayed at the end of the line. If **textOverflow** is not null, lines will be clipped according to the given strategy." + }, + "monospace": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, changes the default **fontFamily** to *monospace*, and uses simplified monospaced text metrics calculations." + }, + "pathFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The image filter for the tip’s box; defaults to a drop shadow." + }, + "pointer": { + "$ref": "#/definitions/TipPointer" + }, + "pointerSize": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The size of the tip’s pointer in pixels; defaults to 12." + }, + "preferredAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If an explicit tip anchor is not specified, an anchor is chosen automatically such that the tip fits within the plot’s frame; if the preferred anchor fits, it is chosen." + }, + "textAnchor": { + "anyOf": [ + { + "const": "start", + "type": "string" + }, + { + "const": "middle", + "type": "string" + }, + { + "const": "end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [text anchor][1] controls how text is aligned (typically horizontally) relative to its anchor point; it is one of *start*, *end*, or *middle*. If the frame anchor is *left*, *top-left*, or *bottom-left*, the default text anchor is *start*; if the frame anchor is *right*, *top-right*, or\n*bottom-right*, the default is *end*; otherwise it is *middle*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/text-anchor" + }, + "textOverflow": { + "anyOf": [ + { + "type": "null" + }, + { + "const": "clip", + "type": "string" + }, + { + "const": "ellipsis", + "type": "string" + }, + { + "const": "clip-start", + "type": "string" + }, + { + "const": "clip-end", + "type": "string" + }, + { + "const": "ellipsis-start", + "type": "string" + }, + { + "const": "ellipsis-middle", + "type": "string" + }, + { + "const": "ellipsis-end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How truncate (or wrap) lines of text longer than the given **lineWidth**; one of:\n\n- null (default) - preserve overflowing characters (and wrap if needed)\n- *clip* or *clip-end* - remove characters from the end\n- *clip-start* - remove characters from the start\n- *ellipsis* or *ellipsis-end* - replace characters from the end with an ellipsis (…)\n- *ellipsis-start* - replace characters from the start with an ellipsis (…)\n- *ellipsis-middle* - replace characters from the middle with an ellipsis (…)\n\nIf no **title** was specified, if text requires truncation, a title containing the non-truncated text will be implicitly added." + }, + "textPadding": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The padding around the text in pixels; defaults to 8." + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + } + }, + "type": "object" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to generate a tooltip for this mark, and any tip options." + }, + "title": { + "$ref": "#/definitions/ChannelValue", + "description": "The title; a channel specifying accessible, short textual descriptions as strings (possibly with newlines). If the tip option is specified, the title will be displayed with an interactive tooltip instead of using the SVG [title element][1].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/title" + } + }, + "required": [ + "mark" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "$schema": { + "description": "A [JSON schema](http://json-schema.org/) URL for this specification, such as https://uwdata.github.io/mosaic/schema/latest.json. This property enables validation and autocomplete in editors with JSON schema support.", + "format": "uri", + "type": "string" + }, + "ariaDescription": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-description][1]; a constant textual description.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-description" + }, + "ariaHidden": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-hidden][1] state; a constant indicating whether the element is exposed to an accessibility API.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-hidden" + }, + "ariaLabel": { + "$ref": "#/definitions/ChannelValue", + "description": "The [aria-label][1]; a channel specifying short textual labels representing the value in the accessibility tree.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-label" + }, + "binWidth": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The distance between centers of neighboring hexagons, in pixels; defaults to 20. If also using a hexgrid mark, use matching **binWidth** values." + }, + "clip": { + "anyOf": [ + { + "const": "frame", + "type": "string" + }, + { + "const": "sphere", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to clip the mark; one of:\n\n- *frame* or true - clip to the plot’s frame (inner area)\n- *sphere* - clip to the projected sphere (*e.g.*, front hemisphere)\n- null or false - do not clip\n\nThe *sphere* clip option requires a geographic projection." + }, + "config": { + "$ref": "#/definitions/Config", + "description": "Configuration options." + }, + "data": { + "$ref": "#/definitions/Data", + "description": "Dataset definitions." + }, + "dx": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The horizontal offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "dy": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The vertical offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "facet": { + "anyOf": [ + { + "const": "auto", + "type": "string" + }, + { + "const": "include", + "type": "string" + }, + { + "const": "exclude", + "type": "string" + }, + { + "const": "super", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to enable or disable faceting; one of:\n\n- *auto* (default) - automatically determine if this mark should be faceted\n- *include* (or true) - draw the subset of the mark’s data in the current facet\n- *exclude* - draw the subset of the mark’s data *not* in the current facet\n- *super* - draw this mark in a single frame that covers all facets\n- null (or false) - repeat this mark’s data across all facets (*i.e.*, no faceting)\n\nWhen a mark uses *super* faceting, it is not allowed to use position scales (*x*, *y*, *fx*, or *fy*); *super* faceting is intended for decorations, such as labels and legends.\n\nWhen top-level faceting is used, the default *auto* setting is equivalent to *include* when the mark data is strictly equal to the top-level facet data; otherwise it is equivalent to null. When the *include* or *exclude* facet mode is chosen, the mark data must be parallel to the top-level facet data: the data must have the same length and order. If the data are not parallel, then the wrong data may be shown in each facet. The default\n*auto* therefore requires strict equality (`===`) for safety, and using the facet data as mark data is recommended when using the *exclude* facet mode. (To construct parallel data safely, consider using [*array*.map][1] on the facet data.)\n\nWhen mark-level faceting is used, the default *auto* setting is equivalent to *include*: the mark will be faceted if either the **fx** or **fy** channel option (or both) is specified. The null or false option will disable faceting, while *exclude* draws the subset of the mark’s data *not* in the current facet.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map" + }, + "facetAnchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "right", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "const": "left", + "type": "string" + }, + { + "const": "top-left", + "type": "string" + }, + { + "const": "top-right", + "type": "string" + }, + { + "const": "bottom-left", + "type": "string" + }, + { + "const": "bottom-right", + "type": "string" + }, + { + "const": "top-empty", + "type": "string" + }, + { + "const": "right-empty", + "type": "string" + }, + { + "const": "bottom-empty", + "type": "string" + }, + { + "const": "left-empty", + "type": "string" + }, + { + "const": "empty", + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to place the mark with respect to facets; one of:\n\n- null (default for most marks) - display the mark in each non-empty facet\n- *top*, *right*, *bottom*, or *left* - display the mark only in facets on the given side\n- *top-empty*, *right-empty*, *bottom-empty*, or *left-empty* (default for axis marks) - display the mark only in facets that have empty space on the given side: either the margin, or an empty facet\n- *empty* - display the mark in empty facets only" + }, + "fill": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill" + }, + "fillOpacity": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill-opacity][1]; a constant number between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill-opacity" + }, + "filter": { + "$ref": "#/definitions/ChannelValue", + "description": "Applies a transform to filter the mark’s index according to the given channel values; only truthy values are retained.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "fontFamily": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font-family][1]; a constant; defaults to the plot’s font family, which is typically [*system-ui*][2].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-family [2]: https://drafts.csswg.org/css-fonts-4/#valdef-font-family-system-ui" + }, + "fontSize": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font size][1] in pixels; either a constant or a channel; defaults to the plot’s font size, which is typically 10. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-size" + }, + "fontStyle": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font style][1]; a constant; defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-style" + }, + "fontVariant": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font variant][1]; a constant; if the **text** channel contains numbers or dates, defaults to *tabular-nums* to facilitate comparing numbers; otherwise defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant" + }, + "fontWeight": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font weight][1]; a constant; defaults to the plot’s font weight, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight" + }, + "frameAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The frame anchor specifies defaults for **x** and **y** based on the plot’s frame; it may be one of the four sides (*top*, *right*, *bottom*, *left*), one of the four corners (*top-left*, *top-right*, *bottom-right*,\n*bottom-left*), or the *middle* of the frame. For example, for dots distributed horizontally at the top of the frame:\n\n```js Plot.dot(data, {x: \"date\", frameAnchor: \"top\"}) ```" + }, + "fx": { + "$ref": "#/definitions/ChannelValue", + "description": "The horizontal facet position channel, for mark-level faceting, bound to the *fx* scale." + }, + "fy": { + "$ref": "#/definitions/ChannelValue", + "description": "The vertical facet position channel, for mark-level faceting, bound to the\n*fy* scale." + }, + "href": { + "$ref": "#/definitions/ChannelValue", + "description": "The [href][1]; a channel specifying URLs for clickable links. May be used in conjunction with the **target** option to open links in another window.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/href" + }, + "imageFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A CSS [filter][1]; a constant string used to adjust the rendering of images, such as *blur(5px)*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/filter" + }, + "lineHeight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line height in ems; defaults to 1. The line height affects the (typically vertical) separation between adjacent baselines of text, as well as the separation between the text and its anchor point." + }, + "lineWidth": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line width in ems (e.g., 10 for about 20 characters); defaults to infinity, disabling wrapping and clipping.\n\nIf **textOverflow** is null, lines will be wrapped at the specified length. If a line is split at a soft hyphen (\\xad), a hyphen (-) will be displayed at the end of the line. If **textOverflow** is not null, lines will be clipped according to the given strategy." + }, + "margin": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four mark margins: **marginTop**,\n**marginRight**, **marginBottom**, and **marginLeft**; typically defaults to 0, except for axis marks." + }, + "marginBottom": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s bottom margin; the minimum distance in pixels between the bottom edges of the inner and outer plot area." + }, + "marginLeft": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s left margin; the minimum distance in pixels between the left edges of the inner and outer plot area." + }, + "marginRight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s right margin; the minimum distance in pixels between the right edges of the mark’s inner and outer plot area." + }, + "marginTop": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s top margin; the minimum distance in pixels between the top edges of the inner and outer plot area." + }, + "mark": { + "const": "hexbin", + "description": "A hexbin mark that bins **x** and **y** data into a hexagonal grid and visualizes aggregate functions per bin (e.g., count for binned density). Aggregate functions can be used for fill, stroke, or r (radius) options.", + "type": "string" + }, + "meta": { + "$ref": "#/definitions/Meta", + "description": "Specification metadata." + }, + "mixBlendMode": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [mix-blend-mode][1]; a constant string specifying how to blend content such as *multiply*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode" + }, + "monospace": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, changes the default **fontFamily** to *monospace*, and uses simplified monospaced text metrics calculations." + }, + "opacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally. For faster rendering, prefer the **strokeOpacity** or **fillOpacity** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/opacity" + }, + "paintOrder": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [paint-order][1]; a constant string specifying the order in which the\n**fill**, **stroke**, and any markers are drawn; defaults to *normal*, which draws the fill, then stroke, then markers; defaults to *stroke* for the text mark to create a “halo” around text to improve legibility.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/paint-order" + }, + "params": { + "$ref": "#/definitions/Params", + "description": "Param and Selection definitions." + }, + "plotDefaults": { + "$ref": "#/definitions/PlotAttributes", + "description": "A default set of attributes to apply to all plot components." + }, + "pointerEvents": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [pointer-events][1] property; a constant string such as *none*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/pointer-events" + }, + "r": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The radius of dots; either a channel or constant. When a number, it is interpreted as a constant radius in pixels. Otherwise it is interpreted as a channel, typically bound to the *r* channel, which defaults to the *sqrt* type for proportional symbols. The radius defaults to 4.5 pixels when using the **symbol** channel, and otherwise 3 pixels. Dots with a nonpositive radius are not drawn." + }, + "reverse": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Applies a transform to reverse the order of the mark’s index, say for reverse input order." + }, + "rotate": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The rotation angle of dots in degrees clockwise; either a channel or a constant. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel. Defaults to 0°, pointing up." + }, + "select": { + "$ref": "#/definitions/SelectFilter", + "description": "Applies a filter transform after data is loaded to highlight selected values only. For example, `first` and `last` select the first or last values of series only (using the *z* channel to separate series). Meanwhile, `nearestX` and `nearestY` select the point nearest to the pointer along the *x* or *y* channel dimension. Unlike Mosaic selections, a mark level *select* is internal to the mark only, and does not populate a param or selection value to be shared across clients.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "shapeRendering": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [shape-rendering][1]; a constant string such as *crispEdges*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/shape-rendering" + }, + "sort": { + "anyOf": [ + { + "$ref": "#/definitions/SortOrder" + }, + { + "$ref": "#/definitions/ChannelDomainSort" + } + ], + "description": "Either applies a transform to sort the mark’s index by the specified channel values, or imputes ordinal scale domains from this mark’s channels.\n\nWhen imputing ordinal scale domains from channel values, the **sort** option is an object whose keys are ordinal scale names such as *x* or *fx*, and whose values are channel names such as *y*, *y1*, or *y2*. For example, to impute the *y* scale’s domain from the associated *x* channel values in ascending order:\n\n```js sort: {y: \"x\"} ```\n\nFor different sort options for different scales, replace the channel name with a *value* object and per-scale options:\n\n```js sort: {y: {value: \"-x\"}} ```\n\nWhen sorting the mark’s index, the **sort** option is instead one of:\n\n- a channel value definition for sorting given values in ascending order\n- a {value, order} object for sorting given values\n- a {channel, order} object for sorting the named channel’s values" + }, + "stroke": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke" + }, + "strokeDasharray": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dasharray][1]; a constant number indicating the length in pixels of alternating dashes and gaps, or a constant string of numbers separated by spaces or commas (_e.g._, *10 2* for dashes of 10 pixels separated by gaps of 2 pixels), or *none* (the default) for no dashing\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dasharray" + }, + "strokeDashoffset": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dashoffset][1]; a constant indicating the offset in pixels of the first dash along the stroke; defaults to zero.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dashoffset" + }, + "strokeLinecap": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linecap][1]; a constant specifying how to cap stroked paths, such as *butt*, *round*, or *square*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linecap" + }, + "strokeLinejoin": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linejoin][1]; a constant specifying how to join stroked paths, such as *bevel*, *miter*, *miter-clip*, or *round*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linejoin" + }, + "strokeMiterlimit": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-miterlimit][1]; a constant number specifying how to limit the length of *miter* joins on stroked paths.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-miterlimit" + }, + "strokeOpacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-opacity" + }, + "strokeWidth": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-width][1]; a constant number in pixels, or a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-width" + }, + "symbol": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/SymbolType" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The categorical symbol; either a channel or a constant. A constant symbol can be specified by a valid symbol name such as *star*, or a symbol object (implementing the draw method); otherwise it is interpreted as a channel. Defaults to *circle* for the **dot** mark, and *hexagon* for the\n**hexagon** mark.\n\nIf the **symbol** channel’s values are all symbols, symbol names, or nullish, the channel is unscaled (values are interpreted literally); otherwise, the channel is bound to the *symbol* scale." + }, + "target": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [target][1]; a constant string specifying the target window (_e.g._,\n*_blank*) for clickable links; used in conjunction with the **href** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/target" + }, + "textAnchor": { + "anyOf": [ + { + "const": "start", + "type": "string" + }, + { + "const": "middle", + "type": "string" + }, + { + "const": "end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [text anchor][1] controls how text is aligned (typically horizontally) relative to its anchor point; it is one of *start*, *end*, or *middle*. If the frame anchor is *left*, *top-left*, or *bottom-left*, the default text anchor is *start*; if the frame anchor is *right*, *top-right*, or\n*bottom-right*, the default is *end*; otherwise it is *middle*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/text-anchor" + }, + "textOverflow": { + "anyOf": [ + { + "type": "null" + }, + { + "const": "clip", + "type": "string" + }, + { + "const": "ellipsis", + "type": "string" + }, + { + "const": "clip-start", + "type": "string" + }, + { + "const": "clip-end", + "type": "string" + }, + { + "const": "ellipsis-start", + "type": "string" + }, + { + "const": "ellipsis-middle", + "type": "string" + }, + { + "const": "ellipsis-end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How truncate (or wrap) lines of text longer than the given **lineWidth**; one of:\n\n- null (default) - preserve overflowing characters (and wrap if needed)\n- *clip* or *clip-end* - remove characters from the end\n- *clip-start* - remove characters from the start\n- *ellipsis* or *ellipsis-end* - replace characters from the end with an ellipsis (…)\n- *ellipsis-start* - replace characters from the start with an ellipsis (…)\n- *ellipsis-middle* - replace characters from the middle with an ellipsis (…)\n\nIf no **title** was specified, if text requires truncation, a title containing the non-truncated text will be implicitly added." + }, + "tip": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/TipPointer" + }, + { + "properties": { + "anchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The tip anchor specifies how to orient the tip box relative to its anchor position; it refers to the part of the tip box that is attached to the anchor point. For example, the *top-left* anchor places the top-left corner of tip box near the anchor position, hence placing the tip box below and to the right of the anchor position." + }, + "fontFamily": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font-family][1]; a constant; defaults to the plot’s font family, which is typically [*system-ui*][2].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-family [2]: https://drafts.csswg.org/css-fonts-4/#valdef-font-family-system-ui" + }, + "fontSize": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font size][1] in pixels; either a constant or a channel; defaults to the plot’s font size, which is typically 10. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-size" + }, + "fontStyle": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font style][1]; a constant; defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-style" + }, + "fontVariant": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font variant][1]; a constant; if the **text** channel contains numbers or dates, defaults to *tabular-nums* to facilitate comparing numbers; otherwise defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant" + }, + "fontWeight": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font weight][1]; a constant; defaults to the plot’s font weight, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight" + }, + "format": { + "additionalProperties": false, + "description": "How channel values are formatted for display. If a format is a string, it is interpreted as a (UTC) time format for temporal channels, and otherwise a number format.", + "properties": { + "ariaLabel": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fill": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fillOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fontSize": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fx": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fy": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "geometry": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "height": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "href": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "length": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "opacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "path": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "r": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "rotate": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "src": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "stroke": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeWidth": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "symbol": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "text": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "title": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "weight": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "width": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "z": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + } + }, + "type": "object" + }, + "frameAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The frame anchor specifies defaults for **x** and **y** based on the plot’s frame; it may be one of the four sides (*top*, *right*, *bottom*, *left*), one of the four corners (*top-left*, *top-right*, *bottom-right*,\n*bottom-left*), or the *middle* of the frame. For example, for tips distributed horizontally at the top of the frame:\n\n```js Plot.tip(data, {x: \"date\", frameAnchor: \"top\"}) ```" + }, + "lineHeight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line height in ems; defaults to 1. The line height affects the (typically vertical) separation between adjacent baselines of text, as well as the separation between the text and its anchor point." + }, + "lineWidth": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line width in ems (e.g., 10 for about 20 characters); defaults to infinity, disabling wrapping and clipping.\n\nIf **textOverflow** is null, lines will be wrapped at the specified length. If a line is split at a soft hyphen (\\xad), a hyphen (-) will be displayed at the end of the line. If **textOverflow** is not null, lines will be clipped according to the given strategy." + }, + "monospace": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, changes the default **fontFamily** to *monospace*, and uses simplified monospaced text metrics calculations." + }, + "pathFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The image filter for the tip’s box; defaults to a drop shadow." + }, + "pointer": { + "$ref": "#/definitions/TipPointer" + }, + "pointerSize": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The size of the tip’s pointer in pixels; defaults to 12." + }, + "preferredAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If an explicit tip anchor is not specified, an anchor is chosen automatically such that the tip fits within the plot’s frame; if the preferred anchor fits, it is chosen." + }, + "textAnchor": { + "anyOf": [ + { + "const": "start", + "type": "string" + }, + { + "const": "middle", + "type": "string" + }, + { + "const": "end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [text anchor][1] controls how text is aligned (typically horizontally) relative to its anchor point; it is one of *start*, *end*, or *middle*. If the frame anchor is *left*, *top-left*, or *bottom-left*, the default text anchor is *start*; if the frame anchor is *right*, *top-right*, or\n*bottom-right*, the default is *end*; otherwise it is *middle*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/text-anchor" + }, + "textOverflow": { + "anyOf": [ + { + "type": "null" + }, + { + "const": "clip", + "type": "string" + }, + { + "const": "ellipsis", + "type": "string" + }, + { + "const": "clip-start", + "type": "string" + }, + { + "const": "clip-end", + "type": "string" + }, + { + "const": "ellipsis-start", + "type": "string" + }, + { + "const": "ellipsis-middle", + "type": "string" + }, + { + "const": "ellipsis-end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How truncate (or wrap) lines of text longer than the given **lineWidth**; one of:\n\n- null (default) - preserve overflowing characters (and wrap if needed)\n- *clip* or *clip-end* - remove characters from the end\n- *clip-start* - remove characters from the start\n- *ellipsis* or *ellipsis-end* - replace characters from the end with an ellipsis (…)\n- *ellipsis-start* - replace characters from the start with an ellipsis (…)\n- *ellipsis-middle* - replace characters from the middle with an ellipsis (…)\n\nIf no **title** was specified, if text requires truncation, a title containing the non-truncated text will be implicitly added." + }, + "textPadding": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The padding around the text in pixels; defaults to 8." + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + } + }, + "type": "object" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to generate a tooltip for this mark, and any tip options." + }, + "title": { + "$ref": "#/definitions/ChannelValue", + "description": "The title; a channel specifying accessible, short textual descriptions as strings (possibly with newlines). If the tip option is specified, the title will be displayed with an interactive tooltip instead of using the SVG [title element][1].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/title" + }, + "type": { + "anyOf": [ + { + "const": "dot", + "type": "string" + }, + { + "const": "circle", + "type": "string" + }, + { + "const": "hexagon", + "type": "string" + }, + { + "const": "text", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The basic mark type to use for hex-binned values. Defaults to a hexagon mark; dot and text marks are also supported." + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel specifying the dot’s center, typically bound to the *x* scale." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel specifying the dot’s center, typically bound to the *y* scale." + }, + "z": { + "$ref": "#/definitions/ChannelValue", + "description": "How to subdivide bins. If not specified, defaults to the *fill* channel, if any, or the *stroke* channel, if any. If null, bins will not be subdivided." + } + }, + "required": [ + "data", + "mark" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "$schema": { + "description": "A [JSON schema](http://json-schema.org/) URL for this specification, such as https://uwdata.github.io/mosaic/schema/latest.json. This property enables validation and autocomplete in editors with JSON schema support.", + "format": "uri", + "type": "string" + }, + "ariaDescription": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-description][1]; a constant textual description.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-description" + }, + "ariaHidden": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-hidden][1] state; a constant indicating whether the element is exposed to an accessibility API.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-hidden" + }, + "ariaLabel": { + "$ref": "#/definitions/ChannelValue", + "description": "The [aria-label][1]; a channel specifying short textual labels representing the value in the accessibility tree.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-label" + }, + "binWidth": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The distance between centers of neighboring hexagons, in pixels; defaults to 20. Should match the **binWidth** of the hexbin mark." + }, + "clip": { + "anyOf": [ + { + "const": "frame", + "type": "string" + }, + { + "const": "sphere", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to clip the mark; one of:\n\n- *frame* or true - clip to the plot’s frame (inner area)\n- *sphere* - clip to the projected sphere (*e.g.*, front hemisphere)\n- null or false - do not clip\n\nThe *sphere* clip option requires a geographic projection." + }, + "config": { + "$ref": "#/definitions/Config", + "description": "Configuration options." + }, + "data": { + "$ref": "#/definitions/Data", + "description": "Dataset definitions." + }, + "dx": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The horizontal offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "dy": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The vertical offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "facet": { + "anyOf": [ + { + "const": "auto", + "type": "string" + }, + { + "const": "include", + "type": "string" + }, + { + "const": "exclude", + "type": "string" + }, + { + "const": "super", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to enable or disable faceting; one of:\n\n- *auto* (default) - automatically determine if this mark should be faceted\n- *include* (or true) - draw the subset of the mark’s data in the current facet\n- *exclude* - draw the subset of the mark’s data *not* in the current facet\n- *super* - draw this mark in a single frame that covers all facets\n- null (or false) - repeat this mark’s data across all facets (*i.e.*, no faceting)\n\nWhen a mark uses *super* faceting, it is not allowed to use position scales (*x*, *y*, *fx*, or *fy*); *super* faceting is intended for decorations, such as labels and legends.\n\nWhen top-level faceting is used, the default *auto* setting is equivalent to *include* when the mark data is strictly equal to the top-level facet data; otherwise it is equivalent to null. When the *include* or *exclude* facet mode is chosen, the mark data must be parallel to the top-level facet data: the data must have the same length and order. If the data are not parallel, then the wrong data may be shown in each facet. The default\n*auto* therefore requires strict equality (`===`) for safety, and using the facet data as mark data is recommended when using the *exclude* facet mode. (To construct parallel data safely, consider using [*array*.map][1] on the facet data.)\n\nWhen mark-level faceting is used, the default *auto* setting is equivalent to *include*: the mark will be faceted if either the **fx** or **fy** channel option (or both) is specified. The null or false option will disable faceting, while *exclude* draws the subset of the mark’s data *not* in the current facet.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map" + }, + "facetAnchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "right", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "const": "left", + "type": "string" + }, + { + "const": "top-left", + "type": "string" + }, + { + "const": "top-right", + "type": "string" + }, + { + "const": "bottom-left", + "type": "string" + }, + { + "const": "bottom-right", + "type": "string" + }, + { + "const": "top-empty", + "type": "string" + }, + { + "const": "right-empty", + "type": "string" + }, + { + "const": "bottom-empty", + "type": "string" + }, + { + "const": "left-empty", + "type": "string" + }, + { + "const": "empty", + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to place the mark with respect to facets; one of:\n\n- null (default for most marks) - display the mark in each non-empty facet\n- *top*, *right*, *bottom*, or *left* - display the mark only in facets on the given side\n- *top-empty*, *right-empty*, *bottom-empty*, or *left-empty* (default for axis marks) - display the mark only in facets that have empty space on the given side: either the margin, or an empty facet\n- *empty* - display the mark in empty facets only" + }, + "fill": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill" + }, + "fillOpacity": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill-opacity][1]; a constant number between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill-opacity" + }, + "filter": { + "$ref": "#/definitions/ChannelValue", + "description": "Applies a transform to filter the mark’s index according to the given channel values; only truthy values are retained.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "fx": { + "$ref": "#/definitions/ChannelValue", + "description": "The horizontal facet position channel, for mark-level faceting, bound to the *fx* scale." + }, + "fy": { + "$ref": "#/definitions/ChannelValue", + "description": "The vertical facet position channel, for mark-level faceting, bound to the\n*fy* scale." + }, + "href": { + "$ref": "#/definitions/ChannelValue", + "description": "The [href][1]; a channel specifying URLs for clickable links. May be used in conjunction with the **target** option to open links in another window.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/href" + }, + "imageFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A CSS [filter][1]; a constant string used to adjust the rendering of images, such as *blur(5px)*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/filter" + }, + "margin": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four mark margins: **marginTop**,\n**marginRight**, **marginBottom**, and **marginLeft**; typically defaults to 0, except for axis marks." + }, + "marginBottom": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s bottom margin; the minimum distance in pixels between the bottom edges of the inner and outer plot area." + }, + "marginLeft": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s left margin; the minimum distance in pixels between the left edges of the inner and outer plot area." + }, + "marginRight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s right margin; the minimum distance in pixels between the right edges of the mark’s inner and outer plot area." + }, + "marginTop": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s top margin; the minimum distance in pixels between the top edges of the inner and outer plot area." + }, + "mark": { + "const": "hexgrid", + "description": "The hexgrid decoration mark complements the hexbin mark, showing the outlines of all hexagons spanning the frame with a default **stroke** of\n*currentColor* and a default **strokeOpacity** of 0.1, similar to the default axis grids.\n\nNote that the **binWidth** option of the hexgrid mark should match that of the hexbin transform. The grid is clipped by the frame. This is a stroke-only mark, and **fill** is not supported; to fill the frame, use the frame mark.", + "type": "string" + }, + "meta": { + "$ref": "#/definitions/Meta", + "description": "Specification metadata." + }, + "mixBlendMode": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [mix-blend-mode][1]; a constant string specifying how to blend content such as *multiply*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode" + }, + "opacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally. For faster rendering, prefer the **strokeOpacity** or **fillOpacity** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/opacity" + }, + "paintOrder": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [paint-order][1]; a constant string specifying the order in which the\n**fill**, **stroke**, and any markers are drawn; defaults to *normal*, which draws the fill, then stroke, then markers; defaults to *stroke* for the text mark to create a “halo” around text to improve legibility.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/paint-order" + }, + "params": { + "$ref": "#/definitions/Params", + "description": "Param and Selection definitions." + }, + "plotDefaults": { + "$ref": "#/definitions/PlotAttributes", + "description": "A default set of attributes to apply to all plot components." + }, + "pointerEvents": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [pointer-events][1] property; a constant string such as *none*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/pointer-events" + }, + "reverse": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Applies a transform to reverse the order of the mark’s index, say for reverse input order." + }, + "select": { + "$ref": "#/definitions/SelectFilter", + "description": "Applies a filter transform after data is loaded to highlight selected values only. For example, `first` and `last` select the first or last values of series only (using the *z* channel to separate series). Meanwhile, `nearestX` and `nearestY` select the point nearest to the pointer along the *x* or *y* channel dimension. Unlike Mosaic selections, a mark level *select* is internal to the mark only, and does not populate a param or selection value to be shared across clients.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "shapeRendering": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [shape-rendering][1]; a constant string such as *crispEdges*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/shape-rendering" + }, + "sort": { + "anyOf": [ + { + "$ref": "#/definitions/SortOrder" + }, + { + "$ref": "#/definitions/ChannelDomainSort" + } + ], + "description": "Either applies a transform to sort the mark’s index by the specified channel values, or imputes ordinal scale domains from this mark’s channels.\n\nWhen imputing ordinal scale domains from channel values, the **sort** option is an object whose keys are ordinal scale names such as *x* or *fx*, and whose values are channel names such as *y*, *y1*, or *y2*. For example, to impute the *y* scale’s domain from the associated *x* channel values in ascending order:\n\n```js sort: {y: \"x\"} ```\n\nFor different sort options for different scales, replace the channel name with a *value* object and per-scale options:\n\n```js sort: {y: {value: \"-x\"}} ```\n\nWhen sorting the mark’s index, the **sort** option is instead one of:\n\n- a channel value definition for sorting given values in ascending order\n- a {value, order} object for sorting given values\n- a {channel, order} object for sorting the named channel’s values" + }, + "stroke": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke" + }, + "strokeDasharray": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dasharray][1]; a constant number indicating the length in pixels of alternating dashes and gaps, or a constant string of numbers separated by spaces or commas (_e.g._, *10 2* for dashes of 10 pixels separated by gaps of 2 pixels), or *none* (the default) for no dashing\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dasharray" + }, + "strokeDashoffset": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dashoffset][1]; a constant indicating the offset in pixels of the first dash along the stroke; defaults to zero.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dashoffset" + }, + "strokeLinecap": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linecap][1]; a constant specifying how to cap stroked paths, such as *butt*, *round*, or *square*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linecap" + }, + "strokeLinejoin": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linejoin][1]; a constant specifying how to join stroked paths, such as *bevel*, *miter*, *miter-clip*, or *round*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linejoin" + }, + "strokeMiterlimit": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-miterlimit][1]; a constant number specifying how to limit the length of *miter* joins on stroked paths.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-miterlimit" + }, + "strokeOpacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-opacity" + }, + "strokeWidth": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-width][1]; a constant number in pixels, or a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-width" + }, + "target": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [target][1]; a constant string specifying the target window (_e.g._,\n*_blank*) for clickable links; used in conjunction with the **href** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/target" + }, + "tip": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/TipPointer" + }, + { + "properties": { + "anchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The tip anchor specifies how to orient the tip box relative to its anchor position; it refers to the part of the tip box that is attached to the anchor point. For example, the *top-left* anchor places the top-left corner of tip box near the anchor position, hence placing the tip box below and to the right of the anchor position." + }, + "fontFamily": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font-family][1]; a constant; defaults to the plot’s font family, which is typically [*system-ui*][2].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-family [2]: https://drafts.csswg.org/css-fonts-4/#valdef-font-family-system-ui" + }, + "fontSize": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font size][1] in pixels; either a constant or a channel; defaults to the plot’s font size, which is typically 10. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-size" + }, + "fontStyle": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font style][1]; a constant; defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-style" + }, + "fontVariant": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font variant][1]; a constant; if the **text** channel contains numbers or dates, defaults to *tabular-nums* to facilitate comparing numbers; otherwise defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant" + }, + "fontWeight": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font weight][1]; a constant; defaults to the plot’s font weight, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight" + }, + "format": { + "additionalProperties": false, + "description": "How channel values are formatted for display. If a format is a string, it is interpreted as a (UTC) time format for temporal channels, and otherwise a number format.", + "properties": { + "ariaLabel": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fill": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fillOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fontSize": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fx": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fy": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "geometry": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "height": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "href": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "length": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "opacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "path": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "r": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "rotate": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "src": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "stroke": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeWidth": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "symbol": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "text": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "title": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "weight": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "width": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "z": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + } + }, + "type": "object" + }, + "frameAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The frame anchor specifies defaults for **x** and **y** based on the plot’s frame; it may be one of the four sides (*top*, *right*, *bottom*, *left*), one of the four corners (*top-left*, *top-right*, *bottom-right*,\n*bottom-left*), or the *middle* of the frame. For example, for tips distributed horizontally at the top of the frame:\n\n```js Plot.tip(data, {x: \"date\", frameAnchor: \"top\"}) ```" + }, + "lineHeight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line height in ems; defaults to 1. The line height affects the (typically vertical) separation between adjacent baselines of text, as well as the separation between the text and its anchor point." + }, + "lineWidth": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line width in ems (e.g., 10 for about 20 characters); defaults to infinity, disabling wrapping and clipping.\n\nIf **textOverflow** is null, lines will be wrapped at the specified length. If a line is split at a soft hyphen (\\xad), a hyphen (-) will be displayed at the end of the line. If **textOverflow** is not null, lines will be clipped according to the given strategy." + }, + "monospace": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, changes the default **fontFamily** to *monospace*, and uses simplified monospaced text metrics calculations." + }, + "pathFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The image filter for the tip’s box; defaults to a drop shadow." + }, + "pointer": { + "$ref": "#/definitions/TipPointer" + }, + "pointerSize": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The size of the tip’s pointer in pixels; defaults to 12." + }, + "preferredAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If an explicit tip anchor is not specified, an anchor is chosen automatically such that the tip fits within the plot’s frame; if the preferred anchor fits, it is chosen." + }, + "textAnchor": { + "anyOf": [ + { + "const": "start", + "type": "string" + }, + { + "const": "middle", + "type": "string" + }, + { + "const": "end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [text anchor][1] controls how text is aligned (typically horizontally) relative to its anchor point; it is one of *start*, *end*, or *middle*. If the frame anchor is *left*, *top-left*, or *bottom-left*, the default text anchor is *start*; if the frame anchor is *right*, *top-right*, or\n*bottom-right*, the default is *end*; otherwise it is *middle*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/text-anchor" + }, + "textOverflow": { + "anyOf": [ + { + "type": "null" + }, + { + "const": "clip", + "type": "string" + }, + { + "const": "ellipsis", + "type": "string" + }, + { + "const": "clip-start", + "type": "string" + }, + { + "const": "clip-end", + "type": "string" + }, + { + "const": "ellipsis-start", + "type": "string" + }, + { + "const": "ellipsis-middle", + "type": "string" + }, + { + "const": "ellipsis-end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How truncate (or wrap) lines of text longer than the given **lineWidth**; one of:\n\n- null (default) - preserve overflowing characters (and wrap if needed)\n- *clip* or *clip-end* - remove characters from the end\n- *clip-start* - remove characters from the start\n- *ellipsis* or *ellipsis-end* - replace characters from the end with an ellipsis (…)\n- *ellipsis-start* - replace characters from the start with an ellipsis (…)\n- *ellipsis-middle* - replace characters from the middle with an ellipsis (…)\n\nIf no **title** was specified, if text requires truncation, a title containing the non-truncated text will be implicitly added." + }, + "textPadding": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The padding around the text in pixels; defaults to 8." + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + } + }, + "type": "object" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to generate a tooltip for this mark, and any tip options." + }, + "title": { + "$ref": "#/definitions/ChannelValue", + "description": "The title; a channel specifying accessible, short textual descriptions as strings (possibly with newlines). If the tip option is specified, the title will be displayed with an interactive tooltip instead of using the SVG [title element][1].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/title" + } + }, + "required": [ + "mark" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "$schema": { + "description": "A [JSON schema](http://json-schema.org/) URL for this specification, such as https://uwdata.github.io/mosaic/schema/latest.json. This property enables validation and autocomplete in editors with JSON schema support.", + "format": "uri", + "type": "string" + }, + "ariaDescription": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-description][1]; a constant textual description.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-description" + }, + "ariaHidden": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-hidden][1] state; a constant indicating whether the element is exposed to an accessibility API.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-hidden" + }, + "ariaLabel": { + "$ref": "#/definitions/ChannelValue", + "description": "The [aria-label][1]; a channel specifying short textual labels representing the value in the accessibility tree.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-label" + }, + "clip": { + "anyOf": [ + { + "const": "frame", + "type": "string" + }, + { + "const": "sphere", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to clip the mark; one of:\n\n- *frame* or true - clip to the plot’s frame (inner area)\n- *sphere* - clip to the projected sphere (*e.g.*, front hemisphere)\n- null or false - do not clip\n\nThe *sphere* clip option requires a geographic projection." + }, + "config": { + "$ref": "#/definitions/Config", + "description": "Configuration options." + }, + "crossOrigin": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [cross-origin][1] behavior. See the [Plot.image notebook][2] for details.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/crossorigin [2]: https://observablehq.com/@observablehq/plot-image" + }, + "data": { + "$ref": "#/definitions/Data", + "description": "Dataset definitions." + }, + "dx": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The horizontal offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "dy": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The vertical offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "facet": { + "anyOf": [ + { + "const": "auto", + "type": "string" + }, + { + "const": "include", + "type": "string" + }, + { + "const": "exclude", + "type": "string" + }, + { + "const": "super", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to enable or disable faceting; one of:\n\n- *auto* (default) - automatically determine if this mark should be faceted\n- *include* (or true) - draw the subset of the mark’s data in the current facet\n- *exclude* - draw the subset of the mark’s data *not* in the current facet\n- *super* - draw this mark in a single frame that covers all facets\n- null (or false) - repeat this mark’s data across all facets (*i.e.*, no faceting)\n\nWhen a mark uses *super* faceting, it is not allowed to use position scales (*x*, *y*, *fx*, or *fy*); *super* faceting is intended for decorations, such as labels and legends.\n\nWhen top-level faceting is used, the default *auto* setting is equivalent to *include* when the mark data is strictly equal to the top-level facet data; otherwise it is equivalent to null. When the *include* or *exclude* facet mode is chosen, the mark data must be parallel to the top-level facet data: the data must have the same length and order. If the data are not parallel, then the wrong data may be shown in each facet. The default\n*auto* therefore requires strict equality (`===`) for safety, and using the facet data as mark data is recommended when using the *exclude* facet mode. (To construct parallel data safely, consider using [*array*.map][1] on the facet data.)\n\nWhen mark-level faceting is used, the default *auto* setting is equivalent to *include*: the mark will be faceted if either the **fx** or **fy** channel option (or both) is specified. The null or false option will disable faceting, while *exclude* draws the subset of the mark’s data *not* in the current facet.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map" + }, + "facetAnchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "right", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "const": "left", + "type": "string" + }, + { + "const": "top-left", + "type": "string" + }, + { + "const": "top-right", + "type": "string" + }, + { + "const": "bottom-left", + "type": "string" + }, + { + "const": "bottom-right", + "type": "string" + }, + { + "const": "top-empty", + "type": "string" + }, + { + "const": "right-empty", + "type": "string" + }, + { + "const": "bottom-empty", + "type": "string" + }, + { + "const": "left-empty", + "type": "string" + }, + { + "const": "empty", + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to place the mark with respect to facets; one of:\n\n- null (default for most marks) - display the mark in each non-empty facet\n- *top*, *right*, *bottom*, or *left* - display the mark only in facets on the given side\n- *top-empty*, *right-empty*, *bottom-empty*, or *left-empty* (default for axis marks) - display the mark only in facets that have empty space on the given side: either the margin, or an empty facet\n- *empty* - display the mark in empty facets only" + }, + "fill": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill" + }, + "fillOpacity": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill-opacity][1]; a constant number between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill-opacity" + }, + "filter": { + "$ref": "#/definitions/ChannelValue", + "description": "Applies a transform to filter the mark’s index according to the given channel values; only truthy values are retained.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "frameAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The frame anchor specifies defaults for **x** and **y** based on the plot’s frame; it may be one of the four sides (*top*, *right*, *bottom*, *left*), one of the four corners (*top-left*, *top-right*, *bottom-right*,\n*bottom-left*), or the *middle* of the frame." + }, + "fx": { + "$ref": "#/definitions/ChannelValue", + "description": "The horizontal facet position channel, for mark-level faceting, bound to the *fx* scale." + }, + "fy": { + "$ref": "#/definitions/ChannelValue", + "description": "The vertical facet position channel, for mark-level faceting, bound to the\n*fy* scale." + }, + "height": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The image height in pixels. When a number, it is interpreted as a constant radius in pixels; otherwise it is interpreted as a channel. Also sets the default **height**; if neither are set, defaults to 16. Images with a nonpositive height are not drawn." + }, + "href": { + "$ref": "#/definitions/ChannelValue", + "description": "The [href][1]; a channel specifying URLs for clickable links. May be used in conjunction with the **target** option to open links in another window.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/href" + }, + "imageFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A CSS [filter][1]; a constant string used to adjust the rendering of images, such as *blur(5px)*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/filter" + }, + "imageRendering": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [image-rendering attribute][1]; defaults to *auto* (bilinear). The option may be set to *pixelated* to disable bilinear interpolation for a sharper image; however, note that this is not supported in WebKit.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/image-rendering" + }, + "margin": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four mark margins: **marginTop**,\n**marginRight**, **marginBottom**, and **marginLeft**; typically defaults to 0, except for axis marks." + }, + "marginBottom": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s bottom margin; the minimum distance in pixels between the bottom edges of the inner and outer plot area." + }, + "marginLeft": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s left margin; the minimum distance in pixels between the left edges of the inner and outer plot area." + }, + "marginRight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s right margin; the minimum distance in pixels between the right edges of the mark’s inner and outer plot area." + }, + "marginTop": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s top margin; the minimum distance in pixels between the top edges of the inner and outer plot area." + }, + "mark": { + "const": "image", + "description": "An image mark that draws images as in a scatterplot.\n\nIf either **x** or **y** is not specified, the default is determined by the **frameAnchor** option. If none of **x**, **y**, and **frameAnchor** are specified, *data* is assumed to be an array of pairs [[*x₀*, *y₀*], [*x₁*, *y₁*], [*x₂*, *y₂*], …] such that **x** = [*x₀*, *x₁*, *x₂*, …] and **y** = [*y₀*, *y₁*, *y₂*, …].", + "type": "string" + }, + "meta": { + "$ref": "#/definitions/Meta", + "description": "Specification metadata." + }, + "mixBlendMode": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [mix-blend-mode][1]; a constant string specifying how to blend content such as *multiply*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode" + }, + "opacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally. For faster rendering, prefer the **strokeOpacity** or **fillOpacity** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/opacity" + }, + "paintOrder": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [paint-order][1]; a constant string specifying the order in which the\n**fill**, **stroke**, and any markers are drawn; defaults to *normal*, which draws the fill, then stroke, then markers; defaults to *stroke* for the text mark to create a “halo” around text to improve legibility.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/paint-order" + }, + "params": { + "$ref": "#/definitions/Params", + "description": "Param and Selection definitions." + }, + "plotDefaults": { + "$ref": "#/definitions/PlotAttributes", + "description": "A default set of attributes to apply to all plot components." + }, + "pointerEvents": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [pointer-events][1] property; a constant string such as *none*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/pointer-events" + }, + "preserveAspectRatio": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The image [aspect ratio][1]; defaults to *xMidYMid meet*. To crop the image instead of scaling it to fit, use *xMidYMid slice*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/preserveAspectRatio" + }, + "r": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The image clip radius, for circular images. If null (default), images are not clipped; when a number, it is interpreted as a constant in pixels; otherwise it is interpreted as a channel, typically bound to the *r* scale. Also defaults **height** and **width** to twice its value." + }, + "reverse": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Applies a transform to reverse the order of the mark’s index, say for reverse input order." + }, + "rotate": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The rotation angle, in degrees clockwise. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel." + }, + "select": { + "$ref": "#/definitions/SelectFilter", + "description": "Applies a filter transform after data is loaded to highlight selected values only. For example, `first` and `last` select the first or last values of series only (using the *z* channel to separate series). Meanwhile, `nearestX` and `nearestY` select the point nearest to the pointer along the *x* or *y* channel dimension. Unlike Mosaic selections, a mark level *select* is internal to the mark only, and does not populate a param or selection value to be shared across clients.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "shapeRendering": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [shape-rendering][1]; a constant string such as *crispEdges*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/shape-rendering" + }, + "sort": { + "anyOf": [ + { + "$ref": "#/definitions/SortOrder" + }, + { + "$ref": "#/definitions/ChannelDomainSort" + } + ], + "description": "Either applies a transform to sort the mark’s index by the specified channel values, or imputes ordinal scale domains from this mark’s channels.\n\nWhen imputing ordinal scale domains from channel values, the **sort** option is an object whose keys are ordinal scale names such as *x* or *fx*, and whose values are channel names such as *y*, *y1*, or *y2*. For example, to impute the *y* scale’s domain from the associated *x* channel values in ascending order:\n\n```js sort: {y: \"x\"} ```\n\nFor different sort options for different scales, replace the channel name with a *value* object and per-scale options:\n\n```js sort: {y: {value: \"-x\"}} ```\n\nWhen sorting the mark’s index, the **sort** option is instead one of:\n\n- a channel value definition for sorting given values in ascending order\n- a {value, order} object for sorting given values\n- a {channel, order} object for sorting the named channel’s values" + }, + "src": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The required image URL (or relative path). If a string that starts with a dot, slash, or URL protocol (*e.g.*, “https:”) it is assumed to be a constant; otherwise it is interpreted as a channel." + }, + "stroke": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke" + }, + "strokeDasharray": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dasharray][1]; a constant number indicating the length in pixels of alternating dashes and gaps, or a constant string of numbers separated by spaces or commas (_e.g._, *10 2* for dashes of 10 pixels separated by gaps of 2 pixels), or *none* (the default) for no dashing\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dasharray" + }, + "strokeDashoffset": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dashoffset][1]; a constant indicating the offset in pixels of the first dash along the stroke; defaults to zero.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dashoffset" + }, + "strokeLinecap": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linecap][1]; a constant specifying how to cap stroked paths, such as *butt*, *round*, or *square*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linecap" + }, + "strokeLinejoin": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linejoin][1]; a constant specifying how to join stroked paths, such as *bevel*, *miter*, *miter-clip*, or *round*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linejoin" + }, + "strokeMiterlimit": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-miterlimit][1]; a constant number specifying how to limit the length of *miter* joins on stroked paths.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-miterlimit" + }, + "strokeOpacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-opacity" + }, + "strokeWidth": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-width][1]; a constant number in pixels, or a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-width" + }, + "target": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [target][1]; a constant string specifying the target window (_e.g._,\n*_blank*) for clickable links; used in conjunction with the **href** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/target" + }, + "tip": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/TipPointer" + }, + { + "properties": { + "anchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The tip anchor specifies how to orient the tip box relative to its anchor position; it refers to the part of the tip box that is attached to the anchor point. For example, the *top-left* anchor places the top-left corner of tip box near the anchor position, hence placing the tip box below and to the right of the anchor position." + }, + "fontFamily": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font-family][1]; a constant; defaults to the plot’s font family, which is typically [*system-ui*][2].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-family [2]: https://drafts.csswg.org/css-fonts-4/#valdef-font-family-system-ui" + }, + "fontSize": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font size][1] in pixels; either a constant or a channel; defaults to the plot’s font size, which is typically 10. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-size" + }, + "fontStyle": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font style][1]; a constant; defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-style" + }, + "fontVariant": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font variant][1]; a constant; if the **text** channel contains numbers or dates, defaults to *tabular-nums* to facilitate comparing numbers; otherwise defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant" + }, + "fontWeight": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font weight][1]; a constant; defaults to the plot’s font weight, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight" + }, + "format": { + "additionalProperties": false, + "description": "How channel values are formatted for display. If a format is a string, it is interpreted as a (UTC) time format for temporal channels, and otherwise a number format.", + "properties": { + "ariaLabel": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fill": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fillOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fontSize": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fx": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fy": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "geometry": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "height": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "href": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "length": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "opacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "path": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "r": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "rotate": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "src": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "stroke": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeWidth": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "symbol": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "text": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "title": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "weight": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "width": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "z": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + } + }, + "type": "object" + }, + "frameAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The frame anchor specifies defaults for **x** and **y** based on the plot’s frame; it may be one of the four sides (*top*, *right*, *bottom*, *left*), one of the four corners (*top-left*, *top-right*, *bottom-right*,\n*bottom-left*), or the *middle* of the frame. For example, for tips distributed horizontally at the top of the frame:\n\n```js Plot.tip(data, {x: \"date\", frameAnchor: \"top\"}) ```" + }, + "lineHeight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line height in ems; defaults to 1. The line height affects the (typically vertical) separation between adjacent baselines of text, as well as the separation between the text and its anchor point." + }, + "lineWidth": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line width in ems (e.g., 10 for about 20 characters); defaults to infinity, disabling wrapping and clipping.\n\nIf **textOverflow** is null, lines will be wrapped at the specified length. If a line is split at a soft hyphen (\\xad), a hyphen (-) will be displayed at the end of the line. If **textOverflow** is not null, lines will be clipped according to the given strategy." + }, + "monospace": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, changes the default **fontFamily** to *monospace*, and uses simplified monospaced text metrics calculations." + }, + "pathFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The image filter for the tip’s box; defaults to a drop shadow." + }, + "pointer": { + "$ref": "#/definitions/TipPointer" + }, + "pointerSize": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The size of the tip’s pointer in pixels; defaults to 12." + }, + "preferredAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If an explicit tip anchor is not specified, an anchor is chosen automatically such that the tip fits within the plot’s frame; if the preferred anchor fits, it is chosen." + }, + "textAnchor": { + "anyOf": [ + { + "const": "start", + "type": "string" + }, + { + "const": "middle", + "type": "string" + }, + { + "const": "end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [text anchor][1] controls how text is aligned (typically horizontally) relative to its anchor point; it is one of *start*, *end*, or *middle*. If the frame anchor is *left*, *top-left*, or *bottom-left*, the default text anchor is *start*; if the frame anchor is *right*, *top-right*, or\n*bottom-right*, the default is *end*; otherwise it is *middle*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/text-anchor" + }, + "textOverflow": { + "anyOf": [ + { + "type": "null" + }, + { + "const": "clip", + "type": "string" + }, + { + "const": "ellipsis", + "type": "string" + }, + { + "const": "clip-start", + "type": "string" + }, + { + "const": "clip-end", + "type": "string" + }, + { + "const": "ellipsis-start", + "type": "string" + }, + { + "const": "ellipsis-middle", + "type": "string" + }, + { + "const": "ellipsis-end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How truncate (or wrap) lines of text longer than the given **lineWidth**; one of:\n\n- null (default) - preserve overflowing characters (and wrap if needed)\n- *clip* or *clip-end* - remove characters from the end\n- *clip-start* - remove characters from the start\n- *ellipsis* or *ellipsis-end* - replace characters from the end with an ellipsis (…)\n- *ellipsis-start* - replace characters from the start with an ellipsis (…)\n- *ellipsis-middle* - replace characters from the middle with an ellipsis (…)\n\nIf no **title** was specified, if text requires truncation, a title containing the non-truncated text will be implicitly added." + }, + "textPadding": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The padding around the text in pixels; defaults to 8." + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + } + }, + "type": "object" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to generate a tooltip for this mark, and any tip options." + }, + "title": { + "$ref": "#/definitions/ChannelValue", + "description": "The title; a channel specifying accessible, short textual descriptions as strings (possibly with newlines). If the tip option is specified, the title will be displayed with an interactive tooltip instead of using the SVG [title element][1].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/title" + }, + "width": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The image width in pixels. When a number, it is interpreted as a constant radius in pixels; otherwise it is interpreted as a channel. Also sets the default **height**; if neither are set, defaults to 16. Images with a nonpositive width are not drawn." + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel specifying the image’s center; typically bound to the *x* scale." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel specifying the image’s center; typically bound to the *y* scale." + } + }, + "required": [ + "data", + "mark" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "$schema": { + "description": "A [JSON schema](http://json-schema.org/) URL for this specification, such as https://uwdata.github.io/mosaic/schema/latest.json. This property enables validation and autocomplete in editors with JSON schema support.", + "format": "uri", + "type": "string" + }, + "ariaDescription": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-description][1]; a constant textual description.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-description" + }, + "ariaHidden": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-hidden][1] state; a constant indicating whether the element is exposed to an accessibility API.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-hidden" + }, + "ariaLabel": { + "$ref": "#/definitions/ChannelValue", + "description": "The [aria-label][1]; a channel specifying short textual labels representing the value in the accessibility tree.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-label" + }, + "clip": { + "anyOf": [ + { + "const": "frame", + "type": "string" + }, + { + "const": "sphere", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to clip the mark; one of:\n\n- *frame* or true - clip to the plot’s frame (inner area)\n- *sphere* - clip to the projected sphere (*e.g.*, front hemisphere)\n- null or false - do not clip\n\nThe *sphere* clip option requires a geographic projection." + }, + "config": { + "$ref": "#/definitions/Config", + "description": "Configuration options." + }, + "curve": { + "anyOf": [ + { + "$ref": "#/definitions/Curve" + }, + { + "const": "auto", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The curve (interpolation) method for connecting adjacent points. One of:\n\n- *basis* - a cubic basis spline (repeating the end points)\n- *basis-open* - an open cubic basis spline\n- *basis-closed* - a closed cubic basis spline\n- *bump-x* - a Bézier curve with horizontal tangents\n- *bump-y* - a Bézier curve with vertical tangents\n- *bundle* - a straightened cubic basis spline (suitable for lines only, not areas)\n- *cardinal* - a cubic cardinal spline (with one-sided differences at the ends)\n- *cardinal-open* - an open cubic cardinal spline\n- *cardinal-closed* - an closed cubic cardinal spline\n- *catmull-rom* - a cubic Catmull–Rom spline (with one-sided differences at the ends)\n- *catmull-rom-open* - an open cubic Catmull–Rom spline\n- *catmull-rom-closed* - a closed cubic Catmull–Rom spline\n- *linear* - a piecewise linear curve (*i.e.*, straight line segments)\n- *linear-closed* - a closed piecewise linear curve (*i.e.*, straight line segments)\n- *monotone-x* - a cubic spline that preserves monotonicity in *x*\n- *monotone-y* - a cubic spline that preserves monotonicity in *y*\n- *natural* - a natural cubic spline\n- *step* - a piecewise constant function where *y* changes at the midpoint of *x*\n- *step-after* - a piecewise constant function where *y* changes after *x*\n- *step-before* - a piecewise constant function where *x* changes after *y*\n- *auto* (default) - like *linear*, but use the (possibly spherical) projection, if any\n\nThe *auto* curve is typically used in conjunction with a spherical projection to interpolate along geodesics." + }, + "data": { + "$ref": "#/definitions/Data", + "description": "Dataset definitions." + }, + "dx": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The horizontal offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "dy": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The vertical offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "facet": { + "anyOf": [ + { + "const": "auto", + "type": "string" + }, + { + "const": "include", + "type": "string" + }, + { + "const": "exclude", + "type": "string" + }, + { + "const": "super", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to enable or disable faceting; one of:\n\n- *auto* (default) - automatically determine if this mark should be faceted\n- *include* (or true) - draw the subset of the mark’s data in the current facet\n- *exclude* - draw the subset of the mark’s data *not* in the current facet\n- *super* - draw this mark in a single frame that covers all facets\n- null (or false) - repeat this mark’s data across all facets (*i.e.*, no faceting)\n\nWhen a mark uses *super* faceting, it is not allowed to use position scales (*x*, *y*, *fx*, or *fy*); *super* faceting is intended for decorations, such as labels and legends.\n\nWhen top-level faceting is used, the default *auto* setting is equivalent to *include* when the mark data is strictly equal to the top-level facet data; otherwise it is equivalent to null. When the *include* or *exclude* facet mode is chosen, the mark data must be parallel to the top-level facet data: the data must have the same length and order. If the data are not parallel, then the wrong data may be shown in each facet. The default\n*auto* therefore requires strict equality (`===`) for safety, and using the facet data as mark data is recommended when using the *exclude* facet mode. (To construct parallel data safely, consider using [*array*.map][1] on the facet data.)\n\nWhen mark-level faceting is used, the default *auto* setting is equivalent to *include*: the mark will be faceted if either the **fx** or **fy** channel option (or both) is specified. The null or false option will disable faceting, while *exclude* draws the subset of the mark’s data *not* in the current facet.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map" + }, + "facetAnchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "right", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "const": "left", + "type": "string" + }, + { + "const": "top-left", + "type": "string" + }, + { + "const": "top-right", + "type": "string" + }, + { + "const": "bottom-left", + "type": "string" + }, + { + "const": "bottom-right", + "type": "string" + }, + { + "const": "top-empty", + "type": "string" + }, + { + "const": "right-empty", + "type": "string" + }, + { + "const": "bottom-empty", + "type": "string" + }, + { + "const": "left-empty", + "type": "string" + }, + { + "const": "empty", + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to place the mark with respect to facets; one of:\n\n- null (default for most marks) - display the mark in each non-empty facet\n- *top*, *right*, *bottom*, or *left* - display the mark only in facets on the given side\n- *top-empty*, *right-empty*, *bottom-empty*, or *left-empty* (default for axis marks) - display the mark only in facets that have empty space on the given side: either the margin, or an empty facet\n- *empty* - display the mark in empty facets only" + }, + "fill": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill" + }, + "fillOpacity": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill-opacity][1]; a constant number between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill-opacity" + }, + "filter": { + "$ref": "#/definitions/ChannelValue", + "description": "Applies a transform to filter the mark’s index according to the given channel values; only truthy values are retained.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "fx": { + "$ref": "#/definitions/ChannelValue", + "description": "The horizontal facet position channel, for mark-level faceting, bound to the *fx* scale." + }, + "fy": { + "$ref": "#/definitions/ChannelValue", + "description": "The vertical facet position channel, for mark-level faceting, bound to the\n*fy* scale." + }, + "href": { + "$ref": "#/definitions/ChannelValue", + "description": "The [href][1]; a channel specifying URLs for clickable links. May be used in conjunction with the **target** option to open links in another window.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/href" + }, + "imageFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A CSS [filter][1]; a constant string used to adjust the rendering of images, such as *blur(5px)*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/filter" + }, + "margin": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four mark margins: **marginTop**,\n**marginRight**, **marginBottom**, and **marginLeft**; typically defaults to 0, except for axis marks." + }, + "marginBottom": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s bottom margin; the minimum distance in pixels between the bottom edges of the inner and outer plot area." + }, + "marginLeft": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s left margin; the minimum distance in pixels between the left edges of the inner and outer plot area." + }, + "marginRight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s right margin; the minimum distance in pixels between the right edges of the mark’s inner and outer plot area." + }, + "marginTop": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s top margin; the minimum distance in pixels between the top edges of the inner and outer plot area." + }, + "mark": { + "const": "line", + "description": "A line mark that connects control points.\n\nPoints along the line are connected in input order. If there are multiple series via the **z**, **fill**, or **stroke** channel, series are drawn in input order such that the last series is drawn on top. Typically *data* is already in sorted order, such as chronological for time series; if needed, consider a **sort** transform.\n\nIf any **x** or **y** values are invalid (undefined, null, or NaN), the line will be interrupted, resulting in a break that divides the line shape into multiple segments. If a line segment consists of only a single point, it may appear invisible unless rendered with rounded or square line caps. In addition, some curves such as *cardinal-open* only render a visible segment if it contains multiple points.\n\nVariable aesthetic channels are supported: if the **stroke** is defined as a channel, the line will be broken into contiguous overlapping segments when the stroke color changes; the stroke color will apply to the interval spanning the current data point and the following data point. This behavior also applies to the **fill**, **fillOpacity**, **strokeOpacity**,\n**strokeWidth**, **opacity**, **href**, **title**, and **ariaLabel** channels. When any of these channels are used, setting an explicit **z** channel (possibly to null) is strongly recommended.", + "type": "string" + }, + "marker": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for markerStart, markerMid, and markerEnd; one of:\n\n- a marker name such as *arrow* or *circle*\n- *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*" + }, + "markerEnd": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The marker for the ending point of a line segment; one of:\n\n- a marker name such as *arrow* or *circle*\n* *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*" + }, + "markerMid": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The marker for any middle (interior) points of a line segment. If the line segment only has a start and end point, this option has no effect. One of:\n\n- a marker name such as *arrow* or *circle*\n* *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*\n* a function - a custom marker function; see below" + }, + "markerStart": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The marker for the starting point of a line segment; one of:\n\n- a marker name such as *arrow* or *circle*\n* *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*" + }, + "meta": { + "$ref": "#/definitions/Meta", + "description": "Specification metadata." + }, + "mixBlendMode": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [mix-blend-mode][1]; a constant string specifying how to blend content such as *multiply*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode" + }, + "opacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally. For faster rendering, prefer the **strokeOpacity** or **fillOpacity** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/opacity" + }, + "paintOrder": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [paint-order][1]; a constant string specifying the order in which the\n**fill**, **stroke**, and any markers are drawn; defaults to *normal*, which draws the fill, then stroke, then markers; defaults to *stroke* for the text mark to create a “halo” around text to improve legibility.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/paint-order" + }, + "params": { + "$ref": "#/definitions/Params", + "description": "Param and Selection definitions." + }, + "plotDefaults": { + "$ref": "#/definitions/PlotAttributes", + "description": "A default set of attributes to apply to all plot components." + }, + "pointerEvents": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [pointer-events][1] property; a constant string such as *none*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/pointer-events" + }, + "reverse": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Applies a transform to reverse the order of the mark’s index, say for reverse input order." + }, + "select": { + "$ref": "#/definitions/SelectFilter", + "description": "Applies a filter transform after data is loaded to highlight selected values only. For example, `first` and `last` select the first or last values of series only (using the *z* channel to separate series). Meanwhile, `nearestX` and `nearestY` select the point nearest to the pointer along the *x* or *y* channel dimension. Unlike Mosaic selections, a mark level *select* is internal to the mark only, and does not populate a param or selection value to be shared across clients.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "shapeRendering": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [shape-rendering][1]; a constant string such as *crispEdges*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/shape-rendering" + }, + "sort": { + "anyOf": [ + { + "$ref": "#/definitions/SortOrder" + }, + { + "$ref": "#/definitions/ChannelDomainSort" + } + ], + "description": "Either applies a transform to sort the mark’s index by the specified channel values, or imputes ordinal scale domains from this mark’s channels.\n\nWhen imputing ordinal scale domains from channel values, the **sort** option is an object whose keys are ordinal scale names such as *x* or *fx*, and whose values are channel names such as *y*, *y1*, or *y2*. For example, to impute the *y* scale’s domain from the associated *x* channel values in ascending order:\n\n```js sort: {y: \"x\"} ```\n\nFor different sort options for different scales, replace the channel name with a *value* object and per-scale options:\n\n```js sort: {y: {value: \"-x\"}} ```\n\nWhen sorting the mark’s index, the **sort** option is instead one of:\n\n- a channel value definition for sorting given values in ascending order\n- a {value, order} object for sorting given values\n- a {channel, order} object for sorting the named channel’s values" + }, + "stroke": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke" + }, + "strokeDasharray": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dasharray][1]; a constant number indicating the length in pixels of alternating dashes and gaps, or a constant string of numbers separated by spaces or commas (_e.g._, *10 2* for dashes of 10 pixels separated by gaps of 2 pixels), or *none* (the default) for no dashing\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dasharray" + }, + "strokeDashoffset": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dashoffset][1]; a constant indicating the offset in pixels of the first dash along the stroke; defaults to zero.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dashoffset" + }, + "strokeLinecap": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linecap][1]; a constant specifying how to cap stroked paths, such as *butt*, *round*, or *square*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linecap" + }, + "strokeLinejoin": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linejoin][1]; a constant specifying how to join stroked paths, such as *bevel*, *miter*, *miter-clip*, or *round*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linejoin" + }, + "strokeMiterlimit": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-miterlimit][1]; a constant number specifying how to limit the length of *miter* joins on stroked paths.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-miterlimit" + }, + "strokeOpacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-opacity" + }, + "strokeWidth": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-width][1]; a constant number in pixels, or a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-width" + }, + "target": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [target][1]; a constant string specifying the target window (_e.g._,\n*_blank*) for clickable links; used in conjunction with the **href** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/target" + }, + "tension": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The tension option only has an effect on bundle, cardinal and Catmull–Rom splines (*bundle*, *cardinal*, *cardinal-open*, *cardinal-closed*,\n*catmull-rom*, *catmull-rom-open*, and *catmull-rom-closed*). For bundle splines, it corresponds to [beta][1]; for cardinal splines, [tension][2]; for Catmull–Rom splines, [alpha][3].\n\n[1]: https://d3js.org/d3-shape/curve#curveBundle_beta [2]: https://d3js.org/d3-shape/curve#curveCardinal_tension [3]: https://d3js.org/d3-shape/curve#curveCatmullRom_alpha" + }, + "tip": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/TipPointer" + }, + { + "properties": { + "anchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The tip anchor specifies how to orient the tip box relative to its anchor position; it refers to the part of the tip box that is attached to the anchor point. For example, the *top-left* anchor places the top-left corner of tip box near the anchor position, hence placing the tip box below and to the right of the anchor position." + }, + "fontFamily": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font-family][1]; a constant; defaults to the plot’s font family, which is typically [*system-ui*][2].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-family [2]: https://drafts.csswg.org/css-fonts-4/#valdef-font-family-system-ui" + }, + "fontSize": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font size][1] in pixels; either a constant or a channel; defaults to the plot’s font size, which is typically 10. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-size" + }, + "fontStyle": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font style][1]; a constant; defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-style" + }, + "fontVariant": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font variant][1]; a constant; if the **text** channel contains numbers or dates, defaults to *tabular-nums* to facilitate comparing numbers; otherwise defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant" + }, + "fontWeight": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font weight][1]; a constant; defaults to the plot’s font weight, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight" + }, + "format": { + "additionalProperties": false, + "description": "How channel values are formatted for display. If a format is a string, it is interpreted as a (UTC) time format for temporal channels, and otherwise a number format.", + "properties": { + "ariaLabel": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fill": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fillOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fontSize": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fx": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fy": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "geometry": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "height": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "href": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "length": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "opacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "path": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "r": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "rotate": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "src": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "stroke": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeWidth": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "symbol": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "text": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "title": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "weight": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "width": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "z": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + } + }, + "type": "object" + }, + "frameAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The frame anchor specifies defaults for **x** and **y** based on the plot’s frame; it may be one of the four sides (*top*, *right*, *bottom*, *left*), one of the four corners (*top-left*, *top-right*, *bottom-right*,\n*bottom-left*), or the *middle* of the frame. For example, for tips distributed horizontally at the top of the frame:\n\n```js Plot.tip(data, {x: \"date\", frameAnchor: \"top\"}) ```" + }, + "lineHeight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line height in ems; defaults to 1. The line height affects the (typically vertical) separation between adjacent baselines of text, as well as the separation between the text and its anchor point." + }, + "lineWidth": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line width in ems (e.g., 10 for about 20 characters); defaults to infinity, disabling wrapping and clipping.\n\nIf **textOverflow** is null, lines will be wrapped at the specified length. If a line is split at a soft hyphen (\\xad), a hyphen (-) will be displayed at the end of the line. If **textOverflow** is not null, lines will be clipped according to the given strategy." + }, + "monospace": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, changes the default **fontFamily** to *monospace*, and uses simplified monospaced text metrics calculations." + }, + "pathFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The image filter for the tip’s box; defaults to a drop shadow." + }, + "pointer": { + "$ref": "#/definitions/TipPointer" + }, + "pointerSize": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The size of the tip’s pointer in pixels; defaults to 12." + }, + "preferredAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If an explicit tip anchor is not specified, an anchor is chosen automatically such that the tip fits within the plot’s frame; if the preferred anchor fits, it is chosen." + }, + "textAnchor": { + "anyOf": [ + { + "const": "start", + "type": "string" + }, + { + "const": "middle", + "type": "string" + }, + { + "const": "end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [text anchor][1] controls how text is aligned (typically horizontally) relative to its anchor point; it is one of *start*, *end*, or *middle*. If the frame anchor is *left*, *top-left*, or *bottom-left*, the default text anchor is *start*; if the frame anchor is *right*, *top-right*, or\n*bottom-right*, the default is *end*; otherwise it is *middle*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/text-anchor" + }, + "textOverflow": { + "anyOf": [ + { + "type": "null" + }, + { + "const": "clip", + "type": "string" + }, + { + "const": "ellipsis", + "type": "string" + }, + { + "const": "clip-start", + "type": "string" + }, + { + "const": "clip-end", + "type": "string" + }, + { + "const": "ellipsis-start", + "type": "string" + }, + { + "const": "ellipsis-middle", + "type": "string" + }, + { + "const": "ellipsis-end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How truncate (or wrap) lines of text longer than the given **lineWidth**; one of:\n\n- null (default) - preserve overflowing characters (and wrap if needed)\n- *clip* or *clip-end* - remove characters from the end\n- *clip-start* - remove characters from the start\n- *ellipsis* or *ellipsis-end* - replace characters from the end with an ellipsis (…)\n- *ellipsis-start* - replace characters from the start with an ellipsis (…)\n- *ellipsis-middle* - replace characters from the middle with an ellipsis (…)\n\nIf no **title** was specified, if text requires truncation, a title containing the non-truncated text will be implicitly added." + }, + "textPadding": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The padding around the text in pixels; defaults to 8." + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + } + }, + "type": "object" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to generate a tooltip for this mark, and any tip options." + }, + "title": { + "$ref": "#/definitions/ChannelValue", + "description": "The title; a channel specifying accessible, short textual descriptions as strings (possibly with newlines). If the tip option is specified, the title will be displayed with an interactive tooltip instead of using the SVG [title element][1].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/title" + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The required horizontal position channel, typically bound to the *x* scale." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The required vertical position channel, typically bound to the *y* scale." + }, + "z": { + "$ref": "#/definitions/ChannelValue", + "description": "An optional ordinal channel for grouping data into (possibly stacked) series to be drawn as separate lines. If not specified, it defaults to\n**fill** if a channel, or **stroke** if a channel." + } + }, + "required": [ + "data", + "mark" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "$schema": { + "description": "A [JSON schema](http://json-schema.org/) URL for this specification, such as https://uwdata.github.io/mosaic/schema/latest.json. This property enables validation and autocomplete in editors with JSON schema support.", + "format": "uri", + "type": "string" + }, + "ariaDescription": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-description][1]; a constant textual description.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-description" + }, + "ariaHidden": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-hidden][1] state; a constant indicating whether the element is exposed to an accessibility API.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-hidden" + }, + "ariaLabel": { + "$ref": "#/definitions/ChannelValue", + "description": "The [aria-label][1]; a channel specifying short textual labels representing the value in the accessibility tree.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-label" + }, + "clip": { + "anyOf": [ + { + "const": "frame", + "type": "string" + }, + { + "const": "sphere", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to clip the mark; one of:\n\n- *frame* or true - clip to the plot’s frame (inner area)\n- *sphere* - clip to the projected sphere (*e.g.*, front hemisphere)\n- null or false - do not clip\n\nThe *sphere* clip option requires a geographic projection." + }, + "config": { + "$ref": "#/definitions/Config", + "description": "Configuration options." + }, + "curve": { + "anyOf": [ + { + "$ref": "#/definitions/Curve" + }, + { + "const": "auto", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The curve (interpolation) method for connecting adjacent points. One of:\n\n- *basis* - a cubic basis spline (repeating the end points)\n- *basis-open* - an open cubic basis spline\n- *basis-closed* - a closed cubic basis spline\n- *bump-x* - a Bézier curve with horizontal tangents\n- *bump-y* - a Bézier curve with vertical tangents\n- *bundle* - a straightened cubic basis spline (suitable for lines only, not areas)\n- *cardinal* - a cubic cardinal spline (with one-sided differences at the ends)\n- *cardinal-open* - an open cubic cardinal spline\n- *cardinal-closed* - an closed cubic cardinal spline\n- *catmull-rom* - a cubic Catmull–Rom spline (with one-sided differences at the ends)\n- *catmull-rom-open* - an open cubic Catmull–Rom spline\n- *catmull-rom-closed* - a closed cubic Catmull–Rom spline\n- *linear* - a piecewise linear curve (*i.e.*, straight line segments)\n- *linear-closed* - a closed piecewise linear curve (*i.e.*, straight line segments)\n- *monotone-x* - a cubic spline that preserves monotonicity in *x*\n- *monotone-y* - a cubic spline that preserves monotonicity in *y*\n- *natural* - a natural cubic spline\n- *step* - a piecewise constant function where *y* changes at the midpoint of *x*\n- *step-after* - a piecewise constant function where *y* changes after *x*\n- *step-before* - a piecewise constant function where *x* changes after *y*\n- *auto* (default) - like *linear*, but use the (possibly spherical) projection, if any\n\nThe *auto* curve is typically used in conjunction with a spherical projection to interpolate along geodesics." + }, + "data": { + "$ref": "#/definitions/Data", + "description": "Dataset definitions." + }, + "dx": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The horizontal offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "dy": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The vertical offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "facet": { + "anyOf": [ + { + "const": "auto", + "type": "string" + }, + { + "const": "include", + "type": "string" + }, + { + "const": "exclude", + "type": "string" + }, + { + "const": "super", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to enable or disable faceting; one of:\n\n- *auto* (default) - automatically determine if this mark should be faceted\n- *include* (or true) - draw the subset of the mark’s data in the current facet\n- *exclude* - draw the subset of the mark’s data *not* in the current facet\n- *super* - draw this mark in a single frame that covers all facets\n- null (or false) - repeat this mark’s data across all facets (*i.e.*, no faceting)\n\nWhen a mark uses *super* faceting, it is not allowed to use position scales (*x*, *y*, *fx*, or *fy*); *super* faceting is intended for decorations, such as labels and legends.\n\nWhen top-level faceting is used, the default *auto* setting is equivalent to *include* when the mark data is strictly equal to the top-level facet data; otherwise it is equivalent to null. When the *include* or *exclude* facet mode is chosen, the mark data must be parallel to the top-level facet data: the data must have the same length and order. If the data are not parallel, then the wrong data may be shown in each facet. The default\n*auto* therefore requires strict equality (`===`) for safety, and using the facet data as mark data is recommended when using the *exclude* facet mode. (To construct parallel data safely, consider using [*array*.map][1] on the facet data.)\n\nWhen mark-level faceting is used, the default *auto* setting is equivalent to *include*: the mark will be faceted if either the **fx** or **fy** channel option (or both) is specified. The null or false option will disable faceting, while *exclude* draws the subset of the mark’s data *not* in the current facet.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map" + }, + "facetAnchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "right", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "const": "left", + "type": "string" + }, + { + "const": "top-left", + "type": "string" + }, + { + "const": "top-right", + "type": "string" + }, + { + "const": "bottom-left", + "type": "string" + }, + { + "const": "bottom-right", + "type": "string" + }, + { + "const": "top-empty", + "type": "string" + }, + { + "const": "right-empty", + "type": "string" + }, + { + "const": "bottom-empty", + "type": "string" + }, + { + "const": "left-empty", + "type": "string" + }, + { + "const": "empty", + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to place the mark with respect to facets; one of:\n\n- null (default for most marks) - display the mark in each non-empty facet\n- *top*, *right*, *bottom*, or *left* - display the mark only in facets on the given side\n- *top-empty*, *right-empty*, *bottom-empty*, or *left-empty* (default for axis marks) - display the mark only in facets that have empty space on the given side: either the margin, or an empty facet\n- *empty* - display the mark in empty facets only" + }, + "fill": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill" + }, + "fillOpacity": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill-opacity][1]; a constant number between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill-opacity" + }, + "filter": { + "$ref": "#/definitions/ChannelValue", + "description": "Applies a transform to filter the mark’s index according to the given channel values; only truthy values are retained.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "fx": { + "$ref": "#/definitions/ChannelValue", + "description": "The horizontal facet position channel, for mark-level faceting, bound to the *fx* scale." + }, + "fy": { + "$ref": "#/definitions/ChannelValue", + "description": "The vertical facet position channel, for mark-level faceting, bound to the\n*fy* scale." + }, + "href": { + "$ref": "#/definitions/ChannelValue", + "description": "The [href][1]; a channel specifying URLs for clickable links. May be used in conjunction with the **target** option to open links in another window.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/href" + }, + "imageFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A CSS [filter][1]; a constant string used to adjust the rendering of images, such as *blur(5px)*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/filter" + }, + "margin": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four mark margins: **marginTop**,\n**marginRight**, **marginBottom**, and **marginLeft**; typically defaults to 0, except for axis marks." + }, + "marginBottom": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s bottom margin; the minimum distance in pixels between the bottom edges of the inner and outer plot area." + }, + "marginLeft": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s left margin; the minimum distance in pixels between the left edges of the inner and outer plot area." + }, + "marginRight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s right margin; the minimum distance in pixels between the right edges of the mark’s inner and outer plot area." + }, + "marginTop": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s top margin; the minimum distance in pixels between the top edges of the inner and outer plot area." + }, + "mark": { + "const": "lineX", + "description": "Like line, except that **x** defaults to the identity function assuming that *data* = [*x₀*, *x₁*, *x₂*, …] and **y** defaults to the zero-based index [0, 1, 2, …].", + "type": "string" + }, + "marker": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for markerStart, markerMid, and markerEnd; one of:\n\n- a marker name such as *arrow* or *circle*\n- *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*" + }, + "markerEnd": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The marker for the ending point of a line segment; one of:\n\n- a marker name such as *arrow* or *circle*\n* *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*" + }, + "markerMid": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The marker for any middle (interior) points of a line segment. If the line segment only has a start and end point, this option has no effect. One of:\n\n- a marker name such as *arrow* or *circle*\n* *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*\n* a function - a custom marker function; see below" + }, + "markerStart": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The marker for the starting point of a line segment; one of:\n\n- a marker name such as *arrow* or *circle*\n* *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*" + }, + "meta": { + "$ref": "#/definitions/Meta", + "description": "Specification metadata." + }, + "mixBlendMode": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [mix-blend-mode][1]; a constant string specifying how to blend content such as *multiply*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode" + }, + "opacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally. For faster rendering, prefer the **strokeOpacity** or **fillOpacity** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/opacity" + }, + "paintOrder": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [paint-order][1]; a constant string specifying the order in which the\n**fill**, **stroke**, and any markers are drawn; defaults to *normal*, which draws the fill, then stroke, then markers; defaults to *stroke* for the text mark to create a “halo” around text to improve legibility.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/paint-order" + }, + "params": { + "$ref": "#/definitions/Params", + "description": "Param and Selection definitions." + }, + "plotDefaults": { + "$ref": "#/definitions/PlotAttributes", + "description": "A default set of attributes to apply to all plot components." + }, + "pointerEvents": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [pointer-events][1] property; a constant string such as *none*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/pointer-events" + }, + "reverse": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Applies a transform to reverse the order of the mark’s index, say for reverse input order." + }, + "select": { + "$ref": "#/definitions/SelectFilter", + "description": "Applies a filter transform after data is loaded to highlight selected values only. For example, `first` and `last` select the first or last values of series only (using the *z* channel to separate series). Meanwhile, `nearestX` and `nearestY` select the point nearest to the pointer along the *x* or *y* channel dimension. Unlike Mosaic selections, a mark level *select* is internal to the mark only, and does not populate a param or selection value to be shared across clients.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "shapeRendering": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [shape-rendering][1]; a constant string such as *crispEdges*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/shape-rendering" + }, + "sort": { + "anyOf": [ + { + "$ref": "#/definitions/SortOrder" + }, + { + "$ref": "#/definitions/ChannelDomainSort" + } + ], + "description": "Either applies a transform to sort the mark’s index by the specified channel values, or imputes ordinal scale domains from this mark’s channels.\n\nWhen imputing ordinal scale domains from channel values, the **sort** option is an object whose keys are ordinal scale names such as *x* or *fx*, and whose values are channel names such as *y*, *y1*, or *y2*. For example, to impute the *y* scale’s domain from the associated *x* channel values in ascending order:\n\n```js sort: {y: \"x\"} ```\n\nFor different sort options for different scales, replace the channel name with a *value* object and per-scale options:\n\n```js sort: {y: {value: \"-x\"}} ```\n\nWhen sorting the mark’s index, the **sort** option is instead one of:\n\n- a channel value definition for sorting given values in ascending order\n- a {value, order} object for sorting given values\n- a {channel, order} object for sorting the named channel’s values" + }, + "stroke": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke" + }, + "strokeDasharray": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dasharray][1]; a constant number indicating the length in pixels of alternating dashes and gaps, or a constant string of numbers separated by spaces or commas (_e.g._, *10 2* for dashes of 10 pixels separated by gaps of 2 pixels), or *none* (the default) for no dashing\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dasharray" + }, + "strokeDashoffset": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dashoffset][1]; a constant indicating the offset in pixels of the first dash along the stroke; defaults to zero.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dashoffset" + }, + "strokeLinecap": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linecap][1]; a constant specifying how to cap stroked paths, such as *butt*, *round*, or *square*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linecap" + }, + "strokeLinejoin": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linejoin][1]; a constant specifying how to join stroked paths, such as *bevel*, *miter*, *miter-clip*, or *round*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linejoin" + }, + "strokeMiterlimit": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-miterlimit][1]; a constant number specifying how to limit the length of *miter* joins on stroked paths.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-miterlimit" + }, + "strokeOpacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-opacity" + }, + "strokeWidth": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-width][1]; a constant number in pixels, or a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-width" + }, + "target": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [target][1]; a constant string specifying the target window (_e.g._,\n*_blank*) for clickable links; used in conjunction with the **href** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/target" + }, + "tension": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The tension option only has an effect on bundle, cardinal and Catmull–Rom splines (*bundle*, *cardinal*, *cardinal-open*, *cardinal-closed*,\n*catmull-rom*, *catmull-rom-open*, and *catmull-rom-closed*). For bundle splines, it corresponds to [beta][1]; for cardinal splines, [tension][2]; for Catmull–Rom splines, [alpha][3].\n\n[1]: https://d3js.org/d3-shape/curve#curveBundle_beta [2]: https://d3js.org/d3-shape/curve#curveCardinal_tension [3]: https://d3js.org/d3-shape/curve#curveCatmullRom_alpha" + }, + "tip": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/TipPointer" + }, + { + "properties": { + "anchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The tip anchor specifies how to orient the tip box relative to its anchor position; it refers to the part of the tip box that is attached to the anchor point. For example, the *top-left* anchor places the top-left corner of tip box near the anchor position, hence placing the tip box below and to the right of the anchor position." + }, + "fontFamily": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font-family][1]; a constant; defaults to the plot’s font family, which is typically [*system-ui*][2].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-family [2]: https://drafts.csswg.org/css-fonts-4/#valdef-font-family-system-ui" + }, + "fontSize": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font size][1] in pixels; either a constant or a channel; defaults to the plot’s font size, which is typically 10. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-size" + }, + "fontStyle": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font style][1]; a constant; defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-style" + }, + "fontVariant": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font variant][1]; a constant; if the **text** channel contains numbers or dates, defaults to *tabular-nums* to facilitate comparing numbers; otherwise defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant" + }, + "fontWeight": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font weight][1]; a constant; defaults to the plot’s font weight, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight" + }, + "format": { + "additionalProperties": false, + "description": "How channel values are formatted for display. If a format is a string, it is interpreted as a (UTC) time format for temporal channels, and otherwise a number format.", + "properties": { + "ariaLabel": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fill": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fillOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fontSize": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fx": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fy": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "geometry": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "height": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "href": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "length": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "opacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "path": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "r": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "rotate": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "src": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "stroke": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeWidth": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "symbol": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "text": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "title": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "weight": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "width": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "z": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + } + }, + "type": "object" + }, + "frameAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The frame anchor specifies defaults for **x** and **y** based on the plot’s frame; it may be one of the four sides (*top*, *right*, *bottom*, *left*), one of the four corners (*top-left*, *top-right*, *bottom-right*,\n*bottom-left*), or the *middle* of the frame. For example, for tips distributed horizontally at the top of the frame:\n\n```js Plot.tip(data, {x: \"date\", frameAnchor: \"top\"}) ```" + }, + "lineHeight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line height in ems; defaults to 1. The line height affects the (typically vertical) separation between adjacent baselines of text, as well as the separation between the text and its anchor point." + }, + "lineWidth": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line width in ems (e.g., 10 for about 20 characters); defaults to infinity, disabling wrapping and clipping.\n\nIf **textOverflow** is null, lines will be wrapped at the specified length. If a line is split at a soft hyphen (\\xad), a hyphen (-) will be displayed at the end of the line. If **textOverflow** is not null, lines will be clipped according to the given strategy." + }, + "monospace": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, changes the default **fontFamily** to *monospace*, and uses simplified monospaced text metrics calculations." + }, + "pathFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The image filter for the tip’s box; defaults to a drop shadow." + }, + "pointer": { + "$ref": "#/definitions/TipPointer" + }, + "pointerSize": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The size of the tip’s pointer in pixels; defaults to 12." + }, + "preferredAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If an explicit tip anchor is not specified, an anchor is chosen automatically such that the tip fits within the plot’s frame; if the preferred anchor fits, it is chosen." + }, + "textAnchor": { + "anyOf": [ + { + "const": "start", + "type": "string" + }, + { + "const": "middle", + "type": "string" + }, + { + "const": "end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [text anchor][1] controls how text is aligned (typically horizontally) relative to its anchor point; it is one of *start*, *end*, or *middle*. If the frame anchor is *left*, *top-left*, or *bottom-left*, the default text anchor is *start*; if the frame anchor is *right*, *top-right*, or\n*bottom-right*, the default is *end*; otherwise it is *middle*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/text-anchor" + }, + "textOverflow": { + "anyOf": [ + { + "type": "null" + }, + { + "const": "clip", + "type": "string" + }, + { + "const": "ellipsis", + "type": "string" + }, + { + "const": "clip-start", + "type": "string" + }, + { + "const": "clip-end", + "type": "string" + }, + { + "const": "ellipsis-start", + "type": "string" + }, + { + "const": "ellipsis-middle", + "type": "string" + }, + { + "const": "ellipsis-end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How truncate (or wrap) lines of text longer than the given **lineWidth**; one of:\n\n- null (default) - preserve overflowing characters (and wrap if needed)\n- *clip* or *clip-end* - remove characters from the end\n- *clip-start* - remove characters from the start\n- *ellipsis* or *ellipsis-end* - replace characters from the end with an ellipsis (…)\n- *ellipsis-start* - replace characters from the start with an ellipsis (…)\n- *ellipsis-middle* - replace characters from the middle with an ellipsis (…)\n\nIf no **title** was specified, if text requires truncation, a title containing the non-truncated text will be implicitly added." + }, + "textPadding": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The padding around the text in pixels; defaults to 8." + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + } + }, + "type": "object" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to generate a tooltip for this mark, and any tip options." + }, + "title": { + "$ref": "#/definitions/ChannelValue", + "description": "The title; a channel specifying accessible, short textual descriptions as strings (possibly with newlines). If the tip option is specified, the title will be displayed with an interactive tooltip instead of using the SVG [title element][1].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/title" + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The required horizontal position channel, typically bound to the *x* scale." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel, typically bound to the *y* scale; defaults to the zero-based index of the data [0, 1, 2, …]." + }, + "z": { + "$ref": "#/definitions/ChannelValue", + "description": "An optional ordinal channel for grouping data into (possibly stacked) series to be drawn as separate lines. If not specified, it defaults to\n**fill** if a channel, or **stroke** if a channel." + } + }, + "required": [ + "data", + "mark" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "$schema": { + "description": "A [JSON schema](http://json-schema.org/) URL for this specification, such as https://uwdata.github.io/mosaic/schema/latest.json. This property enables validation and autocomplete in editors with JSON schema support.", + "format": "uri", + "type": "string" + }, + "ariaDescription": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-description][1]; a constant textual description.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-description" + }, + "ariaHidden": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-hidden][1] state; a constant indicating whether the element is exposed to an accessibility API.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-hidden" + }, + "ariaLabel": { + "$ref": "#/definitions/ChannelValue", + "description": "The [aria-label][1]; a channel specifying short textual labels representing the value in the accessibility tree.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-label" + }, + "clip": { + "anyOf": [ + { + "const": "frame", + "type": "string" + }, + { + "const": "sphere", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to clip the mark; one of:\n\n- *frame* or true - clip to the plot’s frame (inner area)\n- *sphere* - clip to the projected sphere (*e.g.*, front hemisphere)\n- null or false - do not clip\n\nThe *sphere* clip option requires a geographic projection." + }, + "config": { + "$ref": "#/definitions/Config", + "description": "Configuration options." + }, + "curve": { + "anyOf": [ + { + "$ref": "#/definitions/Curve" + }, + { + "const": "auto", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The curve (interpolation) method for connecting adjacent points. One of:\n\n- *basis* - a cubic basis spline (repeating the end points)\n- *basis-open* - an open cubic basis spline\n- *basis-closed* - a closed cubic basis spline\n- *bump-x* - a Bézier curve with horizontal tangents\n- *bump-y* - a Bézier curve with vertical tangents\n- *bundle* - a straightened cubic basis spline (suitable for lines only, not areas)\n- *cardinal* - a cubic cardinal spline (with one-sided differences at the ends)\n- *cardinal-open* - an open cubic cardinal spline\n- *cardinal-closed* - an closed cubic cardinal spline\n- *catmull-rom* - a cubic Catmull–Rom spline (with one-sided differences at the ends)\n- *catmull-rom-open* - an open cubic Catmull–Rom spline\n- *catmull-rom-closed* - a closed cubic Catmull–Rom spline\n- *linear* - a piecewise linear curve (*i.e.*, straight line segments)\n- *linear-closed* - a closed piecewise linear curve (*i.e.*, straight line segments)\n- *monotone-x* - a cubic spline that preserves monotonicity in *x*\n- *monotone-y* - a cubic spline that preserves monotonicity in *y*\n- *natural* - a natural cubic spline\n- *step* - a piecewise constant function where *y* changes at the midpoint of *x*\n- *step-after* - a piecewise constant function where *y* changes after *x*\n- *step-before* - a piecewise constant function where *x* changes after *y*\n- *auto* (default) - like *linear*, but use the (possibly spherical) projection, if any\n\nThe *auto* curve is typically used in conjunction with a spherical projection to interpolate along geodesics." + }, + "data": { + "$ref": "#/definitions/Data", + "description": "Dataset definitions." + }, + "dx": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The horizontal offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "dy": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The vertical offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "facet": { + "anyOf": [ + { + "const": "auto", + "type": "string" + }, + { + "const": "include", + "type": "string" + }, + { + "const": "exclude", + "type": "string" + }, + { + "const": "super", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to enable or disable faceting; one of:\n\n- *auto* (default) - automatically determine if this mark should be faceted\n- *include* (or true) - draw the subset of the mark’s data in the current facet\n- *exclude* - draw the subset of the mark’s data *not* in the current facet\n- *super* - draw this mark in a single frame that covers all facets\n- null (or false) - repeat this mark’s data across all facets (*i.e.*, no faceting)\n\nWhen a mark uses *super* faceting, it is not allowed to use position scales (*x*, *y*, *fx*, or *fy*); *super* faceting is intended for decorations, such as labels and legends.\n\nWhen top-level faceting is used, the default *auto* setting is equivalent to *include* when the mark data is strictly equal to the top-level facet data; otherwise it is equivalent to null. When the *include* or *exclude* facet mode is chosen, the mark data must be parallel to the top-level facet data: the data must have the same length and order. If the data are not parallel, then the wrong data may be shown in each facet. The default\n*auto* therefore requires strict equality (`===`) for safety, and using the facet data as mark data is recommended when using the *exclude* facet mode. (To construct parallel data safely, consider using [*array*.map][1] on the facet data.)\n\nWhen mark-level faceting is used, the default *auto* setting is equivalent to *include*: the mark will be faceted if either the **fx** or **fy** channel option (or both) is specified. The null or false option will disable faceting, while *exclude* draws the subset of the mark’s data *not* in the current facet.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map" + }, + "facetAnchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "right", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "const": "left", + "type": "string" + }, + { + "const": "top-left", + "type": "string" + }, + { + "const": "top-right", + "type": "string" + }, + { + "const": "bottom-left", + "type": "string" + }, + { + "const": "bottom-right", + "type": "string" + }, + { + "const": "top-empty", + "type": "string" + }, + { + "const": "right-empty", + "type": "string" + }, + { + "const": "bottom-empty", + "type": "string" + }, + { + "const": "left-empty", + "type": "string" + }, + { + "const": "empty", + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to place the mark with respect to facets; one of:\n\n- null (default for most marks) - display the mark in each non-empty facet\n- *top*, *right*, *bottom*, or *left* - display the mark only in facets on the given side\n- *top-empty*, *right-empty*, *bottom-empty*, or *left-empty* (default for axis marks) - display the mark only in facets that have empty space on the given side: either the margin, or an empty facet\n- *empty* - display the mark in empty facets only" + }, + "fill": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill" + }, + "fillOpacity": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill-opacity][1]; a constant number between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill-opacity" + }, + "filter": { + "$ref": "#/definitions/ChannelValue", + "description": "Applies a transform to filter the mark’s index according to the given channel values; only truthy values are retained.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "fx": { + "$ref": "#/definitions/ChannelValue", + "description": "The horizontal facet position channel, for mark-level faceting, bound to the *fx* scale." + }, + "fy": { + "$ref": "#/definitions/ChannelValue", + "description": "The vertical facet position channel, for mark-level faceting, bound to the\n*fy* scale." + }, + "href": { + "$ref": "#/definitions/ChannelValue", + "description": "The [href][1]; a channel specifying URLs for clickable links. May be used in conjunction with the **target** option to open links in another window.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/href" + }, + "imageFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A CSS [filter][1]; a constant string used to adjust the rendering of images, such as *blur(5px)*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/filter" + }, + "margin": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four mark margins: **marginTop**,\n**marginRight**, **marginBottom**, and **marginLeft**; typically defaults to 0, except for axis marks." + }, + "marginBottom": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s bottom margin; the minimum distance in pixels between the bottom edges of the inner and outer plot area." + }, + "marginLeft": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s left margin; the minimum distance in pixels between the left edges of the inner and outer plot area." + }, + "marginRight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s right margin; the minimum distance in pixels between the right edges of the mark’s inner and outer plot area." + }, + "marginTop": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s top margin; the minimum distance in pixels between the top edges of the inner and outer plot area." + }, + "mark": { + "const": "lineY", + "description": "Like line, except **y** defaults to the identity function and assumes that *data* = [*y₀*, *y₁*, *y₂*, …] and **x** defaults to the zero-based index [0, 1, 2, …].", + "type": "string" + }, + "marker": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for markerStart, markerMid, and markerEnd; one of:\n\n- a marker name such as *arrow* or *circle*\n- *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*" + }, + "markerEnd": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The marker for the ending point of a line segment; one of:\n\n- a marker name such as *arrow* or *circle*\n* *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*" + }, + "markerMid": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The marker for any middle (interior) points of a line segment. If the line segment only has a start and end point, this option has no effect. One of:\n\n- a marker name such as *arrow* or *circle*\n* *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*\n* a function - a custom marker function; see below" + }, + "markerStart": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The marker for the starting point of a line segment; one of:\n\n- a marker name such as *arrow* or *circle*\n* *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*" + }, + "meta": { + "$ref": "#/definitions/Meta", + "description": "Specification metadata." + }, + "mixBlendMode": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [mix-blend-mode][1]; a constant string specifying how to blend content such as *multiply*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode" + }, + "opacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally. For faster rendering, prefer the **strokeOpacity** or **fillOpacity** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/opacity" + }, + "paintOrder": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [paint-order][1]; a constant string specifying the order in which the\n**fill**, **stroke**, and any markers are drawn; defaults to *normal*, which draws the fill, then stroke, then markers; defaults to *stroke* for the text mark to create a “halo” around text to improve legibility.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/paint-order" + }, + "params": { + "$ref": "#/definitions/Params", + "description": "Param and Selection definitions." + }, + "plotDefaults": { + "$ref": "#/definitions/PlotAttributes", + "description": "A default set of attributes to apply to all plot components." + }, + "pointerEvents": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [pointer-events][1] property; a constant string such as *none*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/pointer-events" + }, + "reverse": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Applies a transform to reverse the order of the mark’s index, say for reverse input order." + }, + "select": { + "$ref": "#/definitions/SelectFilter", + "description": "Applies a filter transform after data is loaded to highlight selected values only. For example, `first` and `last` select the first or last values of series only (using the *z* channel to separate series). Meanwhile, `nearestX` and `nearestY` select the point nearest to the pointer along the *x* or *y* channel dimension. Unlike Mosaic selections, a mark level *select* is internal to the mark only, and does not populate a param or selection value to be shared across clients.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "shapeRendering": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [shape-rendering][1]; a constant string such as *crispEdges*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/shape-rendering" + }, + "sort": { + "anyOf": [ + { + "$ref": "#/definitions/SortOrder" + }, + { + "$ref": "#/definitions/ChannelDomainSort" + } + ], + "description": "Either applies a transform to sort the mark’s index by the specified channel values, or imputes ordinal scale domains from this mark’s channels.\n\nWhen imputing ordinal scale domains from channel values, the **sort** option is an object whose keys are ordinal scale names such as *x* or *fx*, and whose values are channel names such as *y*, *y1*, or *y2*. For example, to impute the *y* scale’s domain from the associated *x* channel values in ascending order:\n\n```js sort: {y: \"x\"} ```\n\nFor different sort options for different scales, replace the channel name with a *value* object and per-scale options:\n\n```js sort: {y: {value: \"-x\"}} ```\n\nWhen sorting the mark’s index, the **sort** option is instead one of:\n\n- a channel value definition for sorting given values in ascending order\n- a {value, order} object for sorting given values\n- a {channel, order} object for sorting the named channel’s values" + }, + "stroke": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke" + }, + "strokeDasharray": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dasharray][1]; a constant number indicating the length in pixels of alternating dashes and gaps, or a constant string of numbers separated by spaces or commas (_e.g._, *10 2* for dashes of 10 pixels separated by gaps of 2 pixels), or *none* (the default) for no dashing\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dasharray" + }, + "strokeDashoffset": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dashoffset][1]; a constant indicating the offset in pixels of the first dash along the stroke; defaults to zero.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dashoffset" + }, + "strokeLinecap": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linecap][1]; a constant specifying how to cap stroked paths, such as *butt*, *round*, or *square*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linecap" + }, + "strokeLinejoin": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linejoin][1]; a constant specifying how to join stroked paths, such as *bevel*, *miter*, *miter-clip*, or *round*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linejoin" + }, + "strokeMiterlimit": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-miterlimit][1]; a constant number specifying how to limit the length of *miter* joins on stroked paths.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-miterlimit" + }, + "strokeOpacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-opacity" + }, + "strokeWidth": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-width][1]; a constant number in pixels, or a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-width" + }, + "target": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [target][1]; a constant string specifying the target window (_e.g._,\n*_blank*) for clickable links; used in conjunction with the **href** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/target" + }, + "tension": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The tension option only has an effect on bundle, cardinal and Catmull–Rom splines (*bundle*, *cardinal*, *cardinal-open*, *cardinal-closed*,\n*catmull-rom*, *catmull-rom-open*, and *catmull-rom-closed*). For bundle splines, it corresponds to [beta][1]; for cardinal splines, [tension][2]; for Catmull–Rom splines, [alpha][3].\n\n[1]: https://d3js.org/d3-shape/curve#curveBundle_beta [2]: https://d3js.org/d3-shape/curve#curveCardinal_tension [3]: https://d3js.org/d3-shape/curve#curveCatmullRom_alpha" + }, + "tip": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/TipPointer" + }, + { + "properties": { + "anchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The tip anchor specifies how to orient the tip box relative to its anchor position; it refers to the part of the tip box that is attached to the anchor point. For example, the *top-left* anchor places the top-left corner of tip box near the anchor position, hence placing the tip box below and to the right of the anchor position." + }, + "fontFamily": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font-family][1]; a constant; defaults to the plot’s font family, which is typically [*system-ui*][2].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-family [2]: https://drafts.csswg.org/css-fonts-4/#valdef-font-family-system-ui" + }, + "fontSize": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font size][1] in pixels; either a constant or a channel; defaults to the plot’s font size, which is typically 10. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-size" + }, + "fontStyle": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font style][1]; a constant; defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-style" + }, + "fontVariant": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font variant][1]; a constant; if the **text** channel contains numbers or dates, defaults to *tabular-nums* to facilitate comparing numbers; otherwise defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant" + }, + "fontWeight": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font weight][1]; a constant; defaults to the plot’s font weight, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight" + }, + "format": { + "additionalProperties": false, + "description": "How channel values are formatted for display. If a format is a string, it is interpreted as a (UTC) time format for temporal channels, and otherwise a number format.", + "properties": { + "ariaLabel": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fill": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fillOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fontSize": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fx": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fy": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "geometry": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "height": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "href": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "length": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "opacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "path": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "r": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "rotate": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "src": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "stroke": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeWidth": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "symbol": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "text": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "title": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "weight": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "width": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "z": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + } + }, + "type": "object" + }, + "frameAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The frame anchor specifies defaults for **x** and **y** based on the plot’s frame; it may be one of the four sides (*top*, *right*, *bottom*, *left*), one of the four corners (*top-left*, *top-right*, *bottom-right*,\n*bottom-left*), or the *middle* of the frame. For example, for tips distributed horizontally at the top of the frame:\n\n```js Plot.tip(data, {x: \"date\", frameAnchor: \"top\"}) ```" + }, + "lineHeight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line height in ems; defaults to 1. The line height affects the (typically vertical) separation between adjacent baselines of text, as well as the separation between the text and its anchor point." + }, + "lineWidth": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line width in ems (e.g., 10 for about 20 characters); defaults to infinity, disabling wrapping and clipping.\n\nIf **textOverflow** is null, lines will be wrapped at the specified length. If a line is split at a soft hyphen (\\xad), a hyphen (-) will be displayed at the end of the line. If **textOverflow** is not null, lines will be clipped according to the given strategy." + }, + "monospace": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, changes the default **fontFamily** to *monospace*, and uses simplified monospaced text metrics calculations." + }, + "pathFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The image filter for the tip’s box; defaults to a drop shadow." + }, + "pointer": { + "$ref": "#/definitions/TipPointer" + }, + "pointerSize": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The size of the tip’s pointer in pixels; defaults to 12." + }, + "preferredAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If an explicit tip anchor is not specified, an anchor is chosen automatically such that the tip fits within the plot’s frame; if the preferred anchor fits, it is chosen." + }, + "textAnchor": { + "anyOf": [ + { + "const": "start", + "type": "string" + }, + { + "const": "middle", + "type": "string" + }, + { + "const": "end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [text anchor][1] controls how text is aligned (typically horizontally) relative to its anchor point; it is one of *start*, *end*, or *middle*. If the frame anchor is *left*, *top-left*, or *bottom-left*, the default text anchor is *start*; if the frame anchor is *right*, *top-right*, or\n*bottom-right*, the default is *end*; otherwise it is *middle*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/text-anchor" + }, + "textOverflow": { + "anyOf": [ + { + "type": "null" + }, + { + "const": "clip", + "type": "string" + }, + { + "const": "ellipsis", + "type": "string" + }, + { + "const": "clip-start", + "type": "string" + }, + { + "const": "clip-end", + "type": "string" + }, + { + "const": "ellipsis-start", + "type": "string" + }, + { + "const": "ellipsis-middle", + "type": "string" + }, + { + "const": "ellipsis-end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How truncate (or wrap) lines of text longer than the given **lineWidth**; one of:\n\n- null (default) - preserve overflowing characters (and wrap if needed)\n- *clip* or *clip-end* - remove characters from the end\n- *clip-start* - remove characters from the start\n- *ellipsis* or *ellipsis-end* - replace characters from the end with an ellipsis (…)\n- *ellipsis-start* - replace characters from the start with an ellipsis (…)\n- *ellipsis-middle* - replace characters from the middle with an ellipsis (…)\n\nIf no **title** was specified, if text requires truncation, a title containing the non-truncated text will be implicitly added." + }, + "textPadding": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The padding around the text in pixels; defaults to 8." + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + } + }, + "type": "object" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to generate a tooltip for this mark, and any tip options." + }, + "title": { + "$ref": "#/definitions/ChannelValue", + "description": "The title; a channel specifying accessible, short textual descriptions as strings (possibly with newlines). If the tip option is specified, the title will be displayed with an interactive tooltip instead of using the SVG [title element][1].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/title" + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel, typically bound to the *x* scale; defaults to the zero-based index of the data [0, 1, 2, …]." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The required vertical position channel, typically bound to the *y* scale." + }, + "z": { + "$ref": "#/definitions/ChannelValue", + "description": "An optional ordinal channel for grouping data into (possibly stacked) series to be drawn as separate lines. If not specified, it defaults to\n**fill** if a channel, or **stroke** if a channel." + } + }, + "required": [ + "data", + "mark" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "$schema": { + "description": "A [JSON schema](http://json-schema.org/) URL for this specification, such as https://uwdata.github.io/mosaic/schema/latest.json. This property enables validation and autocomplete in editors with JSON schema support.", + "format": "uri", + "type": "string" + }, + "ariaDescription": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-description][1]; a constant textual description.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-description" + }, + "ariaHidden": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-hidden][1] state; a constant indicating whether the element is exposed to an accessibility API.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-hidden" + }, + "ariaLabel": { + "$ref": "#/definitions/ChannelValue", + "description": "The [aria-label][1]; a channel specifying short textual labels representing the value in the accessibility tree.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-label" + }, + "clip": { + "anyOf": [ + { + "const": "frame", + "type": "string" + }, + { + "const": "sphere", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to clip the mark; one of:\n\n- *frame* or true - clip to the plot’s frame (inner area)\n- *sphere* - clip to the projected sphere (*e.g.*, front hemisphere)\n- null or false - do not clip\n\nThe *sphere* clip option requires a geographic projection." + }, + "config": { + "$ref": "#/definitions/Config", + "description": "Configuration options." + }, + "curve": { + "anyOf": [ + { + "anyOf": [ + { + "$ref": "#/definitions/Curve" + }, + { + "const": "auto", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The curve (interpolation) method for connecting adjacent points. One of:\n\n- *basis* - a cubic basis spline (repeating the end points)\n- *basis-open* - an open cubic basis spline\n- *basis-closed* - a closed cubic basis spline\n- *bump-x* - a Bézier curve with horizontal tangents\n- *bump-y* - a Bézier curve with vertical tangents\n- *bundle* - a straightened cubic basis spline (suitable for lines only, not areas)\n- *cardinal* - a cubic cardinal spline (with one-sided differences at the ends)\n- *cardinal-open* - an open cubic cardinal spline\n- *cardinal-closed* - an closed cubic cardinal spline\n- *catmull-rom* - a cubic Catmull–Rom spline (with one-sided differences at the ends)\n- *catmull-rom-open* - an open cubic Catmull–Rom spline\n- *catmull-rom-closed* - a closed cubic Catmull–Rom spline\n- *linear* - a piecewise linear curve (*i.e.*, straight line segments)\n- *linear-closed* - a closed piecewise linear curve (*i.e.*, straight line segments)\n- *monotone-x* - a cubic spline that preserves monotonicity in *x*\n- *monotone-y* - a cubic spline that preserves monotonicity in *y*\n- *natural* - a natural cubic spline\n- *step* - a piecewise constant function where *y* changes at the midpoint of *x*\n- *step-after* - a piecewise constant function where *y* changes after *x*\n- *step-before* - a piecewise constant function where *x* changes after *y*\n- *auto* (default) - like *linear*, but use the (possibly spherical) projection, if any\n\nThe *auto* curve is typically used in conjunction with a spherical projection to interpolate along geodesics." + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The curve (interpolation) method for connecting adjacent points.\n\nSince a link has exactly two points, only the following curves (or a custom curve) are recommended: *linear*, *step*, *step-after*, *step-before*,\n*bump-x*, or *bump-y*. Note that the *linear* curve is incapable of showing a fill since a straight line has zero area. For a curved link, use an arrow mark with the **bend** option.\n\nIf the plot uses a spherical **projection**, the default *auto* **curve** will render links as geodesics; to draw a straight line instead, use the\n*linear* **curve**." + }, + "data": { + "$ref": "#/definitions/Data", + "description": "Dataset definitions." + }, + "dx": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The horizontal offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "dy": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The vertical offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "facet": { + "anyOf": [ + { + "const": "auto", + "type": "string" + }, + { + "const": "include", + "type": "string" + }, + { + "const": "exclude", + "type": "string" + }, + { + "const": "super", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to enable or disable faceting; one of:\n\n- *auto* (default) - automatically determine if this mark should be faceted\n- *include* (or true) - draw the subset of the mark’s data in the current facet\n- *exclude* - draw the subset of the mark’s data *not* in the current facet\n- *super* - draw this mark in a single frame that covers all facets\n- null (or false) - repeat this mark’s data across all facets (*i.e.*, no faceting)\n\nWhen a mark uses *super* faceting, it is not allowed to use position scales (*x*, *y*, *fx*, or *fy*); *super* faceting is intended for decorations, such as labels and legends.\n\nWhen top-level faceting is used, the default *auto* setting is equivalent to *include* when the mark data is strictly equal to the top-level facet data; otherwise it is equivalent to null. When the *include* or *exclude* facet mode is chosen, the mark data must be parallel to the top-level facet data: the data must have the same length and order. If the data are not parallel, then the wrong data may be shown in each facet. The default\n*auto* therefore requires strict equality (`===`) for safety, and using the facet data as mark data is recommended when using the *exclude* facet mode. (To construct parallel data safely, consider using [*array*.map][1] on the facet data.)\n\nWhen mark-level faceting is used, the default *auto* setting is equivalent to *include*: the mark will be faceted if either the **fx** or **fy** channel option (or both) is specified. The null or false option will disable faceting, while *exclude* draws the subset of the mark’s data *not* in the current facet.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map" + }, + "facetAnchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "right", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "const": "left", + "type": "string" + }, + { + "const": "top-left", + "type": "string" + }, + { + "const": "top-right", + "type": "string" + }, + { + "const": "bottom-left", + "type": "string" + }, + { + "const": "bottom-right", + "type": "string" + }, + { + "const": "top-empty", + "type": "string" + }, + { + "const": "right-empty", + "type": "string" + }, + { + "const": "bottom-empty", + "type": "string" + }, + { + "const": "left-empty", + "type": "string" + }, + { + "const": "empty", + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to place the mark with respect to facets; one of:\n\n- null (default for most marks) - display the mark in each non-empty facet\n- *top*, *right*, *bottom*, or *left* - display the mark only in facets on the given side\n- *top-empty*, *right-empty*, *bottom-empty*, or *left-empty* (default for axis marks) - display the mark only in facets that have empty space on the given side: either the margin, or an empty facet\n- *empty* - display the mark in empty facets only" + }, + "fill": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill" + }, + "fillOpacity": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill-opacity][1]; a constant number between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill-opacity" + }, + "filter": { + "$ref": "#/definitions/ChannelValue", + "description": "Applies a transform to filter the mark’s index according to the given channel values; only truthy values are retained.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "fx": { + "$ref": "#/definitions/ChannelValue", + "description": "The horizontal facet position channel, for mark-level faceting, bound to the *fx* scale." + }, + "fy": { + "$ref": "#/definitions/ChannelValue", + "description": "The vertical facet position channel, for mark-level faceting, bound to the\n*fy* scale." + }, + "href": { + "$ref": "#/definitions/ChannelValue", + "description": "The [href][1]; a channel specifying URLs for clickable links. May be used in conjunction with the **target** option to open links in another window.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/href" + }, + "imageFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A CSS [filter][1]; a constant string used to adjust the rendering of images, such as *blur(5px)*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/filter" + }, + "margin": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four mark margins: **marginTop**,\n**marginRight**, **marginBottom**, and **marginLeft**; typically defaults to 0, except for axis marks." + }, + "marginBottom": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s bottom margin; the minimum distance in pixels between the bottom edges of the inner and outer plot area." + }, + "marginLeft": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s left margin; the minimum distance in pixels between the left edges of the inner and outer plot area." + }, + "marginRight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s right margin; the minimum distance in pixels between the right edges of the mark’s inner and outer plot area." + }, + "marginTop": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s top margin; the minimum distance in pixels between the top edges of the inner and outer plot area." + }, + "mark": { + "const": "link", + "description": "A link mark, drawing line segments (curves) connecting pairs of points.\n\nIf the plot uses a spherical **projection**, the default *auto* **curve** will render links as geodesics; to draw a straight line instead, use the\n*linear* **curve**.", + "type": "string" + }, + "marker": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for markerStart, markerMid, and markerEnd; one of:\n\n- a marker name such as *arrow* or *circle*\n- *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*" + }, + "markerEnd": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The marker for the ending point of a line segment; one of:\n\n- a marker name such as *arrow* or *circle*\n* *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*" + }, + "markerMid": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The marker for any middle (interior) points of a line segment. If the line segment only has a start and end point, this option has no effect. One of:\n\n- a marker name such as *arrow* or *circle*\n* *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*\n* a function - a custom marker function; see below" + }, + "markerStart": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The marker for the starting point of a line segment; one of:\n\n- a marker name such as *arrow* or *circle*\n* *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*" + }, + "meta": { + "$ref": "#/definitions/Meta", + "description": "Specification metadata." + }, + "mixBlendMode": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [mix-blend-mode][1]; a constant string specifying how to blend content such as *multiply*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode" + }, + "opacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally. For faster rendering, prefer the **strokeOpacity** or **fillOpacity** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/opacity" + }, + "paintOrder": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [paint-order][1]; a constant string specifying the order in which the\n**fill**, **stroke**, and any markers are drawn; defaults to *normal*, which draws the fill, then stroke, then markers; defaults to *stroke* for the text mark to create a “halo” around text to improve legibility.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/paint-order" + }, + "params": { + "$ref": "#/definitions/Params", + "description": "Param and Selection definitions." + }, + "plotDefaults": { + "$ref": "#/definitions/PlotAttributes", + "description": "A default set of attributes to apply to all plot components." + }, + "pointerEvents": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [pointer-events][1] property; a constant string such as *none*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/pointer-events" + }, + "reverse": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Applies a transform to reverse the order of the mark’s index, say for reverse input order." + }, + "select": { + "$ref": "#/definitions/SelectFilter", + "description": "Applies a filter transform after data is loaded to highlight selected values only. For example, `first` and `last` select the first or last values of series only (using the *z* channel to separate series). Meanwhile, `nearestX` and `nearestY` select the point nearest to the pointer along the *x* or *y* channel dimension. Unlike Mosaic selections, a mark level *select* is internal to the mark only, and does not populate a param or selection value to be shared across clients.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "shapeRendering": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [shape-rendering][1]; a constant string such as *crispEdges*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/shape-rendering" + }, + "sort": { + "anyOf": [ + { + "$ref": "#/definitions/SortOrder" + }, + { + "$ref": "#/definitions/ChannelDomainSort" + } + ], + "description": "Either applies a transform to sort the mark’s index by the specified channel values, or imputes ordinal scale domains from this mark’s channels.\n\nWhen imputing ordinal scale domains from channel values, the **sort** option is an object whose keys are ordinal scale names such as *x* or *fx*, and whose values are channel names such as *y*, *y1*, or *y2*. For example, to impute the *y* scale’s domain from the associated *x* channel values in ascending order:\n\n```js sort: {y: \"x\"} ```\n\nFor different sort options for different scales, replace the channel name with a *value* object and per-scale options:\n\n```js sort: {y: {value: \"-x\"}} ```\n\nWhen sorting the mark’s index, the **sort** option is instead one of:\n\n- a channel value definition for sorting given values in ascending order\n- a {value, order} object for sorting given values\n- a {channel, order} object for sorting the named channel’s values" + }, + "stroke": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke" + }, + "strokeDasharray": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dasharray][1]; a constant number indicating the length in pixels of alternating dashes and gaps, or a constant string of numbers separated by spaces or commas (_e.g._, *10 2* for dashes of 10 pixels separated by gaps of 2 pixels), or *none* (the default) for no dashing\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dasharray" + }, + "strokeDashoffset": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dashoffset][1]; a constant indicating the offset in pixels of the first dash along the stroke; defaults to zero.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dashoffset" + }, + "strokeLinecap": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linecap][1]; a constant specifying how to cap stroked paths, such as *butt*, *round*, or *square*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linecap" + }, + "strokeLinejoin": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linejoin][1]; a constant specifying how to join stroked paths, such as *bevel*, *miter*, *miter-clip*, or *round*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linejoin" + }, + "strokeMiterlimit": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-miterlimit][1]; a constant number specifying how to limit the length of *miter* joins on stroked paths.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-miterlimit" + }, + "strokeOpacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-opacity" + }, + "strokeWidth": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-width][1]; a constant number in pixels, or a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-width" + }, + "target": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [target][1]; a constant string specifying the target window (_e.g._,\n*_blank*) for clickable links; used in conjunction with the **href** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/target" + }, + "tension": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The tension option only has an effect on bundle, cardinal and Catmull–Rom splines (*bundle*, *cardinal*, *cardinal-open*, *cardinal-closed*,\n*catmull-rom*, *catmull-rom-open*, and *catmull-rom-closed*). For bundle splines, it corresponds to [beta][1]; for cardinal splines, [tension][2]; for Catmull–Rom splines, [alpha][3].\n\n[1]: https://d3js.org/d3-shape/curve#curveBundle_beta [2]: https://d3js.org/d3-shape/curve#curveCardinal_tension [3]: https://d3js.org/d3-shape/curve#curveCatmullRom_alpha" + }, + "tip": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/TipPointer" + }, + { + "properties": { + "anchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The tip anchor specifies how to orient the tip box relative to its anchor position; it refers to the part of the tip box that is attached to the anchor point. For example, the *top-left* anchor places the top-left corner of tip box near the anchor position, hence placing the tip box below and to the right of the anchor position." + }, + "fontFamily": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font-family][1]; a constant; defaults to the plot’s font family, which is typically [*system-ui*][2].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-family [2]: https://drafts.csswg.org/css-fonts-4/#valdef-font-family-system-ui" + }, + "fontSize": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font size][1] in pixels; either a constant or a channel; defaults to the plot’s font size, which is typically 10. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-size" + }, + "fontStyle": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font style][1]; a constant; defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-style" + }, + "fontVariant": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font variant][1]; a constant; if the **text** channel contains numbers or dates, defaults to *tabular-nums* to facilitate comparing numbers; otherwise defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant" + }, + "fontWeight": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font weight][1]; a constant; defaults to the plot’s font weight, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight" + }, + "format": { + "additionalProperties": false, + "description": "How channel values are formatted for display. If a format is a string, it is interpreted as a (UTC) time format for temporal channels, and otherwise a number format.", + "properties": { + "ariaLabel": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fill": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fillOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fontSize": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fx": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fy": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "geometry": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "height": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "href": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "length": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "opacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "path": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "r": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "rotate": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "src": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "stroke": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeWidth": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "symbol": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "text": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "title": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "weight": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "width": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "z": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + } + }, + "type": "object" + }, + "frameAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The frame anchor specifies defaults for **x** and **y** based on the plot’s frame; it may be one of the four sides (*top*, *right*, *bottom*, *left*), one of the four corners (*top-left*, *top-right*, *bottom-right*,\n*bottom-left*), or the *middle* of the frame. For example, for tips distributed horizontally at the top of the frame:\n\n```js Plot.tip(data, {x: \"date\", frameAnchor: \"top\"}) ```" + }, + "lineHeight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line height in ems; defaults to 1. The line height affects the (typically vertical) separation between adjacent baselines of text, as well as the separation between the text and its anchor point." + }, + "lineWidth": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line width in ems (e.g., 10 for about 20 characters); defaults to infinity, disabling wrapping and clipping.\n\nIf **textOverflow** is null, lines will be wrapped at the specified length. If a line is split at a soft hyphen (\\xad), a hyphen (-) will be displayed at the end of the line. If **textOverflow** is not null, lines will be clipped according to the given strategy." + }, + "monospace": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, changes the default **fontFamily** to *monospace*, and uses simplified monospaced text metrics calculations." + }, + "pathFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The image filter for the tip’s box; defaults to a drop shadow." + }, + "pointer": { + "$ref": "#/definitions/TipPointer" + }, + "pointerSize": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The size of the tip’s pointer in pixels; defaults to 12." + }, + "preferredAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If an explicit tip anchor is not specified, an anchor is chosen automatically such that the tip fits within the plot’s frame; if the preferred anchor fits, it is chosen." + }, + "textAnchor": { + "anyOf": [ + { + "const": "start", + "type": "string" + }, + { + "const": "middle", + "type": "string" + }, + { + "const": "end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [text anchor][1] controls how text is aligned (typically horizontally) relative to its anchor point; it is one of *start*, *end*, or *middle*. If the frame anchor is *left*, *top-left*, or *bottom-left*, the default text anchor is *start*; if the frame anchor is *right*, *top-right*, or\n*bottom-right*, the default is *end*; otherwise it is *middle*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/text-anchor" + }, + "textOverflow": { + "anyOf": [ + { + "type": "null" + }, + { + "const": "clip", + "type": "string" + }, + { + "const": "ellipsis", + "type": "string" + }, + { + "const": "clip-start", + "type": "string" + }, + { + "const": "clip-end", + "type": "string" + }, + { + "const": "ellipsis-start", + "type": "string" + }, + { + "const": "ellipsis-middle", + "type": "string" + }, + { + "const": "ellipsis-end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How truncate (or wrap) lines of text longer than the given **lineWidth**; one of:\n\n- null (default) - preserve overflowing characters (and wrap if needed)\n- *clip* or *clip-end* - remove characters from the end\n- *clip-start* - remove characters from the start\n- *ellipsis* or *ellipsis-end* - replace characters from the end with an ellipsis (…)\n- *ellipsis-start* - replace characters from the start with an ellipsis (…)\n- *ellipsis-middle* - replace characters from the middle with an ellipsis (…)\n\nIf no **title** was specified, if text requires truncation, a title containing the non-truncated text will be implicitly added." + }, + "textPadding": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The padding around the text in pixels; defaults to 8." + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + } + }, + "type": "object" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to generate a tooltip for this mark, and any tip options." + }, + "title": { + "$ref": "#/definitions/ChannelValue", + "description": "The title; a channel specifying accessible, short textual descriptions as strings (possibly with newlines). If the tip option is specified, the title will be displayed with an interactive tooltip instead of using the SVG [title element][1].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/title" + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position, for vertical links; typically bound to the *x* scale; shorthand for setting defaults for both **x1** and **x2**." + }, + "x1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting horizontal position; typically bound to the *x* scale; also sets a default for **x2**." + }, + "x2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending horizontal position; typically bound to the *x* scale; also sets a default for **x1**." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position, for horizontal links; typically bound to the *y* scale; shorthand for setting defaults for both **y1** and **y2**." + }, + "y1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting vertical position; typically bound to the *y* scale; also sets a default for **y2**." + }, + "y2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending vertical position; typically bound to the *y* scale; also sets a default for **y1**." + } + }, + "required": [ + "data", + "mark" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "$schema": { + "description": "A [JSON schema](http://json-schema.org/) URL for this specification, such as https://uwdata.github.io/mosaic/schema/latest.json. This property enables validation and autocomplete in editors with JSON schema support.", + "format": "uri", + "type": "string" + }, + "ariaDescription": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-description][1]; a constant textual description.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-description" + }, + "ariaHidden": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-hidden][1] state; a constant indicating whether the element is exposed to an accessibility API.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-hidden" + }, + "ariaLabel": { + "$ref": "#/definitions/ChannelValue", + "description": "The [aria-label][1]; a channel specifying short textual labels representing the value in the accessibility tree.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-label" + }, + "bandwidth": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The kernel density bandwidth for smoothing, in pixels." + }, + "clip": { + "anyOf": [ + { + "const": "frame", + "type": "string" + }, + { + "const": "sphere", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to clip the mark; one of:\n\n- *frame* or true - clip to the plot’s frame (inner area)\n- *sphere* - clip to the projected sphere (*e.g.*, front hemisphere)\n- null or false - do not clip\n\nThe *sphere* clip option requires a geographic projection." + }, + "config": { + "$ref": "#/definitions/Config", + "description": "Configuration options." + }, + "data": { + "$ref": "#/definitions/Data", + "description": "Dataset definitions." + }, + "dx": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The horizontal offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "dy": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The vertical offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "facet": { + "anyOf": [ + { + "const": "auto", + "type": "string" + }, + { + "const": "include", + "type": "string" + }, + { + "const": "exclude", + "type": "string" + }, + { + "const": "super", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to enable or disable faceting; one of:\n\n- *auto* (default) - automatically determine if this mark should be faceted\n- *include* (or true) - draw the subset of the mark’s data in the current facet\n- *exclude* - draw the subset of the mark’s data *not* in the current facet\n- *super* - draw this mark in a single frame that covers all facets\n- null (or false) - repeat this mark’s data across all facets (*i.e.*, no faceting)\n\nWhen a mark uses *super* faceting, it is not allowed to use position scales (*x*, *y*, *fx*, or *fy*); *super* faceting is intended for decorations, such as labels and legends.\n\nWhen top-level faceting is used, the default *auto* setting is equivalent to *include* when the mark data is strictly equal to the top-level facet data; otherwise it is equivalent to null. When the *include* or *exclude* facet mode is chosen, the mark data must be parallel to the top-level facet data: the data must have the same length and order. If the data are not parallel, then the wrong data may be shown in each facet. The default\n*auto* therefore requires strict equality (`===`) for safety, and using the facet data as mark data is recommended when using the *exclude* facet mode. (To construct parallel data safely, consider using [*array*.map][1] on the facet data.)\n\nWhen mark-level faceting is used, the default *auto* setting is equivalent to *include*: the mark will be faceted if either the **fx** or **fy** channel option (or both) is specified. The null or false option will disable faceting, while *exclude* draws the subset of the mark’s data *not* in the current facet.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map" + }, + "facetAnchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "right", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "const": "left", + "type": "string" + }, + { + "const": "top-left", + "type": "string" + }, + { + "const": "top-right", + "type": "string" + }, + { + "const": "bottom-left", + "type": "string" + }, + { + "const": "bottom-right", + "type": "string" + }, + { + "const": "top-empty", + "type": "string" + }, + { + "const": "right-empty", + "type": "string" + }, + { + "const": "bottom-empty", + "type": "string" + }, + { + "const": "left-empty", + "type": "string" + }, + { + "const": "empty", + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to place the mark with respect to facets; one of:\n\n- null (default for most marks) - display the mark in each non-empty facet\n- *top*, *right*, *bottom*, or *left* - display the mark only in facets on the given side\n- *top-empty*, *right-empty*, *bottom-empty*, or *left-empty* (default for axis marks) - display the mark only in facets that have empty space on the given side: either the margin, or an empty facet\n- *empty* - display the mark in empty facets only" + }, + "fill": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The fill, typically bound to the *color* scale. Can be specified as a constant or a channel based on the input data. Use the special value `\"density\"` to map computed density values to pixel colors. Use an aggregate expression to instead visualize an aggregate value per raster bin. If fill is set to a constant color or to a non-aggregate field, opacity will be used to convey densities. If a non-aggregate (group by) field is provided, multiple rasters are created with a unique categorical color per layer." + }, + "fillOpacity": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The opacity, typically bound to the *opacity* scale. Can be specified as a constant or a channel based on the input data. Use the special value `\"density\"` to map computed density values to opacity. Use an aggregate expression to instead visualize an aggregate value per raster bin." + }, + "filter": { + "$ref": "#/definitions/ChannelValue", + "description": "Applies a transform to filter the mark’s index according to the given channel values; only truthy values are retained.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "fx": { + "$ref": "#/definitions/ChannelValue", + "description": "The horizontal facet position channel, for mark-level faceting, bound to the *fx* scale." + }, + "fy": { + "$ref": "#/definitions/ChannelValue", + "description": "The vertical facet position channel, for mark-level faceting, bound to the\n*fy* scale." + }, + "height": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The height (number of rows) of the grid, in actual pixels." + }, + "href": { + "$ref": "#/definitions/ChannelValue", + "description": "The [href][1]; a channel specifying URLs for clickable links. May be used in conjunction with the **target** option to open links in another window.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/href" + }, + "imageFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A CSS [filter][1]; a constant string used to adjust the rendering of images, such as *blur(5px)*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/filter" + }, + "imageRendering": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [image-rendering attribute][1]; defaults to *auto* (bilinear). The option may be set to *pixelated* to disable bilinear interpolation for a sharper image; however, note that this is not supported in WebKit.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/image-rendering" + }, + "interpolate": { + "anyOf": [ + { + "$ref": "#/definitions/GridInterpolate" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The spatial interpolation method; one of:\n\n- *none* - do not perform interpolation (the default), maps samples to single bins\n- *linear* - apply proportional linear interpolation across adjacent bins\n- *nearest* - assign each pixel to the closest sample’s value (Voronoi diagram)\n- *barycentric* - apply barycentric interpolation over the Delaunay triangulation\n- *random-walk* - apply a random walk from each pixel, stopping when near a sample" + }, + "margin": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four mark margins: **marginTop**,\n**marginRight**, **marginBottom**, and **marginLeft**; typically defaults to 0, except for axis marks." + }, + "marginBottom": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s bottom margin; the minimum distance in pixels between the bottom edges of the inner and outer plot area." + }, + "marginLeft": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s left margin; the minimum distance in pixels between the left edges of the inner and outer plot area." + }, + "marginRight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s right margin; the minimum distance in pixels between the right edges of the mark’s inner and outer plot area." + }, + "marginTop": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s top margin; the minimum distance in pixels between the top edges of the inner and outer plot area." + }, + "mark": { + "const": "raster", + "description": "A raster mark which renders a raster image from spatial samples. It represents discrete samples in abstract coordinates **x** and **y**; the **fill** and **fillOpacity** channels specify further abstract values (_e.g._, height in a topographic map) to be spatially interpolated to produce an image.\n\nThe **x** and **y** data domains are binned into the cells (\"pixels\") of a raster grid, typically with an aggregate function evaluated over the binned data. The result can be optionally smoothed (blurred).\n\nTo create a smoothed density heatmap, use the heatmap mark, which is a raster mark with different default options.", + "type": "string" + }, + "meta": { + "$ref": "#/definitions/Meta", + "description": "Specification metadata." + }, + "mixBlendMode": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [mix-blend-mode][1]; a constant string specifying how to blend content such as *multiply*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode" + }, + "opacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally. For faster rendering, prefer the **strokeOpacity** or **fillOpacity** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/opacity" + }, + "pad": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The bin padding, one of 1 (default) to include extra padding for the final bin, or 0 to make the bins flush with the maximum domain value." + }, + "paintOrder": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [paint-order][1]; a constant string specifying the order in which the\n**fill**, **stroke**, and any markers are drawn; defaults to *normal*, which draws the fill, then stroke, then markers; defaults to *stroke* for the text mark to create a “halo” around text to improve legibility.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/paint-order" + }, + "params": { + "$ref": "#/definitions/Params", + "description": "Param and Selection definitions." + }, + "pixelSize": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The effective screen size of a raster pixel, used to determine the height and width of the raster from the frame’s dimensions; defaults to 1." + }, + "plotDefaults": { + "$ref": "#/definitions/PlotAttributes", + "description": "A default set of attributes to apply to all plot components." + }, + "pointerEvents": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [pointer-events][1] property; a constant string such as *none*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/pointer-events" + }, + "reverse": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Applies a transform to reverse the order of the mark’s index, say for reverse input order." + }, + "select": { + "$ref": "#/definitions/SelectFilter", + "description": "Applies a filter transform after data is loaded to highlight selected values only. For example, `first` and `last` select the first or last values of series only (using the *z* channel to separate series). Meanwhile, `nearestX` and `nearestY` select the point nearest to the pointer along the *x* or *y* channel dimension. Unlike Mosaic selections, a mark level *select* is internal to the mark only, and does not populate a param or selection value to be shared across clients.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "shapeRendering": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [shape-rendering][1]; a constant string such as *crispEdges*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/shape-rendering" + }, + "sort": { + "anyOf": [ + { + "$ref": "#/definitions/SortOrder" + }, + { + "$ref": "#/definitions/ChannelDomainSort" + } + ], + "description": "Either applies a transform to sort the mark’s index by the specified channel values, or imputes ordinal scale domains from this mark’s channels.\n\nWhen imputing ordinal scale domains from channel values, the **sort** option is an object whose keys are ordinal scale names such as *x* or *fx*, and whose values are channel names such as *y*, *y1*, or *y2*. For example, to impute the *y* scale’s domain from the associated *x* channel values in ascending order:\n\n```js sort: {y: \"x\"} ```\n\nFor different sort options for different scales, replace the channel name with a *value* object and per-scale options:\n\n```js sort: {y: {value: \"-x\"}} ```\n\nWhen sorting the mark’s index, the **sort** option is instead one of:\n\n- a channel value definition for sorting given values in ascending order\n- a {value, order} object for sorting given values\n- a {channel, order} object for sorting the named channel’s values" + }, + "stroke": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke" + }, + "strokeDasharray": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dasharray][1]; a constant number indicating the length in pixels of alternating dashes and gaps, or a constant string of numbers separated by spaces or commas (_e.g._, *10 2* for dashes of 10 pixels separated by gaps of 2 pixels), or *none* (the default) for no dashing\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dasharray" + }, + "strokeDashoffset": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dashoffset][1]; a constant indicating the offset in pixels of the first dash along the stroke; defaults to zero.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dashoffset" + }, + "strokeLinecap": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linecap][1]; a constant specifying how to cap stroked paths, such as *butt*, *round*, or *square*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linecap" + }, + "strokeLinejoin": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linejoin][1]; a constant specifying how to join stroked paths, such as *bevel*, *miter*, *miter-clip*, or *round*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linejoin" + }, + "strokeMiterlimit": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-miterlimit][1]; a constant number specifying how to limit the length of *miter* joins on stroked paths.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-miterlimit" + }, + "strokeOpacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-opacity" + }, + "strokeWidth": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-width][1]; a constant number in pixels, or a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-width" + }, + "target": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [target][1]; a constant string specifying the target window (_e.g._,\n*_blank*) for clickable links; used in conjunction with the **href** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/target" + }, + "tip": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/TipPointer" + }, + { + "properties": { + "anchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The tip anchor specifies how to orient the tip box relative to its anchor position; it refers to the part of the tip box that is attached to the anchor point. For example, the *top-left* anchor places the top-left corner of tip box near the anchor position, hence placing the tip box below and to the right of the anchor position." + }, + "fontFamily": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font-family][1]; a constant; defaults to the plot’s font family, which is typically [*system-ui*][2].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-family [2]: https://drafts.csswg.org/css-fonts-4/#valdef-font-family-system-ui" + }, + "fontSize": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font size][1] in pixels; either a constant or a channel; defaults to the plot’s font size, which is typically 10. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-size" + }, + "fontStyle": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font style][1]; a constant; defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-style" + }, + "fontVariant": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font variant][1]; a constant; if the **text** channel contains numbers or dates, defaults to *tabular-nums* to facilitate comparing numbers; otherwise defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant" + }, + "fontWeight": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font weight][1]; a constant; defaults to the plot’s font weight, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight" + }, + "format": { + "additionalProperties": false, + "description": "How channel values are formatted for display. If a format is a string, it is interpreted as a (UTC) time format for temporal channels, and otherwise a number format.", + "properties": { + "ariaLabel": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fill": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fillOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fontSize": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fx": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fy": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "geometry": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "height": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "href": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "length": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "opacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "path": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "r": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "rotate": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "src": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "stroke": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeWidth": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "symbol": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "text": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "title": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "weight": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "width": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "z": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + } + }, + "type": "object" + }, + "frameAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The frame anchor specifies defaults for **x** and **y** based on the plot’s frame; it may be one of the four sides (*top*, *right*, *bottom*, *left*), one of the four corners (*top-left*, *top-right*, *bottom-right*,\n*bottom-left*), or the *middle* of the frame. For example, for tips distributed horizontally at the top of the frame:\n\n```js Plot.tip(data, {x: \"date\", frameAnchor: \"top\"}) ```" + }, + "lineHeight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line height in ems; defaults to 1. The line height affects the (typically vertical) separation between adjacent baselines of text, as well as the separation between the text and its anchor point." + }, + "lineWidth": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line width in ems (e.g., 10 for about 20 characters); defaults to infinity, disabling wrapping and clipping.\n\nIf **textOverflow** is null, lines will be wrapped at the specified length. If a line is split at a soft hyphen (\\xad), a hyphen (-) will be displayed at the end of the line. If **textOverflow** is not null, lines will be clipped according to the given strategy." + }, + "monospace": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, changes the default **fontFamily** to *monospace*, and uses simplified monospaced text metrics calculations." + }, + "pathFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The image filter for the tip’s box; defaults to a drop shadow." + }, + "pointer": { + "$ref": "#/definitions/TipPointer" + }, + "pointerSize": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The size of the tip’s pointer in pixels; defaults to 12." + }, + "preferredAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If an explicit tip anchor is not specified, an anchor is chosen automatically such that the tip fits within the plot’s frame; if the preferred anchor fits, it is chosen." + }, + "textAnchor": { + "anyOf": [ + { + "const": "start", + "type": "string" + }, + { + "const": "middle", + "type": "string" + }, + { + "const": "end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [text anchor][1] controls how text is aligned (typically horizontally) relative to its anchor point; it is one of *start*, *end*, or *middle*. If the frame anchor is *left*, *top-left*, or *bottom-left*, the default text anchor is *start*; if the frame anchor is *right*, *top-right*, or\n*bottom-right*, the default is *end*; otherwise it is *middle*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/text-anchor" + }, + "textOverflow": { + "anyOf": [ + { + "type": "null" + }, + { + "const": "clip", + "type": "string" + }, + { + "const": "ellipsis", + "type": "string" + }, + { + "const": "clip-start", + "type": "string" + }, + { + "const": "clip-end", + "type": "string" + }, + { + "const": "ellipsis-start", + "type": "string" + }, + { + "const": "ellipsis-middle", + "type": "string" + }, + { + "const": "ellipsis-end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How truncate (or wrap) lines of text longer than the given **lineWidth**; one of:\n\n- null (default) - preserve overflowing characters (and wrap if needed)\n- *clip* or *clip-end* - remove characters from the end\n- *clip-start* - remove characters from the start\n- *ellipsis* or *ellipsis-end* - replace characters from the end with an ellipsis (…)\n- *ellipsis-start* - replace characters from the start with an ellipsis (…)\n- *ellipsis-middle* - replace characters from the middle with an ellipsis (…)\n\nIf no **title** was specified, if text requires truncation, a title containing the non-truncated text will be implicitly added." + }, + "textPadding": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The padding around the text in pixels; defaults to 8." + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + } + }, + "type": "object" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to generate a tooltip for this mark, and any tip options." + }, + "title": { + "$ref": "#/definitions/ChannelValue", + "description": "The title; a channel specifying accessible, short textual descriptions as strings (possibly with newlines). If the tip option is specified, the title will be displayed with an interactive tooltip instead of using the SVG [title element][1].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/title" + }, + "width": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The width (number of columns) of the grid, in actual pixels." + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel, typically bound to the *x* scale. Domain values are binned into a grid with *width* horizontal bins." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel, typically bound to the *y* scale. Domain values are binned into a grid with *height* vertical bins." + } + }, + "required": [ + "data", + "mark" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "$schema": { + "description": "A [JSON schema](http://json-schema.org/) URL for this specification, such as https://uwdata.github.io/mosaic/schema/latest.json. This property enables validation and autocomplete in editors with JSON schema support.", + "format": "uri", + "type": "string" + }, + "ariaDescription": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-description][1]; a constant textual description.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-description" + }, + "ariaHidden": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-hidden][1] state; a constant indicating whether the element is exposed to an accessibility API.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-hidden" + }, + "ariaLabel": { + "$ref": "#/definitions/ChannelValue", + "description": "The [aria-label][1]; a channel specifying short textual labels representing the value in the accessibility tree.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-label" + }, + "bandwidth": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The kernel density bandwidth for smoothing, in pixels." + }, + "clip": { + "anyOf": [ + { + "const": "frame", + "type": "string" + }, + { + "const": "sphere", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to clip the mark; one of:\n\n- *frame* or true - clip to the plot’s frame (inner area)\n- *sphere* - clip to the projected sphere (*e.g.*, front hemisphere)\n- null or false - do not clip\n\nThe *sphere* clip option requires a geographic projection." + }, + "config": { + "$ref": "#/definitions/Config", + "description": "Configuration options." + }, + "data": { + "$ref": "#/definitions/Data", + "description": "Dataset definitions." + }, + "dx": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The horizontal offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "dy": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The vertical offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "facet": { + "anyOf": [ + { + "const": "auto", + "type": "string" + }, + { + "const": "include", + "type": "string" + }, + { + "const": "exclude", + "type": "string" + }, + { + "const": "super", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to enable or disable faceting; one of:\n\n- *auto* (default) - automatically determine if this mark should be faceted\n- *include* (or true) - draw the subset of the mark’s data in the current facet\n- *exclude* - draw the subset of the mark’s data *not* in the current facet\n- *super* - draw this mark in a single frame that covers all facets\n- null (or false) - repeat this mark’s data across all facets (*i.e.*, no faceting)\n\nWhen a mark uses *super* faceting, it is not allowed to use position scales (*x*, *y*, *fx*, or *fy*); *super* faceting is intended for decorations, such as labels and legends.\n\nWhen top-level faceting is used, the default *auto* setting is equivalent to *include* when the mark data is strictly equal to the top-level facet data; otherwise it is equivalent to null. When the *include* or *exclude* facet mode is chosen, the mark data must be parallel to the top-level facet data: the data must have the same length and order. If the data are not parallel, then the wrong data may be shown in each facet. The default\n*auto* therefore requires strict equality (`===`) for safety, and using the facet data as mark data is recommended when using the *exclude* facet mode. (To construct parallel data safely, consider using [*array*.map][1] on the facet data.)\n\nWhen mark-level faceting is used, the default *auto* setting is equivalent to *include*: the mark will be faceted if either the **fx** or **fy** channel option (or both) is specified. The null or false option will disable faceting, while *exclude* draws the subset of the mark’s data *not* in the current facet.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map" + }, + "facetAnchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "right", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "const": "left", + "type": "string" + }, + { + "const": "top-left", + "type": "string" + }, + { + "const": "top-right", + "type": "string" + }, + { + "const": "bottom-left", + "type": "string" + }, + { + "const": "bottom-right", + "type": "string" + }, + { + "const": "top-empty", + "type": "string" + }, + { + "const": "right-empty", + "type": "string" + }, + { + "const": "bottom-empty", + "type": "string" + }, + { + "const": "left-empty", + "type": "string" + }, + { + "const": "empty", + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to place the mark with respect to facets; one of:\n\n- null (default for most marks) - display the mark in each non-empty facet\n- *top*, *right*, *bottom*, or *left* - display the mark only in facets on the given side\n- *top-empty*, *right-empty*, *bottom-empty*, or *left-empty* (default for axis marks) - display the mark only in facets that have empty space on the given side: either the margin, or an empty facet\n- *empty* - display the mark in empty facets only" + }, + "fill": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The fill, typically bound to the *color* scale. Can be specified as a constant or a channel based on the input data. Use the special value `\"density\"` to map computed density values to pixel colors. Use an aggregate expression to instead visualize an aggregate value per raster bin. If fill is set to a constant color or to a non-aggregate field, opacity will be used to convey densities. If a non-aggregate (group by) field is provided, multiple rasters are created with a unique categorical color per layer." + }, + "fillOpacity": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The opacity, typically bound to the *opacity* scale. Can be specified as a constant or a channel based on the input data. Use the special value `\"density\"` to map computed density values to opacity. Use an aggregate expression to instead visualize an aggregate value per raster bin." + }, + "filter": { + "$ref": "#/definitions/ChannelValue", + "description": "Applies a transform to filter the mark’s index according to the given channel values; only truthy values are retained.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "fx": { + "$ref": "#/definitions/ChannelValue", + "description": "The horizontal facet position channel, for mark-level faceting, bound to the *fx* scale." + }, + "fy": { + "$ref": "#/definitions/ChannelValue", + "description": "The vertical facet position channel, for mark-level faceting, bound to the\n*fy* scale." + }, + "height": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The height (number of rows) of the grid, in actual pixels." + }, + "href": { + "$ref": "#/definitions/ChannelValue", + "description": "The [href][1]; a channel specifying URLs for clickable links. May be used in conjunction with the **target** option to open links in another window.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/href" + }, + "imageFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A CSS [filter][1]; a constant string used to adjust the rendering of images, such as *blur(5px)*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/filter" + }, + "imageRendering": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [image-rendering attribute][1]; defaults to *auto* (bilinear). The option may be set to *pixelated* to disable bilinear interpolation for a sharper image; however, note that this is not supported in WebKit.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/image-rendering" + }, + "interpolate": { + "anyOf": [ + { + "$ref": "#/definitions/GridInterpolate" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The spatial interpolation method; one of:\n\n- *none* - do not perform interpolation (the default), maps samples to single bins\n- *linear* - apply proportional linear interpolation across adjacent bins\n- *nearest* - assign each pixel to the closest sample’s value (Voronoi diagram)\n- *barycentric* - apply barycentric interpolation over the Delaunay triangulation\n- *random-walk* - apply a random walk from each pixel, stopping when near a sample" + }, + "margin": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four mark margins: **marginTop**,\n**marginRight**, **marginBottom**, and **marginLeft**; typically defaults to 0, except for axis marks." + }, + "marginBottom": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s bottom margin; the minimum distance in pixels between the bottom edges of the inner and outer plot area." + }, + "marginLeft": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s left margin; the minimum distance in pixels between the left edges of the inner and outer plot area." + }, + "marginRight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s right margin; the minimum distance in pixels between the right edges of the mark’s inner and outer plot area." + }, + "marginTop": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s top margin; the minimum distance in pixels between the top edges of the inner and outer plot area." + }, + "mark": { + "const": "heatmap", + "description": "Like raster, but with default options for accurate density estimation via smoothing. The *bandwidth* (20), *interpolate* (\"linear\"), and\n*pixelSize* (2) options are set to produce smoothed density heatmaps.", + "type": "string" + }, + "meta": { + "$ref": "#/definitions/Meta", + "description": "Specification metadata." + }, + "mixBlendMode": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [mix-blend-mode][1]; a constant string specifying how to blend content such as *multiply*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode" + }, + "opacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally. For faster rendering, prefer the **strokeOpacity** or **fillOpacity** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/opacity" + }, + "pad": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The bin padding, one of 1 (default) to include extra padding for the final bin, or 0 to make the bins flush with the maximum domain value." + }, + "paintOrder": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [paint-order][1]; a constant string specifying the order in which the\n**fill**, **stroke**, and any markers are drawn; defaults to *normal*, which draws the fill, then stroke, then markers; defaults to *stroke* for the text mark to create a “halo” around text to improve legibility.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/paint-order" + }, + "params": { + "$ref": "#/definitions/Params", + "description": "Param and Selection definitions." + }, + "pixelSize": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The effective screen size of a raster pixel, used to determine the height and width of the raster from the frame’s dimensions; defaults to 1." + }, + "plotDefaults": { + "$ref": "#/definitions/PlotAttributes", + "description": "A default set of attributes to apply to all plot components." + }, + "pointerEvents": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [pointer-events][1] property; a constant string such as *none*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/pointer-events" + }, + "reverse": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Applies a transform to reverse the order of the mark’s index, say for reverse input order." + }, + "select": { + "$ref": "#/definitions/SelectFilter", + "description": "Applies a filter transform after data is loaded to highlight selected values only. For example, `first` and `last` select the first or last values of series only (using the *z* channel to separate series). Meanwhile, `nearestX` and `nearestY` select the point nearest to the pointer along the *x* or *y* channel dimension. Unlike Mosaic selections, a mark level *select* is internal to the mark only, and does not populate a param or selection value to be shared across clients.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "shapeRendering": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [shape-rendering][1]; a constant string such as *crispEdges*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/shape-rendering" + }, + "sort": { + "anyOf": [ + { + "$ref": "#/definitions/SortOrder" + }, + { + "$ref": "#/definitions/ChannelDomainSort" + } + ], + "description": "Either applies a transform to sort the mark’s index by the specified channel values, or imputes ordinal scale domains from this mark’s channels.\n\nWhen imputing ordinal scale domains from channel values, the **sort** option is an object whose keys are ordinal scale names such as *x* or *fx*, and whose values are channel names such as *y*, *y1*, or *y2*. For example, to impute the *y* scale’s domain from the associated *x* channel values in ascending order:\n\n```js sort: {y: \"x\"} ```\n\nFor different sort options for different scales, replace the channel name with a *value* object and per-scale options:\n\n```js sort: {y: {value: \"-x\"}} ```\n\nWhen sorting the mark’s index, the **sort** option is instead one of:\n\n- a channel value definition for sorting given values in ascending order\n- a {value, order} object for sorting given values\n- a {channel, order} object for sorting the named channel’s values" + }, + "stroke": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke" + }, + "strokeDasharray": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dasharray][1]; a constant number indicating the length in pixels of alternating dashes and gaps, or a constant string of numbers separated by spaces or commas (_e.g._, *10 2* for dashes of 10 pixels separated by gaps of 2 pixels), or *none* (the default) for no dashing\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dasharray" + }, + "strokeDashoffset": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dashoffset][1]; a constant indicating the offset in pixels of the first dash along the stroke; defaults to zero.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dashoffset" + }, + "strokeLinecap": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linecap][1]; a constant specifying how to cap stroked paths, such as *butt*, *round*, or *square*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linecap" + }, + "strokeLinejoin": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linejoin][1]; a constant specifying how to join stroked paths, such as *bevel*, *miter*, *miter-clip*, or *round*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linejoin" + }, + "strokeMiterlimit": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-miterlimit][1]; a constant number specifying how to limit the length of *miter* joins on stroked paths.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-miterlimit" + }, + "strokeOpacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-opacity" + }, + "strokeWidth": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-width][1]; a constant number in pixels, or a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-width" + }, + "target": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [target][1]; a constant string specifying the target window (_e.g._,\n*_blank*) for clickable links; used in conjunction with the **href** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/target" + }, + "tip": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/TipPointer" + }, + { + "properties": { + "anchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The tip anchor specifies how to orient the tip box relative to its anchor position; it refers to the part of the tip box that is attached to the anchor point. For example, the *top-left* anchor places the top-left corner of tip box near the anchor position, hence placing the tip box below and to the right of the anchor position." + }, + "fontFamily": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font-family][1]; a constant; defaults to the plot’s font family, which is typically [*system-ui*][2].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-family [2]: https://drafts.csswg.org/css-fonts-4/#valdef-font-family-system-ui" + }, + "fontSize": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font size][1] in pixels; either a constant or a channel; defaults to the plot’s font size, which is typically 10. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-size" + }, + "fontStyle": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font style][1]; a constant; defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-style" + }, + "fontVariant": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font variant][1]; a constant; if the **text** channel contains numbers or dates, defaults to *tabular-nums* to facilitate comparing numbers; otherwise defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant" + }, + "fontWeight": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font weight][1]; a constant; defaults to the plot’s font weight, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight" + }, + "format": { + "additionalProperties": false, + "description": "How channel values are formatted for display. If a format is a string, it is interpreted as a (UTC) time format for temporal channels, and otherwise a number format.", + "properties": { + "ariaLabel": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fill": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fillOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fontSize": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fx": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fy": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "geometry": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "height": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "href": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "length": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "opacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "path": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "r": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "rotate": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "src": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "stroke": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeWidth": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "symbol": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "text": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "title": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "weight": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "width": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "z": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + } + }, + "type": "object" + }, + "frameAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The frame anchor specifies defaults for **x** and **y** based on the plot’s frame; it may be one of the four sides (*top*, *right*, *bottom*, *left*), one of the four corners (*top-left*, *top-right*, *bottom-right*,\n*bottom-left*), or the *middle* of the frame. For example, for tips distributed horizontally at the top of the frame:\n\n```js Plot.tip(data, {x: \"date\", frameAnchor: \"top\"}) ```" + }, + "lineHeight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line height in ems; defaults to 1. The line height affects the (typically vertical) separation between adjacent baselines of text, as well as the separation between the text and its anchor point." + }, + "lineWidth": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line width in ems (e.g., 10 for about 20 characters); defaults to infinity, disabling wrapping and clipping.\n\nIf **textOverflow** is null, lines will be wrapped at the specified length. If a line is split at a soft hyphen (\\xad), a hyphen (-) will be displayed at the end of the line. If **textOverflow** is not null, lines will be clipped according to the given strategy." + }, + "monospace": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, changes the default **fontFamily** to *monospace*, and uses simplified monospaced text metrics calculations." + }, + "pathFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The image filter for the tip’s box; defaults to a drop shadow." + }, + "pointer": { + "$ref": "#/definitions/TipPointer" + }, + "pointerSize": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The size of the tip’s pointer in pixels; defaults to 12." + }, + "preferredAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If an explicit tip anchor is not specified, an anchor is chosen automatically such that the tip fits within the plot’s frame; if the preferred anchor fits, it is chosen." + }, + "textAnchor": { + "anyOf": [ + { + "const": "start", + "type": "string" + }, + { + "const": "middle", + "type": "string" + }, + { + "const": "end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [text anchor][1] controls how text is aligned (typically horizontally) relative to its anchor point; it is one of *start*, *end*, or *middle*. If the frame anchor is *left*, *top-left*, or *bottom-left*, the default text anchor is *start*; if the frame anchor is *right*, *top-right*, or\n*bottom-right*, the default is *end*; otherwise it is *middle*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/text-anchor" + }, + "textOverflow": { + "anyOf": [ + { + "type": "null" + }, + { + "const": "clip", + "type": "string" + }, + { + "const": "ellipsis", + "type": "string" + }, + { + "const": "clip-start", + "type": "string" + }, + { + "const": "clip-end", + "type": "string" + }, + { + "const": "ellipsis-start", + "type": "string" + }, + { + "const": "ellipsis-middle", + "type": "string" + }, + { + "const": "ellipsis-end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How truncate (or wrap) lines of text longer than the given **lineWidth**; one of:\n\n- null (default) - preserve overflowing characters (and wrap if needed)\n- *clip* or *clip-end* - remove characters from the end\n- *clip-start* - remove characters from the start\n- *ellipsis* or *ellipsis-end* - replace characters from the end with an ellipsis (…)\n- *ellipsis-start* - replace characters from the start with an ellipsis (…)\n- *ellipsis-middle* - replace characters from the middle with an ellipsis (…)\n\nIf no **title** was specified, if text requires truncation, a title containing the non-truncated text will be implicitly added." + }, + "textPadding": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The padding around the text in pixels; defaults to 8." + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + } + }, + "type": "object" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to generate a tooltip for this mark, and any tip options." + }, + "title": { + "$ref": "#/definitions/ChannelValue", + "description": "The title; a channel specifying accessible, short textual descriptions as strings (possibly with newlines). If the tip option is specified, the title will be displayed with an interactive tooltip instead of using the SVG [title element][1].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/title" + }, + "width": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The width (number of columns) of the grid, in actual pixels." + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel, typically bound to the *x* scale. Domain values are binned into a grid with *width* horizontal bins." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel, typically bound to the *y* scale. Domain values are binned into a grid with *height* vertical bins." + } + }, + "required": [ + "data", + "mark" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "$schema": { + "description": "A [JSON schema](http://json-schema.org/) URL for this specification, such as https://uwdata.github.io/mosaic/schema/latest.json. This property enables validation and autocomplete in editors with JSON schema support.", + "format": "uri", + "type": "string" + }, + "ariaDescription": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-description][1]; a constant textual description.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-description" + }, + "ariaHidden": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-hidden][1] state; a constant indicating whether the element is exposed to an accessibility API.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-hidden" + }, + "ariaLabel": { + "$ref": "#/definitions/ChannelValue", + "description": "The [aria-label][1]; a channel specifying short textual labels representing the value in the accessibility tree.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-label" + }, + "bandwidth": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The kernel density bandwidth for smoothing, in pixels." + }, + "clip": { + "anyOf": [ + { + "const": "frame", + "type": "string" + }, + { + "const": "sphere", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to clip the mark; one of:\n\n- *frame* or true - clip to the plot’s frame (inner area)\n- *sphere* - clip to the projected sphere (*e.g.*, front hemisphere)\n- null or false - do not clip\n\nThe *sphere* clip option requires a geographic projection." + }, + "config": { + "$ref": "#/definitions/Config", + "description": "Configuration options." + }, + "data": { + "$ref": "#/definitions/Data", + "description": "Dataset definitions." + }, + "dx": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The horizontal offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "dy": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The vertical offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "facet": { + "anyOf": [ + { + "const": "auto", + "type": "string" + }, + { + "const": "include", + "type": "string" + }, + { + "const": "exclude", + "type": "string" + }, + { + "const": "super", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to enable or disable faceting; one of:\n\n- *auto* (default) - automatically determine if this mark should be faceted\n- *include* (or true) - draw the subset of the mark’s data in the current facet\n- *exclude* - draw the subset of the mark’s data *not* in the current facet\n- *super* - draw this mark in a single frame that covers all facets\n- null (or false) - repeat this mark’s data across all facets (*i.e.*, no faceting)\n\nWhen a mark uses *super* faceting, it is not allowed to use position scales (*x*, *y*, *fx*, or *fy*); *super* faceting is intended for decorations, such as labels and legends.\n\nWhen top-level faceting is used, the default *auto* setting is equivalent to *include* when the mark data is strictly equal to the top-level facet data; otherwise it is equivalent to null. When the *include* or *exclude* facet mode is chosen, the mark data must be parallel to the top-level facet data: the data must have the same length and order. If the data are not parallel, then the wrong data may be shown in each facet. The default\n*auto* therefore requires strict equality (`===`) for safety, and using the facet data as mark data is recommended when using the *exclude* facet mode. (To construct parallel data safely, consider using [*array*.map][1] on the facet data.)\n\nWhen mark-level faceting is used, the default *auto* setting is equivalent to *include*: the mark will be faceted if either the **fx** or **fy** channel option (or both) is specified. The null or false option will disable faceting, while *exclude* draws the subset of the mark’s data *not* in the current facet.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map" + }, + "facetAnchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "right", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "const": "left", + "type": "string" + }, + { + "const": "top-left", + "type": "string" + }, + { + "const": "top-right", + "type": "string" + }, + { + "const": "bottom-left", + "type": "string" + }, + { + "const": "bottom-right", + "type": "string" + }, + { + "const": "top-empty", + "type": "string" + }, + { + "const": "right-empty", + "type": "string" + }, + { + "const": "bottom-empty", + "type": "string" + }, + { + "const": "left-empty", + "type": "string" + }, + { + "const": "empty", + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to place the mark with respect to facets; one of:\n\n- null (default for most marks) - display the mark in each non-empty facet\n- *top*, *right*, *bottom*, or *left* - display the mark only in facets on the given side\n- *top-empty*, *right-empty*, *bottom-empty*, or *left-empty* (default for axis marks) - display the mark only in facets that have empty space on the given side: either the margin, or an empty facet\n- *empty* - display the mark in empty facets only" + }, + "fill": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The fill, typically bound to the *color* scale. Can be specified as a constant or a channel based on the input data. Use the special value `\"density\"` to map computed density values to pixel colors. Use an aggregate expression to instead visualize an aggregate value per raster bin. If fill is set to a constant color or to a non-aggregate field, opacity will be used to convey densities. If a non-aggregate (group by) field is provided, multiple rasters are created with a unique categorical color per layer." + }, + "fillOpacity": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The opacity, typically bound to the *opacity* scale. Can be specified as a constant or a channel based on the input data. Use the special value `\"density\"` to map computed density values to opacity. Use an aggregate expression to instead visualize an aggregate value per raster bin." + }, + "filter": { + "$ref": "#/definitions/ChannelValue", + "description": "Applies a transform to filter the mark’s index according to the given channel values; only truthy values are retained.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "fx": { + "$ref": "#/definitions/ChannelValue", + "description": "The horizontal facet position channel, for mark-level faceting, bound to the *fx* scale." + }, + "fy": { + "$ref": "#/definitions/ChannelValue", + "description": "The vertical facet position channel, for mark-level faceting, bound to the\n*fy* scale." + }, + "height": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The height (number of rows) of the grid, in actual pixels." + }, + "href": { + "$ref": "#/definitions/ChannelValue", + "description": "The [href][1]; a channel specifying URLs for clickable links. May be used in conjunction with the **target** option to open links in another window.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/href" + }, + "imageFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A CSS [filter][1]; a constant string used to adjust the rendering of images, such as *blur(5px)*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/filter" + }, + "imageRendering": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [image-rendering attribute][1]; defaults to *auto* (bilinear). The option may be set to *pixelated* to disable bilinear interpolation for a sharper image; however, note that this is not supported in WebKit.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/image-rendering" + }, + "interpolate": { + "anyOf": [ + { + "$ref": "#/definitions/GridInterpolate" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The spatial interpolation method; one of:\n\n- *none* - do not perform interpolation (the default), maps samples to single bins\n- *linear* - apply proportional linear interpolation across adjacent bins\n- *nearest* - assign each pixel to the closest sample’s value (Voronoi diagram)\n- *barycentric* - apply barycentric interpolation over the Delaunay triangulation\n- *random-walk* - apply a random walk from each pixel, stopping when near a sample" + }, + "margin": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four mark margins: **marginTop**,\n**marginRight**, **marginBottom**, and **marginLeft**; typically defaults to 0, except for axis marks." + }, + "marginBottom": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s bottom margin; the minimum distance in pixels between the bottom edges of the inner and outer plot area." + }, + "marginLeft": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s left margin; the minimum distance in pixels between the left edges of the inner and outer plot area." + }, + "marginRight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s right margin; the minimum distance in pixels between the right edges of the mark’s inner and outer plot area." + }, + "marginTop": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s top margin; the minimum distance in pixels between the top edges of the inner and outer plot area." + }, + "mark": { + "const": "rasterTile", + "description": "An experimental raster mark which performs tiling and prefetching to support more scalable rasters upon panning the domain. Uses a tile size that matches with current width and height, and prefetches data from neighboring tile segments.", + "type": "string" + }, + "meta": { + "$ref": "#/definitions/Meta", + "description": "Specification metadata." + }, + "mixBlendMode": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [mix-blend-mode][1]; a constant string specifying how to blend content such as *multiply*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode" + }, + "opacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally. For faster rendering, prefer the **strokeOpacity** or **fillOpacity** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/opacity" + }, + "origin": { + "anyOf": [ + { + "items": { + "type": "number" + }, + "maxItems": 2, + "minItems": 2, + "type": "array" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The coordinates of the tile origin in the **x** and **y** data domains. Defaults to [0, 0]." + }, + "pad": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The bin padding, one of 1 (default) to include extra padding for the final bin, or 0 to make the bins flush with the maximum domain value." + }, + "paintOrder": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [paint-order][1]; a constant string specifying the order in which the\n**fill**, **stroke**, and any markers are drawn; defaults to *normal*, which draws the fill, then stroke, then markers; defaults to *stroke* for the text mark to create a “halo” around text to improve legibility.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/paint-order" + }, + "params": { + "$ref": "#/definitions/Params", + "description": "Param and Selection definitions." + }, + "pixelSize": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The effective screen size of a raster pixel, used to determine the height and width of the raster from the frame’s dimensions; defaults to 1." + }, + "plotDefaults": { + "$ref": "#/definitions/PlotAttributes", + "description": "A default set of attributes to apply to all plot components." + }, + "pointerEvents": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [pointer-events][1] property; a constant string such as *none*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/pointer-events" + }, + "reverse": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Applies a transform to reverse the order of the mark’s index, say for reverse input order." + }, + "select": { + "$ref": "#/definitions/SelectFilter", + "description": "Applies a filter transform after data is loaded to highlight selected values only. For example, `first` and `last` select the first or last values of series only (using the *z* channel to separate series). Meanwhile, `nearestX` and `nearestY` select the point nearest to the pointer along the *x* or *y* channel dimension. Unlike Mosaic selections, a mark level *select* is internal to the mark only, and does not populate a param or selection value to be shared across clients.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "shapeRendering": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [shape-rendering][1]; a constant string such as *crispEdges*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/shape-rendering" + }, + "sort": { + "anyOf": [ + { + "$ref": "#/definitions/SortOrder" + }, + { + "$ref": "#/definitions/ChannelDomainSort" + } + ], + "description": "Either applies a transform to sort the mark’s index by the specified channel values, or imputes ordinal scale domains from this mark’s channels.\n\nWhen imputing ordinal scale domains from channel values, the **sort** option is an object whose keys are ordinal scale names such as *x* or *fx*, and whose values are channel names such as *y*, *y1*, or *y2*. For example, to impute the *y* scale’s domain from the associated *x* channel values in ascending order:\n\n```js sort: {y: \"x\"} ```\n\nFor different sort options for different scales, replace the channel name with a *value* object and per-scale options:\n\n```js sort: {y: {value: \"-x\"}} ```\n\nWhen sorting the mark’s index, the **sort** option is instead one of:\n\n- a channel value definition for sorting given values in ascending order\n- a {value, order} object for sorting given values\n- a {channel, order} object for sorting the named channel’s values" + }, + "stroke": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke" + }, + "strokeDasharray": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dasharray][1]; a constant number indicating the length in pixels of alternating dashes and gaps, or a constant string of numbers separated by spaces or commas (_e.g._, *10 2* for dashes of 10 pixels separated by gaps of 2 pixels), or *none* (the default) for no dashing\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dasharray" + }, + "strokeDashoffset": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dashoffset][1]; a constant indicating the offset in pixels of the first dash along the stroke; defaults to zero.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dashoffset" + }, + "strokeLinecap": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linecap][1]; a constant specifying how to cap stroked paths, such as *butt*, *round*, or *square*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linecap" + }, + "strokeLinejoin": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linejoin][1]; a constant specifying how to join stroked paths, such as *bevel*, *miter*, *miter-clip*, or *round*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linejoin" + }, + "strokeMiterlimit": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-miterlimit][1]; a constant number specifying how to limit the length of *miter* joins on stroked paths.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-miterlimit" + }, + "strokeOpacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-opacity" + }, + "strokeWidth": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-width][1]; a constant number in pixels, or a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-width" + }, + "target": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [target][1]; a constant string specifying the target window (_e.g._,\n*_blank*) for clickable links; used in conjunction with the **href** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/target" + }, + "tip": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/TipPointer" + }, + { + "properties": { + "anchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The tip anchor specifies how to orient the tip box relative to its anchor position; it refers to the part of the tip box that is attached to the anchor point. For example, the *top-left* anchor places the top-left corner of tip box near the anchor position, hence placing the tip box below and to the right of the anchor position." + }, + "fontFamily": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font-family][1]; a constant; defaults to the plot’s font family, which is typically [*system-ui*][2].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-family [2]: https://drafts.csswg.org/css-fonts-4/#valdef-font-family-system-ui" + }, + "fontSize": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font size][1] in pixels; either a constant or a channel; defaults to the plot’s font size, which is typically 10. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-size" + }, + "fontStyle": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font style][1]; a constant; defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-style" + }, + "fontVariant": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font variant][1]; a constant; if the **text** channel contains numbers or dates, defaults to *tabular-nums* to facilitate comparing numbers; otherwise defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant" + }, + "fontWeight": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font weight][1]; a constant; defaults to the plot’s font weight, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight" + }, + "format": { + "additionalProperties": false, + "description": "How channel values are formatted for display. If a format is a string, it is interpreted as a (UTC) time format for temporal channels, and otherwise a number format.", + "properties": { + "ariaLabel": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fill": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fillOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fontSize": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fx": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fy": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "geometry": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "height": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "href": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "length": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "opacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "path": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "r": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "rotate": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "src": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "stroke": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeWidth": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "symbol": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "text": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "title": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "weight": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "width": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "z": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + } + }, + "type": "object" + }, + "frameAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The frame anchor specifies defaults for **x** and **y** based on the plot’s frame; it may be one of the four sides (*top*, *right*, *bottom*, *left*), one of the four corners (*top-left*, *top-right*, *bottom-right*,\n*bottom-left*), or the *middle* of the frame. For example, for tips distributed horizontally at the top of the frame:\n\n```js Plot.tip(data, {x: \"date\", frameAnchor: \"top\"}) ```" + }, + "lineHeight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line height in ems; defaults to 1. The line height affects the (typically vertical) separation between adjacent baselines of text, as well as the separation between the text and its anchor point." + }, + "lineWidth": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line width in ems (e.g., 10 for about 20 characters); defaults to infinity, disabling wrapping and clipping.\n\nIf **textOverflow** is null, lines will be wrapped at the specified length. If a line is split at a soft hyphen (\\xad), a hyphen (-) will be displayed at the end of the line. If **textOverflow** is not null, lines will be clipped according to the given strategy." + }, + "monospace": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, changes the default **fontFamily** to *monospace*, and uses simplified monospaced text metrics calculations." + }, + "pathFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The image filter for the tip’s box; defaults to a drop shadow." + }, + "pointer": { + "$ref": "#/definitions/TipPointer" + }, + "pointerSize": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The size of the tip’s pointer in pixels; defaults to 12." + }, + "preferredAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If an explicit tip anchor is not specified, an anchor is chosen automatically such that the tip fits within the plot’s frame; if the preferred anchor fits, it is chosen." + }, + "textAnchor": { + "anyOf": [ + { + "const": "start", + "type": "string" + }, + { + "const": "middle", + "type": "string" + }, + { + "const": "end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [text anchor][1] controls how text is aligned (typically horizontally) relative to its anchor point; it is one of *start*, *end*, or *middle*. If the frame anchor is *left*, *top-left*, or *bottom-left*, the default text anchor is *start*; if the frame anchor is *right*, *top-right*, or\n*bottom-right*, the default is *end*; otherwise it is *middle*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/text-anchor" + }, + "textOverflow": { + "anyOf": [ + { + "type": "null" + }, + { + "const": "clip", + "type": "string" + }, + { + "const": "ellipsis", + "type": "string" + }, + { + "const": "clip-start", + "type": "string" + }, + { + "const": "clip-end", + "type": "string" + }, + { + "const": "ellipsis-start", + "type": "string" + }, + { + "const": "ellipsis-middle", + "type": "string" + }, + { + "const": "ellipsis-end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How truncate (or wrap) lines of text longer than the given **lineWidth**; one of:\n\n- null (default) - preserve overflowing characters (and wrap if needed)\n- *clip* or *clip-end* - remove characters from the end\n- *clip-start* - remove characters from the start\n- *ellipsis* or *ellipsis-end* - replace characters from the end with an ellipsis (…)\n- *ellipsis-start* - replace characters from the start with an ellipsis (…)\n- *ellipsis-middle* - replace characters from the middle with an ellipsis (…)\n\nIf no **title** was specified, if text requires truncation, a title containing the non-truncated text will be implicitly added." + }, + "textPadding": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The padding around the text in pixels; defaults to 8." + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + } + }, + "type": "object" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to generate a tooltip for this mark, and any tip options." + }, + "title": { + "$ref": "#/definitions/ChannelValue", + "description": "The title; a channel specifying accessible, short textual descriptions as strings (possibly with newlines). If the tip option is specified, the title will be displayed with an interactive tooltip instead of using the SVG [title element][1].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/title" + }, + "width": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The width (number of columns) of the grid, in actual pixels." + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel, typically bound to the *x* scale. Domain values are binned into a grid with *width* horizontal bins." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel, typically bound to the *y* scale. Domain values are binned into a grid with *height* vertical bins." + } + }, + "required": [ + "data", + "mark" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "$schema": { + "description": "A [JSON schema](http://json-schema.org/) URL for this specification, such as https://uwdata.github.io/mosaic/schema/latest.json. This property enables validation and autocomplete in editors with JSON schema support.", + "format": "uri", + "type": "string" + }, + "ariaDescription": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-description][1]; a constant textual description.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-description" + }, + "ariaHidden": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-hidden][1] state; a constant indicating whether the element is exposed to an accessibility API.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-hidden" + }, + "ariaLabel": { + "$ref": "#/definitions/ChannelValue", + "description": "The [aria-label][1]; a channel specifying short textual labels representing the value in the accessibility tree.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-label" + }, + "clip": { + "anyOf": [ + { + "const": "frame", + "type": "string" + }, + { + "const": "sphere", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to clip the mark; one of:\n\n- *frame* or true - clip to the plot’s frame (inner area)\n- *sphere* - clip to the projected sphere (*e.g.*, front hemisphere)\n- null or false - do not clip\n\nThe *sphere* clip option requires a geographic projection." + }, + "config": { + "$ref": "#/definitions/Config", + "description": "Configuration options." + }, + "data": { + "$ref": "#/definitions/Data", + "description": "Dataset definitions." + }, + "dx": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The horizontal offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "dy": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The vertical offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "facet": { + "anyOf": [ + { + "const": "auto", + "type": "string" + }, + { + "const": "include", + "type": "string" + }, + { + "const": "exclude", + "type": "string" + }, + { + "const": "super", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to enable or disable faceting; one of:\n\n- *auto* (default) - automatically determine if this mark should be faceted\n- *include* (or true) - draw the subset of the mark’s data in the current facet\n- *exclude* - draw the subset of the mark’s data *not* in the current facet\n- *super* - draw this mark in a single frame that covers all facets\n- null (or false) - repeat this mark’s data across all facets (*i.e.*, no faceting)\n\nWhen a mark uses *super* faceting, it is not allowed to use position scales (*x*, *y*, *fx*, or *fy*); *super* faceting is intended for decorations, such as labels and legends.\n\nWhen top-level faceting is used, the default *auto* setting is equivalent to *include* when the mark data is strictly equal to the top-level facet data; otherwise it is equivalent to null. When the *include* or *exclude* facet mode is chosen, the mark data must be parallel to the top-level facet data: the data must have the same length and order. If the data are not parallel, then the wrong data may be shown in each facet. The default\n*auto* therefore requires strict equality (`===`) for safety, and using the facet data as mark data is recommended when using the *exclude* facet mode. (To construct parallel data safely, consider using [*array*.map][1] on the facet data.)\n\nWhen mark-level faceting is used, the default *auto* setting is equivalent to *include*: the mark will be faceted if either the **fx** or **fy** channel option (or both) is specified. The null or false option will disable faceting, while *exclude* draws the subset of the mark’s data *not* in the current facet.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map" + }, + "facetAnchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "right", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "const": "left", + "type": "string" + }, + { + "const": "top-left", + "type": "string" + }, + { + "const": "top-right", + "type": "string" + }, + { + "const": "bottom-left", + "type": "string" + }, + { + "const": "bottom-right", + "type": "string" + }, + { + "const": "top-empty", + "type": "string" + }, + { + "const": "right-empty", + "type": "string" + }, + { + "const": "bottom-empty", + "type": "string" + }, + { + "const": "left-empty", + "type": "string" + }, + { + "const": "empty", + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to place the mark with respect to facets; one of:\n\n- null (default for most marks) - display the mark in each non-empty facet\n- *top*, *right*, *bottom*, or *left* - display the mark only in facets on the given side\n- *top-empty*, *right-empty*, *bottom-empty*, or *left-empty* (default for axis marks) - display the mark only in facets that have empty space on the given side: either the margin, or an empty facet\n- *empty* - display the mark in empty facets only" + }, + "fill": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill" + }, + "fillOpacity": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill-opacity][1]; a constant number between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill-opacity" + }, + "filter": { + "$ref": "#/definitions/ChannelValue", + "description": "Applies a transform to filter the mark’s index according to the given channel values; only truthy values are retained.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "fx": { + "$ref": "#/definitions/ChannelValue", + "description": "The horizontal facet position channel, for mark-level faceting, bound to the *fx* scale." + }, + "fy": { + "$ref": "#/definitions/ChannelValue", + "description": "The vertical facet position channel, for mark-level faceting, bound to the\n*fy* scale." + }, + "href": { + "$ref": "#/definitions/ChannelValue", + "description": "The [href][1]; a channel specifying URLs for clickable links. May be used in conjunction with the **target** option to open links in another window.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/href" + }, + "imageFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A CSS [filter][1]; a constant string used to adjust the rendering of images, such as *blur(5px)*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/filter" + }, + "inset": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four insets: **insetTop**,\n**insetRight**, **insetBottom**, and **insetLeft**. All insets typically default to zero, though not always (say when using bin transform). A positive inset reduces effective area, while a negative inset increases it." + }, + "insetBottom": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Insets the bottom edge by the specified number of pixels. A positive value insets towards the top edge (reducing effective area), while a negative value insets away from the top edge (increasing it)." + }, + "insetLeft": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Insets the left edge by the specified number of pixels. A positive value insets towards the right edge (reducing effective area), while a negative value insets away from the right edge (increasing it)." + }, + "insetRight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Insets the right edge by the specified number of pixels. A positive value insets towards the left edge (reducing effective area), while a negative value insets away from the left edge (increasing it)." + }, + "insetTop": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Insets the top edge by the specified number of pixels. A positive value insets towards the bottom edge (reducing effective area), while a negative value insets away from the bottom edge (increasing it)." + }, + "interval": { + "anyOf": [ + { + "$ref": "#/definitions/Interval" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to convert a continuous value (**x** for rectY, **y** for rectX, or both for rect) into an interval (**x1** and **x2** for rectY, or **y1** and\n**y2** for rectX, or both for rect); one of:\n\n- a named time interval such as *day* (for date intervals)\n- a number (for number intervals), defining intervals at integer multiples of *n*\n\nSetting this option disables the implicit stack transform (stackX for rectX, or stackY for rectY)." + }, + "margin": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four mark margins: **marginTop**,\n**marginRight**, **marginBottom**, and **marginLeft**; typically defaults to 0, except for axis marks." + }, + "marginBottom": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s bottom margin; the minimum distance in pixels between the bottom edges of the inner and outer plot area." + }, + "marginLeft": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s left margin; the minimum distance in pixels between the left edges of the inner and outer plot area." + }, + "marginRight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s right margin; the minimum distance in pixels between the right edges of the mark’s inner and outer plot area." + }, + "marginTop": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s top margin; the minimum distance in pixels between the top edges of the inner and outer plot area." + }, + "mark": { + "const": "rect", + "description": "A rect mark. The rectangle extends horizontally from **x1** to **x2**, and vertically from **y1** to **y2**. The position channels are often derived with a transform.\n\nWhen **y** extends from zero, for example for a histogram where the height of each rect reflects a count of values, use the rectY mark for an implicit stackY transform; similarly, if **x** extends from zero, use the rectX mark for an implicit stackX transform.\n\nIf an **interval** is specified, then **x1** and **x2** are derived from\n**x**, and **y1** and **y2** are derived from **y**, each representing the lower and upper bound of the containing interval, respectively.\n\nBoth *x* and *y* should be quantitative or temporal; otherwise, use a bar or cell mark.", + "type": "string" + }, + "meta": { + "$ref": "#/definitions/Meta", + "description": "Specification metadata." + }, + "mixBlendMode": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [mix-blend-mode][1]; a constant string specifying how to blend content such as *multiply*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode" + }, + "offset": { + "anyOf": [ + { + "$ref": "#/definitions/StackOffset" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "After stacking, an optional **offset** can be applied to translate and scale stacks, say to produce a streamgraph; defaults to null for a zero baseline (**y** = 0 for stackY, and **x** = 0 for stackX). If the *wiggle* offset is used, the default **order** changes to *inside-out*." + }, + "opacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally. For faster rendering, prefer the **strokeOpacity** or **fillOpacity** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/opacity" + }, + "order": { + "anyOf": [ + { + "$ref": "#/definitions/StackOrder" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The order in which stacks are layered; one of:\n\n- null (default) for input order\n- a named stack order method such as *inside-out* or *sum*\n- a field name, for natural order of the corresponding values\n- a function of data, for natural order of the corresponding values\n- an array of explicit **z** values in the desired order\n\nIf the *wiggle* **offset** is used, as for a streamgraph, the default changes to *inside-out*." + }, + "paintOrder": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [paint-order][1]; a constant string specifying the order in which the\n**fill**, **stroke**, and any markers are drawn; defaults to *normal*, which draws the fill, then stroke, then markers; defaults to *stroke* for the text mark to create a “halo” around text to improve legibility.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/paint-order" + }, + "params": { + "$ref": "#/definitions/Params", + "description": "Param and Selection definitions." + }, + "plotDefaults": { + "$ref": "#/definitions/PlotAttributes", + "description": "A default set of attributes to apply to all plot components." + }, + "pointerEvents": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [pointer-events][1] property; a constant string such as *none*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/pointer-events" + }, + "reverse": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Applies a transform to reverse the order of the mark’s index, say for reverse input order." + }, + "rx": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The rounded corner [*x*-radius][1], either in pixels or as a percentage of the rect width. If **rx** is not specified, it defaults to **ry** if present, and otherwise draws square corners.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/rx" + }, + "ry": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The rounded corner [*y*-radius][1], either in pixels or as a percentage of the rect height. If **ry** is not specified, it defaults to **rx** if present, and otherwise draws square corners.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/ry" + }, + "select": { + "$ref": "#/definitions/SelectFilter", + "description": "Applies a filter transform after data is loaded to highlight selected values only. For example, `first` and `last` select the first or last values of series only (using the *z* channel to separate series). Meanwhile, `nearestX` and `nearestY` select the point nearest to the pointer along the *x* or *y* channel dimension. Unlike Mosaic selections, a mark level *select* is internal to the mark only, and does not populate a param or selection value to be shared across clients.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "shapeRendering": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [shape-rendering][1]; a constant string such as *crispEdges*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/shape-rendering" + }, + "sort": { + "anyOf": [ + { + "$ref": "#/definitions/SortOrder" + }, + { + "$ref": "#/definitions/ChannelDomainSort" + } + ], + "description": "Either applies a transform to sort the mark’s index by the specified channel values, or imputes ordinal scale domains from this mark’s channels.\n\nWhen imputing ordinal scale domains from channel values, the **sort** option is an object whose keys are ordinal scale names such as *x* or *fx*, and whose values are channel names such as *y*, *y1*, or *y2*. For example, to impute the *y* scale’s domain from the associated *x* channel values in ascending order:\n\n```js sort: {y: \"x\"} ```\n\nFor different sort options for different scales, replace the channel name with a *value* object and per-scale options:\n\n```js sort: {y: {value: \"-x\"}} ```\n\nWhen sorting the mark’s index, the **sort** option is instead one of:\n\n- a channel value definition for sorting given values in ascending order\n- a {value, order} object for sorting given values\n- a {channel, order} object for sorting the named channel’s values" + }, + "stroke": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke" + }, + "strokeDasharray": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dasharray][1]; a constant number indicating the length in pixels of alternating dashes and gaps, or a constant string of numbers separated by spaces or commas (_e.g._, *10 2* for dashes of 10 pixels separated by gaps of 2 pixels), or *none* (the default) for no dashing\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dasharray" + }, + "strokeDashoffset": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dashoffset][1]; a constant indicating the offset in pixels of the first dash along the stroke; defaults to zero.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dashoffset" + }, + "strokeLinecap": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linecap][1]; a constant specifying how to cap stroked paths, such as *butt*, *round*, or *square*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linecap" + }, + "strokeLinejoin": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linejoin][1]; a constant specifying how to join stroked paths, such as *bevel*, *miter*, *miter-clip*, or *round*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linejoin" + }, + "strokeMiterlimit": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-miterlimit][1]; a constant number specifying how to limit the length of *miter* joins on stroked paths.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-miterlimit" + }, + "strokeOpacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-opacity" + }, + "strokeWidth": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-width][1]; a constant number in pixels, or a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-width" + }, + "target": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [target][1]; a constant string specifying the target window (_e.g._,\n*_blank*) for clickable links; used in conjunction with the **href** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/target" + }, + "tip": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/TipPointer" + }, + { + "properties": { + "anchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The tip anchor specifies how to orient the tip box relative to its anchor position; it refers to the part of the tip box that is attached to the anchor point. For example, the *top-left* anchor places the top-left corner of tip box near the anchor position, hence placing the tip box below and to the right of the anchor position." + }, + "fontFamily": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font-family][1]; a constant; defaults to the plot’s font family, which is typically [*system-ui*][2].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-family [2]: https://drafts.csswg.org/css-fonts-4/#valdef-font-family-system-ui" + }, + "fontSize": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font size][1] in pixels; either a constant or a channel; defaults to the plot’s font size, which is typically 10. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-size" + }, + "fontStyle": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font style][1]; a constant; defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-style" + }, + "fontVariant": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font variant][1]; a constant; if the **text** channel contains numbers or dates, defaults to *tabular-nums* to facilitate comparing numbers; otherwise defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant" + }, + "fontWeight": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font weight][1]; a constant; defaults to the plot’s font weight, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight" + }, + "format": { + "additionalProperties": false, + "description": "How channel values are formatted for display. If a format is a string, it is interpreted as a (UTC) time format for temporal channels, and otherwise a number format.", + "properties": { + "ariaLabel": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fill": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fillOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fontSize": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fx": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fy": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "geometry": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "height": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "href": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "length": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "opacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "path": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "r": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "rotate": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "src": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "stroke": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeWidth": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "symbol": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "text": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "title": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "weight": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "width": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "z": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + } + }, + "type": "object" + }, + "frameAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The frame anchor specifies defaults for **x** and **y** based on the plot’s frame; it may be one of the four sides (*top*, *right*, *bottom*, *left*), one of the four corners (*top-left*, *top-right*, *bottom-right*,\n*bottom-left*), or the *middle* of the frame. For example, for tips distributed horizontally at the top of the frame:\n\n```js Plot.tip(data, {x: \"date\", frameAnchor: \"top\"}) ```" + }, + "lineHeight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line height in ems; defaults to 1. The line height affects the (typically vertical) separation between adjacent baselines of text, as well as the separation between the text and its anchor point." + }, + "lineWidth": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line width in ems (e.g., 10 for about 20 characters); defaults to infinity, disabling wrapping and clipping.\n\nIf **textOverflow** is null, lines will be wrapped at the specified length. If a line is split at a soft hyphen (\\xad), a hyphen (-) will be displayed at the end of the line. If **textOverflow** is not null, lines will be clipped according to the given strategy." + }, + "monospace": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, changes the default **fontFamily** to *monospace*, and uses simplified monospaced text metrics calculations." + }, + "pathFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The image filter for the tip’s box; defaults to a drop shadow." + }, + "pointer": { + "$ref": "#/definitions/TipPointer" + }, + "pointerSize": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The size of the tip’s pointer in pixels; defaults to 12." + }, + "preferredAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If an explicit tip anchor is not specified, an anchor is chosen automatically such that the tip fits within the plot’s frame; if the preferred anchor fits, it is chosen." + }, + "textAnchor": { + "anyOf": [ + { + "const": "start", + "type": "string" + }, + { + "const": "middle", + "type": "string" + }, + { + "const": "end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [text anchor][1] controls how text is aligned (typically horizontally) relative to its anchor point; it is one of *start*, *end*, or *middle*. If the frame anchor is *left*, *top-left*, or *bottom-left*, the default text anchor is *start*; if the frame anchor is *right*, *top-right*, or\n*bottom-right*, the default is *end*; otherwise it is *middle*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/text-anchor" + }, + "textOverflow": { + "anyOf": [ + { + "type": "null" + }, + { + "const": "clip", + "type": "string" + }, + { + "const": "ellipsis", + "type": "string" + }, + { + "const": "clip-start", + "type": "string" + }, + { + "const": "clip-end", + "type": "string" + }, + { + "const": "ellipsis-start", + "type": "string" + }, + { + "const": "ellipsis-middle", + "type": "string" + }, + { + "const": "ellipsis-end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How truncate (or wrap) lines of text longer than the given **lineWidth**; one of:\n\n- null (default) - preserve overflowing characters (and wrap if needed)\n- *clip* or *clip-end* - remove characters from the end\n- *clip-start* - remove characters from the start\n- *ellipsis* or *ellipsis-end* - replace characters from the end with an ellipsis (…)\n- *ellipsis-start* - replace characters from the start with an ellipsis (…)\n- *ellipsis-middle* - replace characters from the middle with an ellipsis (…)\n\nIf no **title** was specified, if text requires truncation, a title containing the non-truncated text will be implicitly added." + }, + "textPadding": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The padding around the text in pixels; defaults to 8." + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + } + }, + "type": "object" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to generate a tooltip for this mark, and any tip options." + }, + "title": { + "$ref": "#/definitions/ChannelValue", + "description": "The title; a channel specifying accessible, short textual descriptions as strings (possibly with newlines). If the tip option is specified, the title will be displayed with an interactive tooltip instead of using the SVG [title element][1].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/title" + }, + "x": { + "$ref": "#/definitions/ChannelValueIntervalSpec", + "description": "The horizontal position (or length/width) channel, typically bound to the\n*x* scale.\n\nIf an **interval** is specified, then **x1** and **x2** are derived from\n**x**, representing the lower and upper bound of the containing interval, respectively. For example, for a vertical bar chart of items sold by day:\n\n```js Plot.rectY(sales, {x: \"date\", interval: \"day\", y2: \"items\"}) ```\n\nIf *x* represents ordinal values, use a bar or cell mark instead." + }, + "x1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The required primary (starting, often left) horizontal position channel, typically bound to the *x* scale. Setting this option disables the rectX mark’s implicit stackX transform.\n\nIf *x* represents ordinal values, use a bar or cell mark instead." + }, + "x2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The required secondary (ending, often right) horizontal position channel, typically bound to the *x* scale. Setting this option disables the rectX mark’s implicit stackX transform.\n\nIf *x* represents ordinal values, use a bar or cell mark instead." + }, + "y": { + "$ref": "#/definitions/ChannelValueIntervalSpec", + "description": "The vertical position (or length/height) channel, typically bound to the\n*y* scale.\n\nIf an **interval** is specified, then **y1** and **y2** are derived from\n**y**, representing the lower and upper bound of the containing interval, respectively. For example, for a horizontal bar chart of items sold by day:\n\n```js Plot.rectX(sales, {y: \"date\", interval: \"day\", x2: \"items\"}) ```\n\nIf *y* represents ordinal values, use a bar or cell mark instead." + }, + "y1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The required primary (starting, often bottom) vertical position channel, typically bound to the *y* scale. Setting this option disables the rectY mark’s implicit stackY transform.\n\nIf *y* represents ordinal values, use a bar or cell mark instead." + }, + "y2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The required secondary (ending, often top) vertical position channel, typically bound to the *y* scale. Setting this option disables the rectY mark’s implicit stackY transform.\n\nIf *y* represents ordinal values, use a bar or cell mark instead." + }, + "z": { + "$ref": "#/definitions/ChannelValue", + "description": "The **z** channel defines the series of each value in the stack. Used when the **order** is *sum*, *appearance*, *inside-out*, or an explicit array of\n**z** values." + } + }, + "required": [ + "data", + "mark" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "$schema": { + "description": "A [JSON schema](http://json-schema.org/) URL for this specification, such as https://uwdata.github.io/mosaic/schema/latest.json. This property enables validation and autocomplete in editors with JSON schema support.", + "format": "uri", + "type": "string" + }, + "ariaDescription": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-description][1]; a constant textual description.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-description" + }, + "ariaHidden": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-hidden][1] state; a constant indicating whether the element is exposed to an accessibility API.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-hidden" + }, + "ariaLabel": { + "$ref": "#/definitions/ChannelValue", + "description": "The [aria-label][1]; a channel specifying short textual labels representing the value in the accessibility tree.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-label" + }, + "clip": { + "anyOf": [ + { + "const": "frame", + "type": "string" + }, + { + "const": "sphere", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to clip the mark; one of:\n\n- *frame* or true - clip to the plot’s frame (inner area)\n- *sphere* - clip to the projected sphere (*e.g.*, front hemisphere)\n- null or false - do not clip\n\nThe *sphere* clip option requires a geographic projection." + }, + "config": { + "$ref": "#/definitions/Config", + "description": "Configuration options." + }, + "data": { + "$ref": "#/definitions/Data", + "description": "Dataset definitions." + }, + "dx": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The horizontal offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "dy": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The vertical offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "facet": { + "anyOf": [ + { + "const": "auto", + "type": "string" + }, + { + "const": "include", + "type": "string" + }, + { + "const": "exclude", + "type": "string" + }, + { + "const": "super", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to enable or disable faceting; one of:\n\n- *auto* (default) - automatically determine if this mark should be faceted\n- *include* (or true) - draw the subset of the mark’s data in the current facet\n- *exclude* - draw the subset of the mark’s data *not* in the current facet\n- *super* - draw this mark in a single frame that covers all facets\n- null (or false) - repeat this mark’s data across all facets (*i.e.*, no faceting)\n\nWhen a mark uses *super* faceting, it is not allowed to use position scales (*x*, *y*, *fx*, or *fy*); *super* faceting is intended for decorations, such as labels and legends.\n\nWhen top-level faceting is used, the default *auto* setting is equivalent to *include* when the mark data is strictly equal to the top-level facet data; otherwise it is equivalent to null. When the *include* or *exclude* facet mode is chosen, the mark data must be parallel to the top-level facet data: the data must have the same length and order. If the data are not parallel, then the wrong data may be shown in each facet. The default\n*auto* therefore requires strict equality (`===`) for safety, and using the facet data as mark data is recommended when using the *exclude* facet mode. (To construct parallel data safely, consider using [*array*.map][1] on the facet data.)\n\nWhen mark-level faceting is used, the default *auto* setting is equivalent to *include*: the mark will be faceted if either the **fx** or **fy** channel option (or both) is specified. The null or false option will disable faceting, while *exclude* draws the subset of the mark’s data *not* in the current facet.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map" + }, + "facetAnchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "right", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "const": "left", + "type": "string" + }, + { + "const": "top-left", + "type": "string" + }, + { + "const": "top-right", + "type": "string" + }, + { + "const": "bottom-left", + "type": "string" + }, + { + "const": "bottom-right", + "type": "string" + }, + { + "const": "top-empty", + "type": "string" + }, + { + "const": "right-empty", + "type": "string" + }, + { + "const": "bottom-empty", + "type": "string" + }, + { + "const": "left-empty", + "type": "string" + }, + { + "const": "empty", + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to place the mark with respect to facets; one of:\n\n- null (default for most marks) - display the mark in each non-empty facet\n- *top*, *right*, *bottom*, or *left* - display the mark only in facets on the given side\n- *top-empty*, *right-empty*, *bottom-empty*, or *left-empty* (default for axis marks) - display the mark only in facets that have empty space on the given side: either the margin, or an empty facet\n- *empty* - display the mark in empty facets only" + }, + "fill": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill" + }, + "fillOpacity": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill-opacity][1]; a constant number between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill-opacity" + }, + "filter": { + "$ref": "#/definitions/ChannelValue", + "description": "Applies a transform to filter the mark’s index according to the given channel values; only truthy values are retained.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "fx": { + "$ref": "#/definitions/ChannelValue", + "description": "The horizontal facet position channel, for mark-level faceting, bound to the *fx* scale." + }, + "fy": { + "$ref": "#/definitions/ChannelValue", + "description": "The vertical facet position channel, for mark-level faceting, bound to the\n*fy* scale." + }, + "href": { + "$ref": "#/definitions/ChannelValue", + "description": "The [href][1]; a channel specifying URLs for clickable links. May be used in conjunction with the **target** option to open links in another window.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/href" + }, + "imageFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A CSS [filter][1]; a constant string used to adjust the rendering of images, such as *blur(5px)*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/filter" + }, + "inset": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four insets: **insetTop**,\n**insetRight**, **insetBottom**, and **insetLeft**. All insets typically default to zero, though not always (say when using bin transform). A positive inset reduces effective area, while a negative inset increases it." + }, + "insetBottom": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Insets the bottom edge by the specified number of pixels. A positive value insets towards the top edge (reducing effective area), while a negative value insets away from the top edge (increasing it)." + }, + "insetLeft": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Insets the left edge by the specified number of pixels. A positive value insets towards the right edge (reducing effective area), while a negative value insets away from the right edge (increasing it)." + }, + "insetRight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Insets the right edge by the specified number of pixels. A positive value insets towards the left edge (reducing effective area), while a negative value insets away from the left edge (increasing it)." + }, + "insetTop": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Insets the top edge by the specified number of pixels. A positive value insets towards the bottom edge (reducing effective area), while a negative value insets away from the bottom edge (increasing it)." + }, + "interval": { + "anyOf": [ + { + "$ref": "#/definitions/Interval" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to convert a continuous value (**x** for rectY, **y** for rectX, or both for rect) into an interval (**x1** and **x2** for rectY, or **y1** and\n**y2** for rectX, or both for rect); one of:\n\n- a named time interval such as *day* (for date intervals)\n- a number (for number intervals), defining intervals at integer multiples of *n*\n\nSetting this option disables the implicit stack transform (stackX for rectX, or stackY for rectY)." + }, + "margin": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four mark margins: **marginTop**,\n**marginRight**, **marginBottom**, and **marginLeft**; typically defaults to 0, except for axis marks." + }, + "marginBottom": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s bottom margin; the minimum distance in pixels between the bottom edges of the inner and outer plot area." + }, + "marginLeft": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s left margin; the minimum distance in pixels between the left edges of the inner and outer plot area." + }, + "marginRight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s right margin; the minimum distance in pixels between the right edges of the mark’s inner and outer plot area." + }, + "marginTop": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s top margin; the minimum distance in pixels between the top edges of the inner and outer plot area." + }, + "mark": { + "const": "rectX", + "description": "Like rect, but if neither **x1** nor **x2** is specified, an implicit stackX transform is applied to **x**, and if **x** is not specified, it defaults to the identity function, assuming that *data* is an array of numbers [*x₀*, *x₁*, *x₂*, …].", + "type": "string" + }, + "meta": { + "$ref": "#/definitions/Meta", + "description": "Specification metadata." + }, + "mixBlendMode": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [mix-blend-mode][1]; a constant string specifying how to blend content such as *multiply*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode" + }, + "offset": { + "anyOf": [ + { + "$ref": "#/definitions/StackOffset" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "After stacking, an optional **offset** can be applied to translate and scale stacks, say to produce a streamgraph; defaults to null for a zero baseline (**y** = 0 for stackY, and **x** = 0 for stackX). If the *wiggle* offset is used, the default **order** changes to *inside-out*." + }, + "opacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally. For faster rendering, prefer the **strokeOpacity** or **fillOpacity** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/opacity" + }, + "order": { + "anyOf": [ + { + "$ref": "#/definitions/StackOrder" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The order in which stacks are layered; one of:\n\n- null (default) for input order\n- a named stack order method such as *inside-out* or *sum*\n- a field name, for natural order of the corresponding values\n- a function of data, for natural order of the corresponding values\n- an array of explicit **z** values in the desired order\n\nIf the *wiggle* **offset** is used, as for a streamgraph, the default changes to *inside-out*." + }, + "paintOrder": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [paint-order][1]; a constant string specifying the order in which the\n**fill**, **stroke**, and any markers are drawn; defaults to *normal*, which draws the fill, then stroke, then markers; defaults to *stroke* for the text mark to create a “halo” around text to improve legibility.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/paint-order" + }, + "params": { + "$ref": "#/definitions/Params", + "description": "Param and Selection definitions." + }, + "plotDefaults": { + "$ref": "#/definitions/PlotAttributes", + "description": "A default set of attributes to apply to all plot components." + }, + "pointerEvents": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [pointer-events][1] property; a constant string such as *none*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/pointer-events" + }, + "reverse": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Applies a transform to reverse the order of the mark’s index, say for reverse input order." + }, + "rx": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The rounded corner [*x*-radius][1], either in pixels or as a percentage of the rect width. If **rx** is not specified, it defaults to **ry** if present, and otherwise draws square corners.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/rx" + }, + "ry": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The rounded corner [*y*-radius][1], either in pixels or as a percentage of the rect height. If **ry** is not specified, it defaults to **rx** if present, and otherwise draws square corners.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/ry" + }, + "select": { + "$ref": "#/definitions/SelectFilter", + "description": "Applies a filter transform after data is loaded to highlight selected values only. For example, `first` and `last` select the first or last values of series only (using the *z* channel to separate series). Meanwhile, `nearestX` and `nearestY` select the point nearest to the pointer along the *x* or *y* channel dimension. Unlike Mosaic selections, a mark level *select* is internal to the mark only, and does not populate a param or selection value to be shared across clients.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "shapeRendering": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [shape-rendering][1]; a constant string such as *crispEdges*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/shape-rendering" + }, + "sort": { + "anyOf": [ + { + "$ref": "#/definitions/SortOrder" + }, + { + "$ref": "#/definitions/ChannelDomainSort" + } + ], + "description": "Either applies a transform to sort the mark’s index by the specified channel values, or imputes ordinal scale domains from this mark’s channels.\n\nWhen imputing ordinal scale domains from channel values, the **sort** option is an object whose keys are ordinal scale names such as *x* or *fx*, and whose values are channel names such as *y*, *y1*, or *y2*. For example, to impute the *y* scale’s domain from the associated *x* channel values in ascending order:\n\n```js sort: {y: \"x\"} ```\n\nFor different sort options for different scales, replace the channel name with a *value* object and per-scale options:\n\n```js sort: {y: {value: \"-x\"}} ```\n\nWhen sorting the mark’s index, the **sort** option is instead one of:\n\n- a channel value definition for sorting given values in ascending order\n- a {value, order} object for sorting given values\n- a {channel, order} object for sorting the named channel’s values" + }, + "stroke": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke" + }, + "strokeDasharray": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dasharray][1]; a constant number indicating the length in pixels of alternating dashes and gaps, or a constant string of numbers separated by spaces or commas (_e.g._, *10 2* for dashes of 10 pixels separated by gaps of 2 pixels), or *none* (the default) for no dashing\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dasharray" + }, + "strokeDashoffset": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dashoffset][1]; a constant indicating the offset in pixels of the first dash along the stroke; defaults to zero.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dashoffset" + }, + "strokeLinecap": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linecap][1]; a constant specifying how to cap stroked paths, such as *butt*, *round*, or *square*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linecap" + }, + "strokeLinejoin": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linejoin][1]; a constant specifying how to join stroked paths, such as *bevel*, *miter*, *miter-clip*, or *round*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linejoin" + }, + "strokeMiterlimit": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-miterlimit][1]; a constant number specifying how to limit the length of *miter* joins on stroked paths.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-miterlimit" + }, + "strokeOpacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-opacity" + }, + "strokeWidth": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-width][1]; a constant number in pixels, or a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-width" + }, + "target": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [target][1]; a constant string specifying the target window (_e.g._,\n*_blank*) for clickable links; used in conjunction with the **href** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/target" + }, + "tip": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/TipPointer" + }, + { + "properties": { + "anchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The tip anchor specifies how to orient the tip box relative to its anchor position; it refers to the part of the tip box that is attached to the anchor point. For example, the *top-left* anchor places the top-left corner of tip box near the anchor position, hence placing the tip box below and to the right of the anchor position." + }, + "fontFamily": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font-family][1]; a constant; defaults to the plot’s font family, which is typically [*system-ui*][2].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-family [2]: https://drafts.csswg.org/css-fonts-4/#valdef-font-family-system-ui" + }, + "fontSize": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font size][1] in pixels; either a constant or a channel; defaults to the plot’s font size, which is typically 10. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-size" + }, + "fontStyle": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font style][1]; a constant; defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-style" + }, + "fontVariant": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font variant][1]; a constant; if the **text** channel contains numbers or dates, defaults to *tabular-nums* to facilitate comparing numbers; otherwise defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant" + }, + "fontWeight": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font weight][1]; a constant; defaults to the plot’s font weight, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight" + }, + "format": { + "additionalProperties": false, + "description": "How channel values are formatted for display. If a format is a string, it is interpreted as a (UTC) time format for temporal channels, and otherwise a number format.", + "properties": { + "ariaLabel": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fill": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fillOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fontSize": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fx": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fy": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "geometry": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "height": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "href": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "length": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "opacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "path": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "r": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "rotate": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "src": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "stroke": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeWidth": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "symbol": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "text": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "title": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "weight": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "width": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "z": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + } + }, + "type": "object" + }, + "frameAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The frame anchor specifies defaults for **x** and **y** based on the plot’s frame; it may be one of the four sides (*top*, *right*, *bottom*, *left*), one of the four corners (*top-left*, *top-right*, *bottom-right*,\n*bottom-left*), or the *middle* of the frame. For example, for tips distributed horizontally at the top of the frame:\n\n```js Plot.tip(data, {x: \"date\", frameAnchor: \"top\"}) ```" + }, + "lineHeight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line height in ems; defaults to 1. The line height affects the (typically vertical) separation between adjacent baselines of text, as well as the separation between the text and its anchor point." + }, + "lineWidth": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line width in ems (e.g., 10 for about 20 characters); defaults to infinity, disabling wrapping and clipping.\n\nIf **textOverflow** is null, lines will be wrapped at the specified length. If a line is split at a soft hyphen (\\xad), a hyphen (-) will be displayed at the end of the line. If **textOverflow** is not null, lines will be clipped according to the given strategy." + }, + "monospace": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, changes the default **fontFamily** to *monospace*, and uses simplified monospaced text metrics calculations." + }, + "pathFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The image filter for the tip’s box; defaults to a drop shadow." + }, + "pointer": { + "$ref": "#/definitions/TipPointer" + }, + "pointerSize": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The size of the tip’s pointer in pixels; defaults to 12." + }, + "preferredAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If an explicit tip anchor is not specified, an anchor is chosen automatically such that the tip fits within the plot’s frame; if the preferred anchor fits, it is chosen." + }, + "textAnchor": { + "anyOf": [ + { + "const": "start", + "type": "string" + }, + { + "const": "middle", + "type": "string" + }, + { + "const": "end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [text anchor][1] controls how text is aligned (typically horizontally) relative to its anchor point; it is one of *start*, *end*, or *middle*. If the frame anchor is *left*, *top-left*, or *bottom-left*, the default text anchor is *start*; if the frame anchor is *right*, *top-right*, or\n*bottom-right*, the default is *end*; otherwise it is *middle*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/text-anchor" + }, + "textOverflow": { + "anyOf": [ + { + "type": "null" + }, + { + "const": "clip", + "type": "string" + }, + { + "const": "ellipsis", + "type": "string" + }, + { + "const": "clip-start", + "type": "string" + }, + { + "const": "clip-end", + "type": "string" + }, + { + "const": "ellipsis-start", + "type": "string" + }, + { + "const": "ellipsis-middle", + "type": "string" + }, + { + "const": "ellipsis-end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How truncate (or wrap) lines of text longer than the given **lineWidth**; one of:\n\n- null (default) - preserve overflowing characters (and wrap if needed)\n- *clip* or *clip-end* - remove characters from the end\n- *clip-start* - remove characters from the start\n- *ellipsis* or *ellipsis-end* - replace characters from the end with an ellipsis (…)\n- *ellipsis-start* - replace characters from the start with an ellipsis (…)\n- *ellipsis-middle* - replace characters from the middle with an ellipsis (…)\n\nIf no **title** was specified, if text requires truncation, a title containing the non-truncated text will be implicitly added." + }, + "textPadding": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The padding around the text in pixels; defaults to 8." + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + } + }, + "type": "object" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to generate a tooltip for this mark, and any tip options." + }, + "title": { + "$ref": "#/definitions/ChannelValue", + "description": "The title; a channel specifying accessible, short textual descriptions as strings (possibly with newlines). If the tip option is specified, the title will be displayed with an interactive tooltip instead of using the SVG [title element][1].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/title" + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position (or length/width) channel, typically bound to the\n*x* scale.\n\nIf neither **x1** nor **x2** is specified, an implicit stackX transform is applied and **x** defaults to the identity function, assuming that *data* = [*x₀*, *x₁*, *x₂*, …]. Otherwise, if only one of **x1** or **x2** is specified, the other defaults to **x**, which defaults to zero." + }, + "x1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The required primary (starting, often left) horizontal position channel, typically bound to the *x* scale. Setting this option disables the rectX mark’s implicit stackX transform.\n\nIf *x* represents ordinal values, use a bar or cell mark instead." + }, + "x2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The required secondary (ending, often right) horizontal position channel, typically bound to the *x* scale. Setting this option disables the rectX mark’s implicit stackX transform.\n\nIf *x* represents ordinal values, use a bar or cell mark instead." + }, + "y": { + "$ref": "#/definitions/ChannelValueIntervalSpec", + "description": "The vertical position (or length/height) channel, typically bound to the\n*y* scale.\n\nIf an **interval** is specified, then **y1** and **y2** are derived from\n**y**, representing the lower and upper bound of the containing interval, respectively. For example, for a horizontal bar chart of items sold by day:\n\n```js Plot.rectX(sales, {y: \"date\", interval: \"day\", x2: \"items\"}) ```\n\nIf *y* represents ordinal values, use a bar or cell mark instead." + }, + "y1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The required primary (starting, often bottom) vertical position channel, typically bound to the *y* scale. Setting this option disables the rectY mark’s implicit stackY transform.\n\nIf *y* represents ordinal values, use a bar or cell mark instead." + }, + "y2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The required secondary (ending, often top) vertical position channel, typically bound to the *y* scale. Setting this option disables the rectY mark’s implicit stackY transform.\n\nIf *y* represents ordinal values, use a bar or cell mark instead." + }, + "z": { + "$ref": "#/definitions/ChannelValue", + "description": "The **z** channel defines the series of each value in the stack. Used when the **order** is *sum*, *appearance*, *inside-out*, or an explicit array of\n**z** values." + } + }, + "required": [ + "data", + "mark" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "$schema": { + "description": "A [JSON schema](http://json-schema.org/) URL for this specification, such as https://uwdata.github.io/mosaic/schema/latest.json. This property enables validation and autocomplete in editors with JSON schema support.", + "format": "uri", + "type": "string" + }, + "ariaDescription": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-description][1]; a constant textual description.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-description" + }, + "ariaHidden": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-hidden][1] state; a constant indicating whether the element is exposed to an accessibility API.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-hidden" + }, + "ariaLabel": { + "$ref": "#/definitions/ChannelValue", + "description": "The [aria-label][1]; a channel specifying short textual labels representing the value in the accessibility tree.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-label" + }, + "clip": { + "anyOf": [ + { + "const": "frame", + "type": "string" + }, + { + "const": "sphere", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to clip the mark; one of:\n\n- *frame* or true - clip to the plot’s frame (inner area)\n- *sphere* - clip to the projected sphere (*e.g.*, front hemisphere)\n- null or false - do not clip\n\nThe *sphere* clip option requires a geographic projection." + }, + "config": { + "$ref": "#/definitions/Config", + "description": "Configuration options." + }, + "data": { + "$ref": "#/definitions/Data", + "description": "Dataset definitions." + }, + "dx": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The horizontal offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "dy": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The vertical offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "facet": { + "anyOf": [ + { + "const": "auto", + "type": "string" + }, + { + "const": "include", + "type": "string" + }, + { + "const": "exclude", + "type": "string" + }, + { + "const": "super", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to enable or disable faceting; one of:\n\n- *auto* (default) - automatically determine if this mark should be faceted\n- *include* (or true) - draw the subset of the mark’s data in the current facet\n- *exclude* - draw the subset of the mark’s data *not* in the current facet\n- *super* - draw this mark in a single frame that covers all facets\n- null (or false) - repeat this mark’s data across all facets (*i.e.*, no faceting)\n\nWhen a mark uses *super* faceting, it is not allowed to use position scales (*x*, *y*, *fx*, or *fy*); *super* faceting is intended for decorations, such as labels and legends.\n\nWhen top-level faceting is used, the default *auto* setting is equivalent to *include* when the mark data is strictly equal to the top-level facet data; otherwise it is equivalent to null. When the *include* or *exclude* facet mode is chosen, the mark data must be parallel to the top-level facet data: the data must have the same length and order. If the data are not parallel, then the wrong data may be shown in each facet. The default\n*auto* therefore requires strict equality (`===`) for safety, and using the facet data as mark data is recommended when using the *exclude* facet mode. (To construct parallel data safely, consider using [*array*.map][1] on the facet data.)\n\nWhen mark-level faceting is used, the default *auto* setting is equivalent to *include*: the mark will be faceted if either the **fx** or **fy** channel option (or both) is specified. The null or false option will disable faceting, while *exclude* draws the subset of the mark’s data *not* in the current facet.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map" + }, + "facetAnchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "right", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "const": "left", + "type": "string" + }, + { + "const": "top-left", + "type": "string" + }, + { + "const": "top-right", + "type": "string" + }, + { + "const": "bottom-left", + "type": "string" + }, + { + "const": "bottom-right", + "type": "string" + }, + { + "const": "top-empty", + "type": "string" + }, + { + "const": "right-empty", + "type": "string" + }, + { + "const": "bottom-empty", + "type": "string" + }, + { + "const": "left-empty", + "type": "string" + }, + { + "const": "empty", + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to place the mark with respect to facets; one of:\n\n- null (default for most marks) - display the mark in each non-empty facet\n- *top*, *right*, *bottom*, or *left* - display the mark only in facets on the given side\n- *top-empty*, *right-empty*, *bottom-empty*, or *left-empty* (default for axis marks) - display the mark only in facets that have empty space on the given side: either the margin, or an empty facet\n- *empty* - display the mark in empty facets only" + }, + "fill": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill" + }, + "fillOpacity": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill-opacity][1]; a constant number between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill-opacity" + }, + "filter": { + "$ref": "#/definitions/ChannelValue", + "description": "Applies a transform to filter the mark’s index according to the given channel values; only truthy values are retained.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "fx": { + "$ref": "#/definitions/ChannelValue", + "description": "The horizontal facet position channel, for mark-level faceting, bound to the *fx* scale." + }, + "fy": { + "$ref": "#/definitions/ChannelValue", + "description": "The vertical facet position channel, for mark-level faceting, bound to the\n*fy* scale." + }, + "href": { + "$ref": "#/definitions/ChannelValue", + "description": "The [href][1]; a channel specifying URLs for clickable links. May be used in conjunction with the **target** option to open links in another window.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/href" + }, + "imageFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A CSS [filter][1]; a constant string used to adjust the rendering of images, such as *blur(5px)*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/filter" + }, + "inset": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four insets: **insetTop**,\n**insetRight**, **insetBottom**, and **insetLeft**. All insets typically default to zero, though not always (say when using bin transform). A positive inset reduces effective area, while a negative inset increases it." + }, + "insetBottom": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Insets the bottom edge by the specified number of pixels. A positive value insets towards the top edge (reducing effective area), while a negative value insets away from the top edge (increasing it)." + }, + "insetLeft": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Insets the left edge by the specified number of pixels. A positive value insets towards the right edge (reducing effective area), while a negative value insets away from the right edge (increasing it)." + }, + "insetRight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Insets the right edge by the specified number of pixels. A positive value insets towards the left edge (reducing effective area), while a negative value insets away from the left edge (increasing it)." + }, + "insetTop": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Insets the top edge by the specified number of pixels. A positive value insets towards the bottom edge (reducing effective area), while a negative value insets away from the bottom edge (increasing it)." + }, + "interval": { + "anyOf": [ + { + "$ref": "#/definitions/Interval" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to convert a continuous value (**x** for rectY, **y** for rectX, or both for rect) into an interval (**x1** and **x2** for rectY, or **y1** and\n**y2** for rectX, or both for rect); one of:\n\n- a named time interval such as *day* (for date intervals)\n- a number (for number intervals), defining intervals at integer multiples of *n*\n\nSetting this option disables the implicit stack transform (stackX for rectX, or stackY for rectY)." + }, + "margin": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four mark margins: **marginTop**,\n**marginRight**, **marginBottom**, and **marginLeft**; typically defaults to 0, except for axis marks." + }, + "marginBottom": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s bottom margin; the minimum distance in pixels between the bottom edges of the inner and outer plot area." + }, + "marginLeft": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s left margin; the minimum distance in pixels between the left edges of the inner and outer plot area." + }, + "marginRight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s right margin; the minimum distance in pixels between the right edges of the mark’s inner and outer plot area." + }, + "marginTop": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s top margin; the minimum distance in pixels between the top edges of the inner and outer plot area." + }, + "mark": { + "const": "rectY", + "description": "Like rect, but if neither **y1** nor **y2** is specified, apply an implicit stackY transform is applied to **y**, and if **y** is not specified, it defaults to the identity function, assuming that *data* is an array of numbers [*y₀*, *y₁*, *y₂*, …].", + "type": "string" + }, + "meta": { + "$ref": "#/definitions/Meta", + "description": "Specification metadata." + }, + "mixBlendMode": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [mix-blend-mode][1]; a constant string specifying how to blend content such as *multiply*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode" + }, + "offset": { + "anyOf": [ + { + "$ref": "#/definitions/StackOffset" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "After stacking, an optional **offset** can be applied to translate and scale stacks, say to produce a streamgraph; defaults to null for a zero baseline (**y** = 0 for stackY, and **x** = 0 for stackX). If the *wiggle* offset is used, the default **order** changes to *inside-out*." + }, + "opacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally. For faster rendering, prefer the **strokeOpacity** or **fillOpacity** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/opacity" + }, + "order": { + "anyOf": [ + { + "$ref": "#/definitions/StackOrder" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The order in which stacks are layered; one of:\n\n- null (default) for input order\n- a named stack order method such as *inside-out* or *sum*\n- a field name, for natural order of the corresponding values\n- a function of data, for natural order of the corresponding values\n- an array of explicit **z** values in the desired order\n\nIf the *wiggle* **offset** is used, as for a streamgraph, the default changes to *inside-out*." + }, + "paintOrder": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [paint-order][1]; a constant string specifying the order in which the\n**fill**, **stroke**, and any markers are drawn; defaults to *normal*, which draws the fill, then stroke, then markers; defaults to *stroke* for the text mark to create a “halo” around text to improve legibility.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/paint-order" + }, + "params": { + "$ref": "#/definitions/Params", + "description": "Param and Selection definitions." + }, + "plotDefaults": { + "$ref": "#/definitions/PlotAttributes", + "description": "A default set of attributes to apply to all plot components." + }, + "pointerEvents": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [pointer-events][1] property; a constant string such as *none*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/pointer-events" + }, + "reverse": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Applies a transform to reverse the order of the mark’s index, say for reverse input order." + }, + "rx": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The rounded corner [*x*-radius][1], either in pixels or as a percentage of the rect width. If **rx** is not specified, it defaults to **ry** if present, and otherwise draws square corners.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/rx" + }, + "ry": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The rounded corner [*y*-radius][1], either in pixels or as a percentage of the rect height. If **ry** is not specified, it defaults to **rx** if present, and otherwise draws square corners.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/ry" + }, + "select": { + "$ref": "#/definitions/SelectFilter", + "description": "Applies a filter transform after data is loaded to highlight selected values only. For example, `first` and `last` select the first or last values of series only (using the *z* channel to separate series). Meanwhile, `nearestX` and `nearestY` select the point nearest to the pointer along the *x* or *y* channel dimension. Unlike Mosaic selections, a mark level *select* is internal to the mark only, and does not populate a param or selection value to be shared across clients.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "shapeRendering": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [shape-rendering][1]; a constant string such as *crispEdges*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/shape-rendering" + }, + "sort": { + "anyOf": [ + { + "$ref": "#/definitions/SortOrder" + }, + { + "$ref": "#/definitions/ChannelDomainSort" + } + ], + "description": "Either applies a transform to sort the mark’s index by the specified channel values, or imputes ordinal scale domains from this mark’s channels.\n\nWhen imputing ordinal scale domains from channel values, the **sort** option is an object whose keys are ordinal scale names such as *x* or *fx*, and whose values are channel names such as *y*, *y1*, or *y2*. For example, to impute the *y* scale’s domain from the associated *x* channel values in ascending order:\n\n```js sort: {y: \"x\"} ```\n\nFor different sort options for different scales, replace the channel name with a *value* object and per-scale options:\n\n```js sort: {y: {value: \"-x\"}} ```\n\nWhen sorting the mark’s index, the **sort** option is instead one of:\n\n- a channel value definition for sorting given values in ascending order\n- a {value, order} object for sorting given values\n- a {channel, order} object for sorting the named channel’s values" + }, + "stroke": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke" + }, + "strokeDasharray": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dasharray][1]; a constant number indicating the length in pixels of alternating dashes and gaps, or a constant string of numbers separated by spaces or commas (_e.g._, *10 2* for dashes of 10 pixels separated by gaps of 2 pixels), or *none* (the default) for no dashing\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dasharray" + }, + "strokeDashoffset": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dashoffset][1]; a constant indicating the offset in pixels of the first dash along the stroke; defaults to zero.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dashoffset" + }, + "strokeLinecap": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linecap][1]; a constant specifying how to cap stroked paths, such as *butt*, *round*, or *square*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linecap" + }, + "strokeLinejoin": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linejoin][1]; a constant specifying how to join stroked paths, such as *bevel*, *miter*, *miter-clip*, or *round*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linejoin" + }, + "strokeMiterlimit": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-miterlimit][1]; a constant number specifying how to limit the length of *miter* joins on stroked paths.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-miterlimit" + }, + "strokeOpacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-opacity" + }, + "strokeWidth": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-width][1]; a constant number in pixels, or a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-width" + }, + "target": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [target][1]; a constant string specifying the target window (_e.g._,\n*_blank*) for clickable links; used in conjunction with the **href** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/target" + }, + "tip": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/TipPointer" + }, + { + "properties": { + "anchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The tip anchor specifies how to orient the tip box relative to its anchor position; it refers to the part of the tip box that is attached to the anchor point. For example, the *top-left* anchor places the top-left corner of tip box near the anchor position, hence placing the tip box below and to the right of the anchor position." + }, + "fontFamily": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font-family][1]; a constant; defaults to the plot’s font family, which is typically [*system-ui*][2].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-family [2]: https://drafts.csswg.org/css-fonts-4/#valdef-font-family-system-ui" + }, + "fontSize": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font size][1] in pixels; either a constant or a channel; defaults to the plot’s font size, which is typically 10. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-size" + }, + "fontStyle": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font style][1]; a constant; defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-style" + }, + "fontVariant": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font variant][1]; a constant; if the **text** channel contains numbers or dates, defaults to *tabular-nums* to facilitate comparing numbers; otherwise defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant" + }, + "fontWeight": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font weight][1]; a constant; defaults to the plot’s font weight, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight" + }, + "format": { + "additionalProperties": false, + "description": "How channel values are formatted for display. If a format is a string, it is interpreted as a (UTC) time format for temporal channels, and otherwise a number format.", + "properties": { + "ariaLabel": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fill": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fillOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fontSize": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fx": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fy": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "geometry": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "height": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "href": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "length": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "opacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "path": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "r": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "rotate": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "src": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "stroke": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeWidth": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "symbol": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "text": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "title": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "weight": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "width": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "z": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + } + }, + "type": "object" + }, + "frameAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The frame anchor specifies defaults for **x** and **y** based on the plot’s frame; it may be one of the four sides (*top*, *right*, *bottom*, *left*), one of the four corners (*top-left*, *top-right*, *bottom-right*,\n*bottom-left*), or the *middle* of the frame. For example, for tips distributed horizontally at the top of the frame:\n\n```js Plot.tip(data, {x: \"date\", frameAnchor: \"top\"}) ```" + }, + "lineHeight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line height in ems; defaults to 1. The line height affects the (typically vertical) separation between adjacent baselines of text, as well as the separation between the text and its anchor point." + }, + "lineWidth": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line width in ems (e.g., 10 for about 20 characters); defaults to infinity, disabling wrapping and clipping.\n\nIf **textOverflow** is null, lines will be wrapped at the specified length. If a line is split at a soft hyphen (\\xad), a hyphen (-) will be displayed at the end of the line. If **textOverflow** is not null, lines will be clipped according to the given strategy." + }, + "monospace": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, changes the default **fontFamily** to *monospace*, and uses simplified monospaced text metrics calculations." + }, + "pathFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The image filter for the tip’s box; defaults to a drop shadow." + }, + "pointer": { + "$ref": "#/definitions/TipPointer" + }, + "pointerSize": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The size of the tip’s pointer in pixels; defaults to 12." + }, + "preferredAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If an explicit tip anchor is not specified, an anchor is chosen automatically such that the tip fits within the plot’s frame; if the preferred anchor fits, it is chosen." + }, + "textAnchor": { + "anyOf": [ + { + "const": "start", + "type": "string" + }, + { + "const": "middle", + "type": "string" + }, + { + "const": "end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [text anchor][1] controls how text is aligned (typically horizontally) relative to its anchor point; it is one of *start*, *end*, or *middle*. If the frame anchor is *left*, *top-left*, or *bottom-left*, the default text anchor is *start*; if the frame anchor is *right*, *top-right*, or\n*bottom-right*, the default is *end*; otherwise it is *middle*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/text-anchor" + }, + "textOverflow": { + "anyOf": [ + { + "type": "null" + }, + { + "const": "clip", + "type": "string" + }, + { + "const": "ellipsis", + "type": "string" + }, + { + "const": "clip-start", + "type": "string" + }, + { + "const": "clip-end", + "type": "string" + }, + { + "const": "ellipsis-start", + "type": "string" + }, + { + "const": "ellipsis-middle", + "type": "string" + }, + { + "const": "ellipsis-end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How truncate (or wrap) lines of text longer than the given **lineWidth**; one of:\n\n- null (default) - preserve overflowing characters (and wrap if needed)\n- *clip* or *clip-end* - remove characters from the end\n- *clip-start* - remove characters from the start\n- *ellipsis* or *ellipsis-end* - replace characters from the end with an ellipsis (…)\n- *ellipsis-start* - replace characters from the start with an ellipsis (…)\n- *ellipsis-middle* - replace characters from the middle with an ellipsis (…)\n\nIf no **title** was specified, if text requires truncation, a title containing the non-truncated text will be implicitly added." + }, + "textPadding": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The padding around the text in pixels; defaults to 8." + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + } + }, + "type": "object" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to generate a tooltip for this mark, and any tip options." + }, + "title": { + "$ref": "#/definitions/ChannelValue", + "description": "The title; a channel specifying accessible, short textual descriptions as strings (possibly with newlines). If the tip option is specified, the title will be displayed with an interactive tooltip instead of using the SVG [title element][1].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/title" + }, + "x": { + "$ref": "#/definitions/ChannelValueIntervalSpec", + "description": "The horizontal position (or length/width) channel, typically bound to the\n*x* scale.\n\nIf an **interval** is specified, then **x1** and **x2** are derived from\n**x**, representing the lower and upper bound of the containing interval, respectively. For example, for a vertical bar chart of items sold by day:\n\n```js Plot.rectY(sales, {x: \"date\", interval: \"day\", y2: \"items\"}) ```\n\nIf *x* represents ordinal values, use a bar or cell mark instead." + }, + "x1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The required primary (starting, often left) horizontal position channel, typically bound to the *x* scale. Setting this option disables the rectX mark’s implicit stackX transform.\n\nIf *x* represents ordinal values, use a bar or cell mark instead." + }, + "x2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The required secondary (ending, often right) horizontal position channel, typically bound to the *x* scale. Setting this option disables the rectX mark’s implicit stackX transform.\n\nIf *x* represents ordinal values, use a bar or cell mark instead." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position (or length/height) channel, typically bound to the\n*y* scale.\n\nIf neither **y1** nor **y2** is specified, an implicit stackY transform is applied and **y** defaults to the identity function, assuming that *data* = [*y₀*, *y₁*, *y₂*, …]. Otherwise, if only one of **y1** or **y2** is specified, the other defaults to **y**, which defaults to zero." + }, + "y1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The required primary (starting, often bottom) vertical position channel, typically bound to the *y* scale. Setting this option disables the rectY mark’s implicit stackY transform.\n\nIf *y* represents ordinal values, use a bar or cell mark instead." + }, + "y2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The required secondary (ending, often top) vertical position channel, typically bound to the *y* scale. Setting this option disables the rectY mark’s implicit stackY transform.\n\nIf *y* represents ordinal values, use a bar or cell mark instead." + }, + "z": { + "$ref": "#/definitions/ChannelValue", + "description": "The **z** channel defines the series of each value in the stack. Used when the **order** is *sum*, *appearance*, *inside-out*, or an explicit array of\n**z** values." + } + }, + "required": [ + "data", + "mark" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "$schema": { + "description": "A [JSON schema](http://json-schema.org/) URL for this specification, such as https://uwdata.github.io/mosaic/schema/latest.json. This property enables validation and autocomplete in editors with JSON schema support.", + "format": "uri", + "type": "string" + }, + "ariaDescription": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-description][1]; a constant textual description.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-description" + }, + "ariaHidden": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-hidden][1] state; a constant indicating whether the element is exposed to an accessibility API.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-hidden" + }, + "ariaLabel": { + "$ref": "#/definitions/ChannelValue", + "description": "The [aria-label][1]; a channel specifying short textual labels representing the value in the accessibility tree.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-label" + }, + "ci": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The confidence interval in (0, 1), or 0 to hide bands; defaults to 0.95." + }, + "clip": { + "anyOf": [ + { + "const": "frame", + "type": "string" + }, + { + "const": "sphere", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to clip the mark; one of:\n\n- *frame* or true - clip to the plot’s frame (inner area)\n- *sphere* - clip to the projected sphere (*e.g.*, front hemisphere)\n- null or false - do not clip\n\nThe *sphere* clip option requires a geographic projection." + }, + "config": { + "$ref": "#/definitions/Config", + "description": "Configuration options." + }, + "data": { + "$ref": "#/definitions/Data", + "description": "Dataset definitions." + }, + "dx": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The horizontal offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "dy": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The vertical offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "facet": { + "anyOf": [ + { + "const": "auto", + "type": "string" + }, + { + "const": "include", + "type": "string" + }, + { + "const": "exclude", + "type": "string" + }, + { + "const": "super", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to enable or disable faceting; one of:\n\n- *auto* (default) - automatically determine if this mark should be faceted\n- *include* (or true) - draw the subset of the mark’s data in the current facet\n- *exclude* - draw the subset of the mark’s data *not* in the current facet\n- *super* - draw this mark in a single frame that covers all facets\n- null (or false) - repeat this mark’s data across all facets (*i.e.*, no faceting)\n\nWhen a mark uses *super* faceting, it is not allowed to use position scales (*x*, *y*, *fx*, or *fy*); *super* faceting is intended for decorations, such as labels and legends.\n\nWhen top-level faceting is used, the default *auto* setting is equivalent to *include* when the mark data is strictly equal to the top-level facet data; otherwise it is equivalent to null. When the *include* or *exclude* facet mode is chosen, the mark data must be parallel to the top-level facet data: the data must have the same length and order. If the data are not parallel, then the wrong data may be shown in each facet. The default\n*auto* therefore requires strict equality (`===`) for safety, and using the facet data as mark data is recommended when using the *exclude* facet mode. (To construct parallel data safely, consider using [*array*.map][1] on the facet data.)\n\nWhen mark-level faceting is used, the default *auto* setting is equivalent to *include*: the mark will be faceted if either the **fx** or **fy** channel option (or both) is specified. The null or false option will disable faceting, while *exclude* draws the subset of the mark’s data *not* in the current facet.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map" + }, + "facetAnchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "right", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "const": "left", + "type": "string" + }, + { + "const": "top-left", + "type": "string" + }, + { + "const": "top-right", + "type": "string" + }, + { + "const": "bottom-left", + "type": "string" + }, + { + "const": "bottom-right", + "type": "string" + }, + { + "const": "top-empty", + "type": "string" + }, + { + "const": "right-empty", + "type": "string" + }, + { + "const": "bottom-empty", + "type": "string" + }, + { + "const": "left-empty", + "type": "string" + }, + { + "const": "empty", + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to place the mark with respect to facets; one of:\n\n- null (default for most marks) - display the mark in each non-empty facet\n- *top*, *right*, *bottom*, or *left* - display the mark only in facets on the given side\n- *top-empty*, *right-empty*, *bottom-empty*, or *left-empty* (default for axis marks) - display the mark only in facets that have empty space on the given side: either the margin, or an empty facet\n- *empty* - display the mark in empty facets only" + }, + "fill": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill" + }, + "fillOpacity": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill-opacity][1]; a constant number between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill-opacity" + }, + "filter": { + "$ref": "#/definitions/ChannelValue", + "description": "Applies a transform to filter the mark’s index according to the given channel values; only truthy values are retained.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "fx": { + "$ref": "#/definitions/ChannelValue", + "description": "The horizontal facet position channel, for mark-level faceting, bound to the *fx* scale." + }, + "fy": { + "$ref": "#/definitions/ChannelValue", + "description": "The vertical facet position channel, for mark-level faceting, bound to the\n*fy* scale." + }, + "href": { + "$ref": "#/definitions/ChannelValue", + "description": "The [href][1]; a channel specifying URLs for clickable links. May be used in conjunction with the **target** option to open links in another window.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/href" + }, + "imageFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A CSS [filter][1]; a constant string used to adjust the rendering of images, such as *blur(5px)*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/filter" + }, + "margin": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four mark margins: **marginTop**,\n**marginRight**, **marginBottom**, and **marginLeft**; typically defaults to 0, except for axis marks." + }, + "marginBottom": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s bottom margin; the minimum distance in pixels between the bottom edges of the inner and outer plot area." + }, + "marginLeft": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s left margin; the minimum distance in pixels between the left edges of the inner and outer plot area." + }, + "marginRight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s right margin; the minimum distance in pixels between the right edges of the mark’s inner and outer plot area." + }, + "marginTop": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s top margin; the minimum distance in pixels between the top edges of the inner and outer plot area." + }, + "mark": { + "const": "regressionY", + "description": "A mark that draws [linear regression][1] lines with confidence bands, representing the estimated relation of a dependent variable (*y*) on an independent variable (*x*).\n\nThe linear regression line is fit using the [least squares][2] approach. See Torben Jansen’s [“Linear regression with confidence bands”][3] and [this StatExchange question][4] for details on the confidence interval calculation.\n\nMultiple regressions can be produced by specifying a **z**, **fill**, or\n**stroke** channel.\n\n[1]: https://en.wikipedia.org/wiki/Linear_regression [2]: https://en.wikipedia.org/wiki/Least_squares [3]: https://observablehq.com/@toja/linear-regression-with-confidence-bands [4]: https://stats.stackexchange.com/questions/101318/understanding-shape-and-calculation-of-confidence-bands-in-linear-regression", + "type": "string" + }, + "meta": { + "$ref": "#/definitions/Meta", + "description": "Specification metadata." + }, + "mixBlendMode": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [mix-blend-mode][1]; a constant string specifying how to blend content such as *multiply*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode" + }, + "opacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally. For faster rendering, prefer the **strokeOpacity** or **fillOpacity** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/opacity" + }, + "paintOrder": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [paint-order][1]; a constant string specifying the order in which the\n**fill**, **stroke**, and any markers are drawn; defaults to *normal*, which draws the fill, then stroke, then markers; defaults to *stroke* for the text mark to create a “halo” around text to improve legibility.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/paint-order" + }, + "params": { + "$ref": "#/definitions/Params", + "description": "Param and Selection definitions." + }, + "plotDefaults": { + "$ref": "#/definitions/PlotAttributes", + "description": "A default set of attributes to apply to all plot components." + }, + "pointerEvents": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [pointer-events][1] property; a constant string such as *none*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/pointer-events" + }, + "precision": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The distance in pixels between samples of the confidence band; defaults to 4." + }, + "reverse": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Applies a transform to reverse the order of the mark’s index, say for reverse input order." + }, + "select": { + "$ref": "#/definitions/SelectFilter", + "description": "Applies a filter transform after data is loaded to highlight selected values only. For example, `first` and `last` select the first or last values of series only (using the *z* channel to separate series). Meanwhile, `nearestX` and `nearestY` select the point nearest to the pointer along the *x* or *y* channel dimension. Unlike Mosaic selections, a mark level *select* is internal to the mark only, and does not populate a param or selection value to be shared across clients.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "shapeRendering": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [shape-rendering][1]; a constant string such as *crispEdges*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/shape-rendering" + }, + "sort": { + "anyOf": [ + { + "$ref": "#/definitions/SortOrder" + }, + { + "$ref": "#/definitions/ChannelDomainSort" + } + ], + "description": "Either applies a transform to sort the mark’s index by the specified channel values, or imputes ordinal scale domains from this mark’s channels.\n\nWhen imputing ordinal scale domains from channel values, the **sort** option is an object whose keys are ordinal scale names such as *x* or *fx*, and whose values are channel names such as *y*, *y1*, or *y2*. For example, to impute the *y* scale’s domain from the associated *x* channel values in ascending order:\n\n```js sort: {y: \"x\"} ```\n\nFor different sort options for different scales, replace the channel name with a *value* object and per-scale options:\n\n```js sort: {y: {value: \"-x\"}} ```\n\nWhen sorting the mark’s index, the **sort** option is instead one of:\n\n- a channel value definition for sorting given values in ascending order\n- a {value, order} object for sorting given values\n- a {channel, order} object for sorting the named channel’s values" + }, + "stroke": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke" + }, + "strokeDasharray": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dasharray][1]; a constant number indicating the length in pixels of alternating dashes and gaps, or a constant string of numbers separated by spaces or commas (_e.g._, *10 2* for dashes of 10 pixels separated by gaps of 2 pixels), or *none* (the default) for no dashing\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dasharray" + }, + "strokeDashoffset": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dashoffset][1]; a constant indicating the offset in pixels of the first dash along the stroke; defaults to zero.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dashoffset" + }, + "strokeLinecap": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linecap][1]; a constant specifying how to cap stroked paths, such as *butt*, *round*, or *square*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linecap" + }, + "strokeLinejoin": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linejoin][1]; a constant specifying how to join stroked paths, such as *bevel*, *miter*, *miter-clip*, or *round*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linejoin" + }, + "strokeMiterlimit": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-miterlimit][1]; a constant number specifying how to limit the length of *miter* joins on stroked paths.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-miterlimit" + }, + "strokeOpacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-opacity" + }, + "strokeWidth": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-width][1]; a constant number in pixels, or a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-width" + }, + "target": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [target][1]; a constant string specifying the target window (_e.g._,\n*_blank*) for clickable links; used in conjunction with the **href** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/target" + }, + "tip": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/TipPointer" + }, + { + "properties": { + "anchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The tip anchor specifies how to orient the tip box relative to its anchor position; it refers to the part of the tip box that is attached to the anchor point. For example, the *top-left* anchor places the top-left corner of tip box near the anchor position, hence placing the tip box below and to the right of the anchor position." + }, + "fontFamily": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font-family][1]; a constant; defaults to the plot’s font family, which is typically [*system-ui*][2].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-family [2]: https://drafts.csswg.org/css-fonts-4/#valdef-font-family-system-ui" + }, + "fontSize": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font size][1] in pixels; either a constant or a channel; defaults to the plot’s font size, which is typically 10. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-size" + }, + "fontStyle": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font style][1]; a constant; defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-style" + }, + "fontVariant": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font variant][1]; a constant; if the **text** channel contains numbers or dates, defaults to *tabular-nums* to facilitate comparing numbers; otherwise defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant" + }, + "fontWeight": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font weight][1]; a constant; defaults to the plot’s font weight, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight" + }, + "format": { + "additionalProperties": false, + "description": "How channel values are formatted for display. If a format is a string, it is interpreted as a (UTC) time format for temporal channels, and otherwise a number format.", + "properties": { + "ariaLabel": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fill": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fillOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fontSize": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fx": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fy": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "geometry": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "height": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "href": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "length": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "opacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "path": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "r": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "rotate": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "src": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "stroke": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeWidth": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "symbol": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "text": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "title": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "weight": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "width": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "z": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + } + }, + "type": "object" + }, + "frameAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The frame anchor specifies defaults for **x** and **y** based on the plot’s frame; it may be one of the four sides (*top*, *right*, *bottom*, *left*), one of the four corners (*top-left*, *top-right*, *bottom-right*,\n*bottom-left*), or the *middle* of the frame. For example, for tips distributed horizontally at the top of the frame:\n\n```js Plot.tip(data, {x: \"date\", frameAnchor: \"top\"}) ```" + }, + "lineHeight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line height in ems; defaults to 1. The line height affects the (typically vertical) separation between adjacent baselines of text, as well as the separation between the text and its anchor point." + }, + "lineWidth": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line width in ems (e.g., 10 for about 20 characters); defaults to infinity, disabling wrapping and clipping.\n\nIf **textOverflow** is null, lines will be wrapped at the specified length. If a line is split at a soft hyphen (\\xad), a hyphen (-) will be displayed at the end of the line. If **textOverflow** is not null, lines will be clipped according to the given strategy." + }, + "monospace": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, changes the default **fontFamily** to *monospace*, and uses simplified monospaced text metrics calculations." + }, + "pathFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The image filter for the tip’s box; defaults to a drop shadow." + }, + "pointer": { + "$ref": "#/definitions/TipPointer" + }, + "pointerSize": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The size of the tip’s pointer in pixels; defaults to 12." + }, + "preferredAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If an explicit tip anchor is not specified, an anchor is chosen automatically such that the tip fits within the plot’s frame; if the preferred anchor fits, it is chosen." + }, + "textAnchor": { + "anyOf": [ + { + "const": "start", + "type": "string" + }, + { + "const": "middle", + "type": "string" + }, + { + "const": "end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [text anchor][1] controls how text is aligned (typically horizontally) relative to its anchor point; it is one of *start*, *end*, or *middle*. If the frame anchor is *left*, *top-left*, or *bottom-left*, the default text anchor is *start*; if the frame anchor is *right*, *top-right*, or\n*bottom-right*, the default is *end*; otherwise it is *middle*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/text-anchor" + }, + "textOverflow": { + "anyOf": [ + { + "type": "null" + }, + { + "const": "clip", + "type": "string" + }, + { + "const": "ellipsis", + "type": "string" + }, + { + "const": "clip-start", + "type": "string" + }, + { + "const": "clip-end", + "type": "string" + }, + { + "const": "ellipsis-start", + "type": "string" + }, + { + "const": "ellipsis-middle", + "type": "string" + }, + { + "const": "ellipsis-end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How truncate (or wrap) lines of text longer than the given **lineWidth**; one of:\n\n- null (default) - preserve overflowing characters (and wrap if needed)\n- *clip* or *clip-end* - remove characters from the end\n- *clip-start* - remove characters from the start\n- *ellipsis* or *ellipsis-end* - replace characters from the end with an ellipsis (…)\n- *ellipsis-start* - replace characters from the start with an ellipsis (…)\n- *ellipsis-middle* - replace characters from the middle with an ellipsis (…)\n\nIf no **title** was specified, if text requires truncation, a title containing the non-truncated text will be implicitly added." + }, + "textPadding": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The padding around the text in pixels; defaults to 8." + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + } + }, + "type": "object" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to generate a tooltip for this mark, and any tip options." + }, + "title": { + "$ref": "#/definitions/ChannelValue", + "description": "The title; a channel specifying accessible, short textual descriptions as strings (possibly with newlines). If the tip option is specified, the title will be displayed with an interactive tooltip instead of using the SVG [title element][1].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/title" + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The independent variable horizontal position channel, typically bound to the *x* scale; defaults to the zero-based index of the data [0, 1, 2, …]." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The dependent variable vertical position channel, typically bound to the\n*y* scale; defaults to identity, assuming that *data* = [*y₀*, *y₁*, *y₂*, …]." + }, + "z": { + "$ref": "#/definitions/ChannelValue", + "description": "An optional ordinal channel for grouping data into (possibly stacked) series, producing an independent regression for each group. If not specified, it defaults to **fill** if a channel, or **stroke** if a channel." + } + }, + "required": [ + "data", + "mark" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "$schema": { + "description": "A [JSON schema](http://json-schema.org/) URL for this specification, such as https://uwdata.github.io/mosaic/schema/latest.json. This property enables validation and autocomplete in editors with JSON schema support.", + "format": "uri", + "type": "string" + }, + "ariaDescription": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-description][1]; a constant textual description.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-description" + }, + "ariaHidden": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-hidden][1] state; a constant indicating whether the element is exposed to an accessibility API.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-hidden" + }, + "ariaLabel": { + "$ref": "#/definitions/ChannelValue", + "description": "The [aria-label][1]; a channel specifying short textual labels representing the value in the accessibility tree.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-label" + }, + "clip": { + "anyOf": [ + { + "const": "frame", + "type": "string" + }, + { + "const": "sphere", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to clip the mark; one of:\n\n- *frame* or true - clip to the plot’s frame (inner area)\n- *sphere* - clip to the projected sphere (*e.g.*, front hemisphere)\n- null or false - do not clip\n\nThe *sphere* clip option requires a geographic projection." + }, + "config": { + "$ref": "#/definitions/Config", + "description": "Configuration options." + }, + "data": { + "$ref": "#/definitions/Data", + "description": "Dataset definitions." + }, + "dx": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The horizontal offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "dy": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The vertical offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "facet": { + "anyOf": [ + { + "const": "auto", + "type": "string" + }, + { + "const": "include", + "type": "string" + }, + { + "const": "exclude", + "type": "string" + }, + { + "const": "super", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to enable or disable faceting; one of:\n\n- *auto* (default) - automatically determine if this mark should be faceted\n- *include* (or true) - draw the subset of the mark’s data in the current facet\n- *exclude* - draw the subset of the mark’s data *not* in the current facet\n- *super* - draw this mark in a single frame that covers all facets\n- null (or false) - repeat this mark’s data across all facets (*i.e.*, no faceting)\n\nWhen a mark uses *super* faceting, it is not allowed to use position scales (*x*, *y*, *fx*, or *fy*); *super* faceting is intended for decorations, such as labels and legends.\n\nWhen top-level faceting is used, the default *auto* setting is equivalent to *include* when the mark data is strictly equal to the top-level facet data; otherwise it is equivalent to null. When the *include* or *exclude* facet mode is chosen, the mark data must be parallel to the top-level facet data: the data must have the same length and order. If the data are not parallel, then the wrong data may be shown in each facet. The default\n*auto* therefore requires strict equality (`===`) for safety, and using the facet data as mark data is recommended when using the *exclude* facet mode. (To construct parallel data safely, consider using [*array*.map][1] on the facet data.)\n\nWhen mark-level faceting is used, the default *auto* setting is equivalent to *include*: the mark will be faceted if either the **fx** or **fy** channel option (or both) is specified. The null or false option will disable faceting, while *exclude* draws the subset of the mark’s data *not* in the current facet.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map" + }, + "facetAnchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "right", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "const": "left", + "type": "string" + }, + { + "const": "top-left", + "type": "string" + }, + { + "const": "top-right", + "type": "string" + }, + { + "const": "bottom-left", + "type": "string" + }, + { + "const": "bottom-right", + "type": "string" + }, + { + "const": "top-empty", + "type": "string" + }, + { + "const": "right-empty", + "type": "string" + }, + { + "const": "bottom-empty", + "type": "string" + }, + { + "const": "left-empty", + "type": "string" + }, + { + "const": "empty", + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to place the mark with respect to facets; one of:\n\n- null (default for most marks) - display the mark in each non-empty facet\n- *top*, *right*, *bottom*, or *left* - display the mark only in facets on the given side\n- *top-empty*, *right-empty*, *bottom-empty*, or *left-empty* (default for axis marks) - display the mark only in facets that have empty space on the given side: either the margin, or an empty facet\n- *empty* - display the mark in empty facets only" + }, + "fill": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill" + }, + "fillOpacity": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill-opacity][1]; a constant number between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill-opacity" + }, + "filter": { + "$ref": "#/definitions/ChannelValue", + "description": "Applies a transform to filter the mark’s index according to the given channel values; only truthy values are retained.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "fx": { + "$ref": "#/definitions/ChannelValue", + "description": "The horizontal facet position channel, for mark-level faceting, bound to the *fx* scale." + }, + "fy": { + "$ref": "#/definitions/ChannelValue", + "description": "The vertical facet position channel, for mark-level faceting, bound to the\n*fy* scale." + }, + "href": { + "$ref": "#/definitions/ChannelValue", + "description": "The [href][1]; a channel specifying URLs for clickable links. May be used in conjunction with the **target** option to open links in another window.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/href" + }, + "imageFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A CSS [filter][1]; a constant string used to adjust the rendering of images, such as *blur(5px)*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/filter" + }, + "inset": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four insets: **insetTop**,\n**insetRight**, **insetBottom**, and **insetLeft**. All insets typically default to zero, though not always (say when using bin transform). A positive inset reduces effective area, while a negative inset increases it." + }, + "insetBottom": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Insets the bottom edge by the specified number of pixels. A positive value insets towards the top edge (reducing effective area), while a negative value insets away from the top edge (increasing it)." + }, + "insetTop": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Insets the top edge by the specified number of pixels. A positive value insets towards the bottom edge (reducing effective area), while a negative value insets away from the bottom edge (increasing it)." + }, + "interval": { + "anyOf": [ + { + "$ref": "#/definitions/Interval" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to convert a continuous value (**y** for ruleX, or **x** for ruleY) into an interval (**y1** and **y2** for ruleX, or **x1** and **x2** for ruleY); one of:\n\n- a named time interval such as *day* (for date intervals)\n- a number (for number intervals), defining intervals at integer multiples of *n*" + }, + "margin": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four mark margins: **marginTop**,\n**marginRight**, **marginBottom**, and **marginLeft**; typically defaults to 0, except for axis marks." + }, + "marginBottom": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s bottom margin; the minimum distance in pixels between the bottom edges of the inner and outer plot area." + }, + "marginLeft": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s left margin; the minimum distance in pixels between the left edges of the inner and outer plot area." + }, + "marginRight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s right margin; the minimum distance in pixels between the right edges of the mark’s inner and outer plot area." + }, + "marginTop": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s top margin; the minimum distance in pixels between the top edges of the inner and outer plot area." + }, + "mark": { + "const": "ruleX", + "description": "A horizontally-positioned ruleX mark (a vertical line, |). The **x** channel specifies the rule’s horizontal position and defaults to identity, assuming that *data* = [*x₀*, *x₁*, *x₂*, …]; the optional **y1** and\n**y2** channels specify its vertical extent.\n\nThe ruleX mark is often used to highlight specific *x* values. If *y* represents ordinal values, use a tickX mark instead.", + "type": "string" + }, + "marker": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for markerStart, markerMid, and markerEnd; one of:\n\n- a marker name such as *arrow* or *circle*\n- *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*" + }, + "markerEnd": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The marker for the ending point of a line segment; one of:\n\n- a marker name such as *arrow* or *circle*\n* *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*" + }, + "markerMid": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The marker for any middle (interior) points of a line segment. If the line segment only has a start and end point, this option has no effect. One of:\n\n- a marker name such as *arrow* or *circle*\n* *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*\n* a function - a custom marker function; see below" + }, + "markerStart": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The marker for the starting point of a line segment; one of:\n\n- a marker name such as *arrow* or *circle*\n* *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*" + }, + "meta": { + "$ref": "#/definitions/Meta", + "description": "Specification metadata." + }, + "mixBlendMode": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [mix-blend-mode][1]; a constant string specifying how to blend content such as *multiply*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode" + }, + "opacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally. For faster rendering, prefer the **strokeOpacity** or **fillOpacity** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/opacity" + }, + "paintOrder": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [paint-order][1]; a constant string specifying the order in which the\n**fill**, **stroke**, and any markers are drawn; defaults to *normal*, which draws the fill, then stroke, then markers; defaults to *stroke* for the text mark to create a “halo” around text to improve legibility.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/paint-order" + }, + "params": { + "$ref": "#/definitions/Params", + "description": "Param and Selection definitions." + }, + "plotDefaults": { + "$ref": "#/definitions/PlotAttributes", + "description": "A default set of attributes to apply to all plot components." + }, + "pointerEvents": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [pointer-events][1] property; a constant string such as *none*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/pointer-events" + }, + "reverse": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Applies a transform to reverse the order of the mark’s index, say for reverse input order." + }, + "select": { + "$ref": "#/definitions/SelectFilter", + "description": "Applies a filter transform after data is loaded to highlight selected values only. For example, `first` and `last` select the first or last values of series only (using the *z* channel to separate series). Meanwhile, `nearestX` and `nearestY` select the point nearest to the pointer along the *x* or *y* channel dimension. Unlike Mosaic selections, a mark level *select* is internal to the mark only, and does not populate a param or selection value to be shared across clients.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "shapeRendering": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [shape-rendering][1]; a constant string such as *crispEdges*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/shape-rendering" + }, + "sort": { + "anyOf": [ + { + "$ref": "#/definitions/SortOrder" + }, + { + "$ref": "#/definitions/ChannelDomainSort" + } + ], + "description": "Either applies a transform to sort the mark’s index by the specified channel values, or imputes ordinal scale domains from this mark’s channels.\n\nWhen imputing ordinal scale domains from channel values, the **sort** option is an object whose keys are ordinal scale names such as *x* or *fx*, and whose values are channel names such as *y*, *y1*, or *y2*. For example, to impute the *y* scale’s domain from the associated *x* channel values in ascending order:\n\n```js sort: {y: \"x\"} ```\n\nFor different sort options for different scales, replace the channel name with a *value* object and per-scale options:\n\n```js sort: {y: {value: \"-x\"}} ```\n\nWhen sorting the mark’s index, the **sort** option is instead one of:\n\n- a channel value definition for sorting given values in ascending order\n- a {value, order} object for sorting given values\n- a {channel, order} object for sorting the named channel’s values" + }, + "stroke": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke" + }, + "strokeDasharray": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dasharray][1]; a constant number indicating the length in pixels of alternating dashes and gaps, or a constant string of numbers separated by spaces or commas (_e.g._, *10 2* for dashes of 10 pixels separated by gaps of 2 pixels), or *none* (the default) for no dashing\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dasharray" + }, + "strokeDashoffset": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dashoffset][1]; a constant indicating the offset in pixels of the first dash along the stroke; defaults to zero.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dashoffset" + }, + "strokeLinecap": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linecap][1]; a constant specifying how to cap stroked paths, such as *butt*, *round*, or *square*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linecap" + }, + "strokeLinejoin": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linejoin][1]; a constant specifying how to join stroked paths, such as *bevel*, *miter*, *miter-clip*, or *round*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linejoin" + }, + "strokeMiterlimit": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-miterlimit][1]; a constant number specifying how to limit the length of *miter* joins on stroked paths.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-miterlimit" + }, + "strokeOpacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-opacity" + }, + "strokeWidth": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-width][1]; a constant number in pixels, or a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-width" + }, + "target": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [target][1]; a constant string specifying the target window (_e.g._,\n*_blank*) for clickable links; used in conjunction with the **href** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/target" + }, + "tip": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/TipPointer" + }, + { + "properties": { + "anchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The tip anchor specifies how to orient the tip box relative to its anchor position; it refers to the part of the tip box that is attached to the anchor point. For example, the *top-left* anchor places the top-left corner of tip box near the anchor position, hence placing the tip box below and to the right of the anchor position." + }, + "fontFamily": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font-family][1]; a constant; defaults to the plot’s font family, which is typically [*system-ui*][2].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-family [2]: https://drafts.csswg.org/css-fonts-4/#valdef-font-family-system-ui" + }, + "fontSize": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font size][1] in pixels; either a constant or a channel; defaults to the plot’s font size, which is typically 10. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-size" + }, + "fontStyle": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font style][1]; a constant; defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-style" + }, + "fontVariant": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font variant][1]; a constant; if the **text** channel contains numbers or dates, defaults to *tabular-nums* to facilitate comparing numbers; otherwise defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant" + }, + "fontWeight": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font weight][1]; a constant; defaults to the plot’s font weight, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight" + }, + "format": { + "additionalProperties": false, + "description": "How channel values are formatted for display. If a format is a string, it is interpreted as a (UTC) time format for temporal channels, and otherwise a number format.", + "properties": { + "ariaLabel": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fill": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fillOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fontSize": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fx": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fy": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "geometry": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "height": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "href": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "length": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "opacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "path": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "r": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "rotate": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "src": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "stroke": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeWidth": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "symbol": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "text": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "title": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "weight": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "width": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "z": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + } + }, + "type": "object" + }, + "frameAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The frame anchor specifies defaults for **x** and **y** based on the plot’s frame; it may be one of the four sides (*top*, *right*, *bottom*, *left*), one of the four corners (*top-left*, *top-right*, *bottom-right*,\n*bottom-left*), or the *middle* of the frame. For example, for tips distributed horizontally at the top of the frame:\n\n```js Plot.tip(data, {x: \"date\", frameAnchor: \"top\"}) ```" + }, + "lineHeight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line height in ems; defaults to 1. The line height affects the (typically vertical) separation between adjacent baselines of text, as well as the separation between the text and its anchor point." + }, + "lineWidth": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line width in ems (e.g., 10 for about 20 characters); defaults to infinity, disabling wrapping and clipping.\n\nIf **textOverflow** is null, lines will be wrapped at the specified length. If a line is split at a soft hyphen (\\xad), a hyphen (-) will be displayed at the end of the line. If **textOverflow** is not null, lines will be clipped according to the given strategy." + }, + "monospace": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, changes the default **fontFamily** to *monospace*, and uses simplified monospaced text metrics calculations." + }, + "pathFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The image filter for the tip’s box; defaults to a drop shadow." + }, + "pointer": { + "$ref": "#/definitions/TipPointer" + }, + "pointerSize": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The size of the tip’s pointer in pixels; defaults to 12." + }, + "preferredAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If an explicit tip anchor is not specified, an anchor is chosen automatically such that the tip fits within the plot’s frame; if the preferred anchor fits, it is chosen." + }, + "textAnchor": { + "anyOf": [ + { + "const": "start", + "type": "string" + }, + { + "const": "middle", + "type": "string" + }, + { + "const": "end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [text anchor][1] controls how text is aligned (typically horizontally) relative to its anchor point; it is one of *start*, *end*, or *middle*. If the frame anchor is *left*, *top-left*, or *bottom-left*, the default text anchor is *start*; if the frame anchor is *right*, *top-right*, or\n*bottom-right*, the default is *end*; otherwise it is *middle*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/text-anchor" + }, + "textOverflow": { + "anyOf": [ + { + "type": "null" + }, + { + "const": "clip", + "type": "string" + }, + { + "const": "ellipsis", + "type": "string" + }, + { + "const": "clip-start", + "type": "string" + }, + { + "const": "clip-end", + "type": "string" + }, + { + "const": "ellipsis-start", + "type": "string" + }, + { + "const": "ellipsis-middle", + "type": "string" + }, + { + "const": "ellipsis-end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How truncate (or wrap) lines of text longer than the given **lineWidth**; one of:\n\n- null (default) - preserve overflowing characters (and wrap if needed)\n- *clip* or *clip-end* - remove characters from the end\n- *clip-start* - remove characters from the start\n- *ellipsis* or *ellipsis-end* - replace characters from the end with an ellipsis (…)\n- *ellipsis-start* - replace characters from the start with an ellipsis (…)\n- *ellipsis-middle* - replace characters from the middle with an ellipsis (…)\n\nIf no **title** was specified, if text requires truncation, a title containing the non-truncated text will be implicitly added." + }, + "textPadding": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The padding around the text in pixels; defaults to 8." + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + } + }, + "type": "object" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to generate a tooltip for this mark, and any tip options." + }, + "title": { + "$ref": "#/definitions/ChannelValue", + "description": "The title; a channel specifying accessible, short textual descriptions as strings (possibly with newlines). If the tip option is specified, the title will be displayed with an interactive tooltip instead of using the SVG [title element][1].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/title" + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position of the tick; an optional channel bound to the *x* scale. If not specified, the rule will be horizontally centered in the plot’s frame." + }, + "y": { + "$ref": "#/definitions/ChannelValueIntervalSpec", + "description": "Shorthand for specifying both the primary and secondary vertical position of the tick as the bounds of the containing interval; can only be used in conjunction with the **interval** option." + }, + "y1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The primary (starting, often bottom) vertical position of the tick; a channel bound to the *y* scale.\n\nIf *y* represents ordinal values, use a tickX mark instead." + }, + "y2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The secondary (ending, often top) vertical position of the tick; a channel bound to the *y* scale.\n\nIf *y* represents ordinal values, use a tickX mark instead." + } + }, + "required": [ + "mark" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "$schema": { + "description": "A [JSON schema](http://json-schema.org/) URL for this specification, such as https://uwdata.github.io/mosaic/schema/latest.json. This property enables validation and autocomplete in editors with JSON schema support.", + "format": "uri", + "type": "string" + }, + "ariaDescription": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-description][1]; a constant textual description.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-description" + }, + "ariaHidden": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-hidden][1] state; a constant indicating whether the element is exposed to an accessibility API.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-hidden" + }, + "ariaLabel": { + "$ref": "#/definitions/ChannelValue", + "description": "The [aria-label][1]; a channel specifying short textual labels representing the value in the accessibility tree.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-label" + }, + "clip": { + "anyOf": [ + { + "const": "frame", + "type": "string" + }, + { + "const": "sphere", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to clip the mark; one of:\n\n- *frame* or true - clip to the plot’s frame (inner area)\n- *sphere* - clip to the projected sphere (*e.g.*, front hemisphere)\n- null or false - do not clip\n\nThe *sphere* clip option requires a geographic projection." + }, + "config": { + "$ref": "#/definitions/Config", + "description": "Configuration options." + }, + "data": { + "$ref": "#/definitions/Data", + "description": "Dataset definitions." + }, + "dx": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The horizontal offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "dy": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The vertical offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "facet": { + "anyOf": [ + { + "const": "auto", + "type": "string" + }, + { + "const": "include", + "type": "string" + }, + { + "const": "exclude", + "type": "string" + }, + { + "const": "super", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to enable or disable faceting; one of:\n\n- *auto* (default) - automatically determine if this mark should be faceted\n- *include* (or true) - draw the subset of the mark’s data in the current facet\n- *exclude* - draw the subset of the mark’s data *not* in the current facet\n- *super* - draw this mark in a single frame that covers all facets\n- null (or false) - repeat this mark’s data across all facets (*i.e.*, no faceting)\n\nWhen a mark uses *super* faceting, it is not allowed to use position scales (*x*, *y*, *fx*, or *fy*); *super* faceting is intended for decorations, such as labels and legends.\n\nWhen top-level faceting is used, the default *auto* setting is equivalent to *include* when the mark data is strictly equal to the top-level facet data; otherwise it is equivalent to null. When the *include* or *exclude* facet mode is chosen, the mark data must be parallel to the top-level facet data: the data must have the same length and order. If the data are not parallel, then the wrong data may be shown in each facet. The default\n*auto* therefore requires strict equality (`===`) for safety, and using the facet data as mark data is recommended when using the *exclude* facet mode. (To construct parallel data safely, consider using [*array*.map][1] on the facet data.)\n\nWhen mark-level faceting is used, the default *auto* setting is equivalent to *include*: the mark will be faceted if either the **fx** or **fy** channel option (or both) is specified. The null or false option will disable faceting, while *exclude* draws the subset of the mark’s data *not* in the current facet.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map" + }, + "facetAnchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "right", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "const": "left", + "type": "string" + }, + { + "const": "top-left", + "type": "string" + }, + { + "const": "top-right", + "type": "string" + }, + { + "const": "bottom-left", + "type": "string" + }, + { + "const": "bottom-right", + "type": "string" + }, + { + "const": "top-empty", + "type": "string" + }, + { + "const": "right-empty", + "type": "string" + }, + { + "const": "bottom-empty", + "type": "string" + }, + { + "const": "left-empty", + "type": "string" + }, + { + "const": "empty", + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to place the mark with respect to facets; one of:\n\n- null (default for most marks) - display the mark in each non-empty facet\n- *top*, *right*, *bottom*, or *left* - display the mark only in facets on the given side\n- *top-empty*, *right-empty*, *bottom-empty*, or *left-empty* (default for axis marks) - display the mark only in facets that have empty space on the given side: either the margin, or an empty facet\n- *empty* - display the mark in empty facets only" + }, + "fill": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill" + }, + "fillOpacity": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill-opacity][1]; a constant number between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill-opacity" + }, + "filter": { + "$ref": "#/definitions/ChannelValue", + "description": "Applies a transform to filter the mark’s index according to the given channel values; only truthy values are retained.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "fx": { + "$ref": "#/definitions/ChannelValue", + "description": "The horizontal facet position channel, for mark-level faceting, bound to the *fx* scale." + }, + "fy": { + "$ref": "#/definitions/ChannelValue", + "description": "The vertical facet position channel, for mark-level faceting, bound to the\n*fy* scale." + }, + "href": { + "$ref": "#/definitions/ChannelValue", + "description": "The [href][1]; a channel specifying URLs for clickable links. May be used in conjunction with the **target** option to open links in another window.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/href" + }, + "imageFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A CSS [filter][1]; a constant string used to adjust the rendering of images, such as *blur(5px)*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/filter" + }, + "inset": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four insets: **insetTop**,\n**insetRight**, **insetBottom**, and **insetLeft**. All insets typically default to zero, though not always (say when using bin transform). A positive inset reduces effective area, while a negative inset increases it." + }, + "insetBottom": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Insets the bottom edge by the specified number of pixels. A positive value insets towards the top edge (reducing effective area), while a negative value insets away from the top edge (increasing it)." + }, + "insetTop": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Insets the top edge by the specified number of pixels. A positive value insets towards the bottom edge (reducing effective area), while a negative value insets away from the bottom edge (increasing it)." + }, + "interval": { + "anyOf": [ + { + "$ref": "#/definitions/Interval" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to convert a continuous value (**y** for ruleX, or **x** for ruleY) into an interval (**y1** and **y2** for ruleX, or **x1** and **x2** for ruleY); one of:\n\n- a named time interval such as *day* (for date intervals)\n- a number (for number intervals), defining intervals at integer multiples of *n*" + }, + "margin": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four mark margins: **marginTop**,\n**marginRight**, **marginBottom**, and **marginLeft**; typically defaults to 0, except for axis marks." + }, + "marginBottom": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s bottom margin; the minimum distance in pixels between the bottom edges of the inner and outer plot area." + }, + "marginLeft": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s left margin; the minimum distance in pixels between the left edges of the inner and outer plot area." + }, + "marginRight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s right margin; the minimum distance in pixels between the right edges of the mark’s inner and outer plot area." + }, + "marginTop": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s top margin; the minimum distance in pixels between the top edges of the inner and outer plot area." + }, + "mark": { + "const": "ruleY", + "description": "A vertically-positioned ruleY mark (a horizontal line, —). The **y** channel specifies the rule's vertical position and defaults to identity, assuming that *data* = [*y₀*, *y₁*, *y₂*, …]; the optional **x1** and\n**x2** channels specify its horizontal extent.\n\nThe ruleY mark is often used to highlight specific *y* values. If *x* represents ordinal values, use a tickY mark instead.", + "type": "string" + }, + "marker": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for markerStart, markerMid, and markerEnd; one of:\n\n- a marker name such as *arrow* or *circle*\n- *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*" + }, + "markerEnd": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The marker for the ending point of a line segment; one of:\n\n- a marker name such as *arrow* or *circle*\n* *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*" + }, + "markerMid": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The marker for any middle (interior) points of a line segment. If the line segment only has a start and end point, this option has no effect. One of:\n\n- a marker name such as *arrow* or *circle*\n* *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*\n* a function - a custom marker function; see below" + }, + "markerStart": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The marker for the starting point of a line segment; one of:\n\n- a marker name such as *arrow* or *circle*\n* *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*" + }, + "meta": { + "$ref": "#/definitions/Meta", + "description": "Specification metadata." + }, + "mixBlendMode": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [mix-blend-mode][1]; a constant string specifying how to blend content such as *multiply*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode" + }, + "opacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally. For faster rendering, prefer the **strokeOpacity** or **fillOpacity** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/opacity" + }, + "paintOrder": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [paint-order][1]; a constant string specifying the order in which the\n**fill**, **stroke**, and any markers are drawn; defaults to *normal*, which draws the fill, then stroke, then markers; defaults to *stroke* for the text mark to create a “halo” around text to improve legibility.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/paint-order" + }, + "params": { + "$ref": "#/definitions/Params", + "description": "Param and Selection definitions." + }, + "plotDefaults": { + "$ref": "#/definitions/PlotAttributes", + "description": "A default set of attributes to apply to all plot components." + }, + "pointerEvents": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [pointer-events][1] property; a constant string such as *none*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/pointer-events" + }, + "reverse": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Applies a transform to reverse the order of the mark’s index, say for reverse input order." + }, + "select": { + "$ref": "#/definitions/SelectFilter", + "description": "Applies a filter transform after data is loaded to highlight selected values only. For example, `first` and `last` select the first or last values of series only (using the *z* channel to separate series). Meanwhile, `nearestX` and `nearestY` select the point nearest to the pointer along the *x* or *y* channel dimension. Unlike Mosaic selections, a mark level *select* is internal to the mark only, and does not populate a param or selection value to be shared across clients.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "shapeRendering": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [shape-rendering][1]; a constant string such as *crispEdges*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/shape-rendering" + }, + "sort": { + "anyOf": [ + { + "$ref": "#/definitions/SortOrder" + }, + { + "$ref": "#/definitions/ChannelDomainSort" + } + ], + "description": "Either applies a transform to sort the mark’s index by the specified channel values, or imputes ordinal scale domains from this mark’s channels.\n\nWhen imputing ordinal scale domains from channel values, the **sort** option is an object whose keys are ordinal scale names such as *x* or *fx*, and whose values are channel names such as *y*, *y1*, or *y2*. For example, to impute the *y* scale’s domain from the associated *x* channel values in ascending order:\n\n```js sort: {y: \"x\"} ```\n\nFor different sort options for different scales, replace the channel name with a *value* object and per-scale options:\n\n```js sort: {y: {value: \"-x\"}} ```\n\nWhen sorting the mark’s index, the **sort** option is instead one of:\n\n- a channel value definition for sorting given values in ascending order\n- a {value, order} object for sorting given values\n- a {channel, order} object for sorting the named channel’s values" + }, + "stroke": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke" + }, + "strokeDasharray": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dasharray][1]; a constant number indicating the length in pixels of alternating dashes and gaps, or a constant string of numbers separated by spaces or commas (_e.g._, *10 2* for dashes of 10 pixels separated by gaps of 2 pixels), or *none* (the default) for no dashing\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dasharray" + }, + "strokeDashoffset": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dashoffset][1]; a constant indicating the offset in pixels of the first dash along the stroke; defaults to zero.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dashoffset" + }, + "strokeLinecap": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linecap][1]; a constant specifying how to cap stroked paths, such as *butt*, *round*, or *square*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linecap" + }, + "strokeLinejoin": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linejoin][1]; a constant specifying how to join stroked paths, such as *bevel*, *miter*, *miter-clip*, or *round*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linejoin" + }, + "strokeMiterlimit": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-miterlimit][1]; a constant number specifying how to limit the length of *miter* joins on stroked paths.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-miterlimit" + }, + "strokeOpacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-opacity" + }, + "strokeWidth": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-width][1]; a constant number in pixels, or a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-width" + }, + "target": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [target][1]; a constant string specifying the target window (_e.g._,\n*_blank*) for clickable links; used in conjunction with the **href** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/target" + }, + "tip": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/TipPointer" + }, + { + "properties": { + "anchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The tip anchor specifies how to orient the tip box relative to its anchor position; it refers to the part of the tip box that is attached to the anchor point. For example, the *top-left* anchor places the top-left corner of tip box near the anchor position, hence placing the tip box below and to the right of the anchor position." + }, + "fontFamily": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font-family][1]; a constant; defaults to the plot’s font family, which is typically [*system-ui*][2].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-family [2]: https://drafts.csswg.org/css-fonts-4/#valdef-font-family-system-ui" + }, + "fontSize": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font size][1] in pixels; either a constant or a channel; defaults to the plot’s font size, which is typically 10. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-size" + }, + "fontStyle": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font style][1]; a constant; defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-style" + }, + "fontVariant": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font variant][1]; a constant; if the **text** channel contains numbers or dates, defaults to *tabular-nums* to facilitate comparing numbers; otherwise defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant" + }, + "fontWeight": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font weight][1]; a constant; defaults to the plot’s font weight, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight" + }, + "format": { + "additionalProperties": false, + "description": "How channel values are formatted for display. If a format is a string, it is interpreted as a (UTC) time format for temporal channels, and otherwise a number format.", + "properties": { + "ariaLabel": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fill": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fillOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fontSize": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fx": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fy": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "geometry": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "height": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "href": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "length": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "opacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "path": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "r": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "rotate": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "src": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "stroke": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeWidth": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "symbol": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "text": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "title": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "weight": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "width": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "z": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + } + }, + "type": "object" + }, + "frameAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The frame anchor specifies defaults for **x** and **y** based on the plot’s frame; it may be one of the four sides (*top*, *right*, *bottom*, *left*), one of the four corners (*top-left*, *top-right*, *bottom-right*,\n*bottom-left*), or the *middle* of the frame. For example, for tips distributed horizontally at the top of the frame:\n\n```js Plot.tip(data, {x: \"date\", frameAnchor: \"top\"}) ```" + }, + "lineHeight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line height in ems; defaults to 1. The line height affects the (typically vertical) separation between adjacent baselines of text, as well as the separation between the text and its anchor point." + }, + "lineWidth": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line width in ems (e.g., 10 for about 20 characters); defaults to infinity, disabling wrapping and clipping.\n\nIf **textOverflow** is null, lines will be wrapped at the specified length. If a line is split at a soft hyphen (\\xad), a hyphen (-) will be displayed at the end of the line. If **textOverflow** is not null, lines will be clipped according to the given strategy." + }, + "monospace": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, changes the default **fontFamily** to *monospace*, and uses simplified monospaced text metrics calculations." + }, + "pathFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The image filter for the tip’s box; defaults to a drop shadow." + }, + "pointer": { + "$ref": "#/definitions/TipPointer" + }, + "pointerSize": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The size of the tip’s pointer in pixels; defaults to 12." + }, + "preferredAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If an explicit tip anchor is not specified, an anchor is chosen automatically such that the tip fits within the plot’s frame; if the preferred anchor fits, it is chosen." + }, + "textAnchor": { + "anyOf": [ + { + "const": "start", + "type": "string" + }, + { + "const": "middle", + "type": "string" + }, + { + "const": "end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [text anchor][1] controls how text is aligned (typically horizontally) relative to its anchor point; it is one of *start*, *end*, or *middle*. If the frame anchor is *left*, *top-left*, or *bottom-left*, the default text anchor is *start*; if the frame anchor is *right*, *top-right*, or\n*bottom-right*, the default is *end*; otherwise it is *middle*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/text-anchor" + }, + "textOverflow": { + "anyOf": [ + { + "type": "null" + }, + { + "const": "clip", + "type": "string" + }, + { + "const": "ellipsis", + "type": "string" + }, + { + "const": "clip-start", + "type": "string" + }, + { + "const": "clip-end", + "type": "string" + }, + { + "const": "ellipsis-start", + "type": "string" + }, + { + "const": "ellipsis-middle", + "type": "string" + }, + { + "const": "ellipsis-end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How truncate (or wrap) lines of text longer than the given **lineWidth**; one of:\n\n- null (default) - preserve overflowing characters (and wrap if needed)\n- *clip* or *clip-end* - remove characters from the end\n- *clip-start* - remove characters from the start\n- *ellipsis* or *ellipsis-end* - replace characters from the end with an ellipsis (…)\n- *ellipsis-start* - replace characters from the start with an ellipsis (…)\n- *ellipsis-middle* - replace characters from the middle with an ellipsis (…)\n\nIf no **title** was specified, if text requires truncation, a title containing the non-truncated text will be implicitly added." + }, + "textPadding": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The padding around the text in pixels; defaults to 8." + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + } + }, + "type": "object" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to generate a tooltip for this mark, and any tip options." + }, + "title": { + "$ref": "#/definitions/ChannelValue", + "description": "The title; a channel specifying accessible, short textual descriptions as strings (possibly with newlines). If the tip option is specified, the title will be displayed with an interactive tooltip instead of using the SVG [title element][1].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/title" + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position of the tick; an optional channel bound to the *x* scale. If not specified, the rule will be horizontally centered in the plot’s frame." + }, + "y": { + "$ref": "#/definitions/ChannelValueIntervalSpec", + "description": "Shorthand for specifying both the primary and secondary vertical position of the tick as the bounds of the containing interval; can only be used in conjunction with the **interval** option." + }, + "y1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The primary (starting, often bottom) vertical position of the tick; a channel bound to the *y* scale.\n\nIf *y* represents ordinal values, use a tickX mark instead." + }, + "y2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The secondary (ending, often top) vertical position of the tick; a channel bound to the *y* scale.\n\nIf *y* represents ordinal values, use a tickX mark instead." + } + }, + "required": [ + "mark" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "$schema": { + "description": "A [JSON schema](http://json-schema.org/) URL for this specification, such as https://uwdata.github.io/mosaic/schema/latest.json. This property enables validation and autocomplete in editors with JSON schema support.", + "format": "uri", + "type": "string" + }, + "ariaDescription": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-description][1]; a constant textual description.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-description" + }, + "ariaHidden": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-hidden][1] state; a constant indicating whether the element is exposed to an accessibility API.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-hidden" + }, + "ariaLabel": { + "$ref": "#/definitions/ChannelValue", + "description": "The [aria-label][1]; a channel specifying short textual labels representing the value in the accessibility tree.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-label" + }, + "clip": { + "anyOf": [ + { + "const": "frame", + "type": "string" + }, + { + "const": "sphere", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to clip the mark; one of:\n\n- *frame* or true - clip to the plot’s frame (inner area)\n- *sphere* - clip to the projected sphere (*e.g.*, front hemisphere)\n- null or false - do not clip\n\nThe *sphere* clip option requires a geographic projection." + }, + "config": { + "$ref": "#/definitions/Config", + "description": "Configuration options." + }, + "data": { + "$ref": "#/definitions/Data", + "description": "Dataset definitions." + }, + "dx": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The horizontal offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "dy": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The vertical offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "facet": { + "anyOf": [ + { + "const": "auto", + "type": "string" + }, + { + "const": "include", + "type": "string" + }, + { + "const": "exclude", + "type": "string" + }, + { + "const": "super", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to enable or disable faceting; one of:\n\n- *auto* (default) - automatically determine if this mark should be faceted\n- *include* (or true) - draw the subset of the mark’s data in the current facet\n- *exclude* - draw the subset of the mark’s data *not* in the current facet\n- *super* - draw this mark in a single frame that covers all facets\n- null (or false) - repeat this mark’s data across all facets (*i.e.*, no faceting)\n\nWhen a mark uses *super* faceting, it is not allowed to use position scales (*x*, *y*, *fx*, or *fy*); *super* faceting is intended for decorations, such as labels and legends.\n\nWhen top-level faceting is used, the default *auto* setting is equivalent to *include* when the mark data is strictly equal to the top-level facet data; otherwise it is equivalent to null. When the *include* or *exclude* facet mode is chosen, the mark data must be parallel to the top-level facet data: the data must have the same length and order. If the data are not parallel, then the wrong data may be shown in each facet. The default\n*auto* therefore requires strict equality (`===`) for safety, and using the facet data as mark data is recommended when using the *exclude* facet mode. (To construct parallel data safely, consider using [*array*.map][1] on the facet data.)\n\nWhen mark-level faceting is used, the default *auto* setting is equivalent to *include*: the mark will be faceted if either the **fx** or **fy** channel option (or both) is specified. The null or false option will disable faceting, while *exclude* draws the subset of the mark’s data *not* in the current facet.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map" + }, + "facetAnchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "right", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "const": "left", + "type": "string" + }, + { + "const": "top-left", + "type": "string" + }, + { + "const": "top-right", + "type": "string" + }, + { + "const": "bottom-left", + "type": "string" + }, + { + "const": "bottom-right", + "type": "string" + }, + { + "const": "top-empty", + "type": "string" + }, + { + "const": "right-empty", + "type": "string" + }, + { + "const": "bottom-empty", + "type": "string" + }, + { + "const": "left-empty", + "type": "string" + }, + { + "const": "empty", + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to place the mark with respect to facets; one of:\n\n- null (default for most marks) - display the mark in each non-empty facet\n- *top*, *right*, *bottom*, or *left* - display the mark only in facets on the given side\n- *top-empty*, *right-empty*, *bottom-empty*, or *left-empty* (default for axis marks) - display the mark only in facets that have empty space on the given side: either the margin, or an empty facet\n- *empty* - display the mark in empty facets only" + }, + "fill": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill" + }, + "fillOpacity": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill-opacity][1]; a constant number between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill-opacity" + }, + "filter": { + "$ref": "#/definitions/ChannelValue", + "description": "Applies a transform to filter the mark’s index according to the given channel values; only truthy values are retained.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "fontFamily": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font-family][1]; a constant; defaults to the plot’s font family, which is typically [*system-ui*][2].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-family [2]: https://drafts.csswg.org/css-fonts-4/#valdef-font-family-system-ui" + }, + "fontSize": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font size][1] in pixels; either a constant or a channel; defaults to the plot’s font size, which is typically 10. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-size" + }, + "fontStyle": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font style][1]; a constant; defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-style" + }, + "fontVariant": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font variant][1]; a constant; if the **text** channel contains numbers or dates, defaults to *tabular-nums* to facilitate comparing numbers; otherwise defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant" + }, + "fontWeight": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font weight][1]; a constant; defaults to the plot’s font weight, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight" + }, + "frameAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The frame anchor specifies defaults for **x** and **y**, along with\n**textAnchor** and **lineAnchor**, based on the plot’s frame; it may be one of the four sides (*top*, *right*, *bottom*, *left*), one of the four corners (*top-left*, *top-right*, *bottom-right*, *bottom-left*), or the\n*middle* of the frame." + }, + "fx": { + "$ref": "#/definitions/ChannelValue", + "description": "The horizontal facet position channel, for mark-level faceting, bound to the *fx* scale." + }, + "fy": { + "$ref": "#/definitions/ChannelValue", + "description": "The vertical facet position channel, for mark-level faceting, bound to the\n*fy* scale." + }, + "href": { + "$ref": "#/definitions/ChannelValue", + "description": "The [href][1]; a channel specifying URLs for clickable links. May be used in conjunction with the **target** option to open links in another window.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/href" + }, + "imageFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A CSS [filter][1]; a constant string used to adjust the rendering of images, such as *blur(5px)*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/filter" + }, + "lineAnchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "middle", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line anchor controls how text is aligned (typically vertically) relative to its anchor point; it is one of *top*, *bottom*, or *middle*. If the frame anchor is *top*, *top-left*, or *top-right*, the default line anchor is *top*; if the frame anchor is *bottom*, *bottom-right*, or\n*bottom-left*, the default is *bottom*; otherwise it is *middle*." + }, + "lineHeight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line height in ems; defaults to 1. The line height affects the (typically vertical) separation between adjacent baselines of text, as well as the separation between the text and its anchor point." + }, + "lineWidth": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line width in ems (e.g., 10 for about 20 characters); defaults to infinity, disabling wrapping and clipping.\n\nIf **textOverflow** is null, lines will be wrapped at the specified length. If a line is split at a soft hyphen (\\xad), a hyphen (-) will be displayed at the end of the line. If **textOverflow** is not null, lines will be clipped according to the given strategy." + }, + "margin": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four mark margins: **marginTop**,\n**marginRight**, **marginBottom**, and **marginLeft**; typically defaults to 0, except for axis marks." + }, + "marginBottom": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s bottom margin; the minimum distance in pixels between the bottom edges of the inner and outer plot area." + }, + "marginLeft": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s left margin; the minimum distance in pixels between the left edges of the inner and outer plot area." + }, + "marginRight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s right margin; the minimum distance in pixels between the right edges of the mark’s inner and outer plot area." + }, + "marginTop": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s top margin; the minimum distance in pixels between the top edges of the inner and outer plot area." + }, + "mark": { + "const": "text", + "description": "A text mark. The **text** channel specifies the textual contents of the mark, which may be preformatted with line breaks (\\n, \\r\\n, or \\r), or wrapped or clipped using the **lineWidth** and **textOverflow** options.\n\nIf **text** contains numbers or dates, a default formatter will be applied, and the **fontVariant** will default to *tabular-nums* instead of *normal*. If **text** is not specified, it defaults to the identity function for primitive data (such as numbers, dates, and strings), and to the zero-based index [0, 1, 2, …] for objects (so that something identifying is visible by default).\n\nIf either **x** or **y** is not specified, the default is determined by the **frameAnchor** option.", + "type": "string" + }, + "meta": { + "$ref": "#/definitions/Meta", + "description": "Specification metadata." + }, + "mixBlendMode": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [mix-blend-mode][1]; a constant string specifying how to blend content such as *multiply*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode" + }, + "monospace": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, changes the default **fontFamily** to *monospace*, and uses simplified monospaced text metrics calculations." + }, + "opacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally. For faster rendering, prefer the **strokeOpacity** or **fillOpacity** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/opacity" + }, + "paintOrder": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [paint-order][1]; a constant string specifying the order in which the\n**fill**, **stroke**, and any markers are drawn; defaults to *normal*, which draws the fill, then stroke, then markers; defaults to *stroke* for the text mark to create a “halo” around text to improve legibility.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/paint-order" + }, + "params": { + "$ref": "#/definitions/Params", + "description": "Param and Selection definitions." + }, + "plotDefaults": { + "$ref": "#/definitions/PlotAttributes", + "description": "A default set of attributes to apply to all plot components." + }, + "pointerEvents": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [pointer-events][1] property; a constant string such as *none*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/pointer-events" + }, + "reverse": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Applies a transform to reverse the order of the mark’s index, say for reverse input order." + }, + "rotate": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The rotation angle in degrees clockwise; a constant or a channel; defaults to 0°. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel." + }, + "select": { + "$ref": "#/definitions/SelectFilter", + "description": "Applies a filter transform after data is loaded to highlight selected values only. For example, `first` and `last` select the first or last values of series only (using the *z* channel to separate series). Meanwhile, `nearestX` and `nearestY` select the point nearest to the pointer along the *x* or *y* channel dimension. Unlike Mosaic selections, a mark level *select* is internal to the mark only, and does not populate a param or selection value to be shared across clients.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "shapeRendering": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [shape-rendering][1]; a constant string such as *crispEdges*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/shape-rendering" + }, + "sort": { + "anyOf": [ + { + "$ref": "#/definitions/SortOrder" + }, + { + "$ref": "#/definitions/ChannelDomainSort" + } + ], + "description": "Either applies a transform to sort the mark’s index by the specified channel values, or imputes ordinal scale domains from this mark’s channels.\n\nWhen imputing ordinal scale domains from channel values, the **sort** option is an object whose keys are ordinal scale names such as *x* or *fx*, and whose values are channel names such as *y*, *y1*, or *y2*. For example, to impute the *y* scale’s domain from the associated *x* channel values in ascending order:\n\n```js sort: {y: \"x\"} ```\n\nFor different sort options for different scales, replace the channel name with a *value* object and per-scale options:\n\n```js sort: {y: {value: \"-x\"}} ```\n\nWhen sorting the mark’s index, the **sort** option is instead one of:\n\n- a channel value definition for sorting given values in ascending order\n- a {value, order} object for sorting given values\n- a {channel, order} object for sorting the named channel’s values" + }, + "stroke": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke" + }, + "strokeDasharray": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dasharray][1]; a constant number indicating the length in pixels of alternating dashes and gaps, or a constant string of numbers separated by spaces or commas (_e.g._, *10 2* for dashes of 10 pixels separated by gaps of 2 pixels), or *none* (the default) for no dashing\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dasharray" + }, + "strokeDashoffset": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dashoffset][1]; a constant indicating the offset in pixels of the first dash along the stroke; defaults to zero.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dashoffset" + }, + "strokeLinecap": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linecap][1]; a constant specifying how to cap stroked paths, such as *butt*, *round*, or *square*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linecap" + }, + "strokeLinejoin": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linejoin][1]; a constant specifying how to join stroked paths, such as *bevel*, *miter*, *miter-clip*, or *round*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linejoin" + }, + "strokeMiterlimit": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-miterlimit][1]; a constant number specifying how to limit the length of *miter* joins on stroked paths.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-miterlimit" + }, + "strokeOpacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-opacity" + }, + "strokeWidth": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-width][1]; a constant number in pixels, or a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-width" + }, + "target": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [target][1]; a constant string specifying the target window (_e.g._,\n*_blank*) for clickable links; used in conjunction with the **href** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/target" + }, + "text": { + "$ref": "#/definitions/ChannelValue", + "description": "The text contents channel, possibly with line breaks (\\n, \\r\\n, or \\r). If not specified, defaults to the zero-based index [0, 1, 2, …]." + }, + "textAnchor": { + "anyOf": [ + { + "const": "start", + "type": "string" + }, + { + "const": "middle", + "type": "string" + }, + { + "const": "end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [text anchor][1] controls how text is aligned (typically horizontally) relative to its anchor point; it is one of *start*, *end*, or *middle*. If the frame anchor is *left*, *top-left*, or *bottom-left*, the default text anchor is *start*; if the frame anchor is *right*, *top-right*, or\n*bottom-right*, the default is *end*; otherwise it is *middle*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/text-anchor" + }, + "textOverflow": { + "anyOf": [ + { + "type": "null" + }, + { + "const": "clip", + "type": "string" + }, + { + "const": "ellipsis", + "type": "string" + }, + { + "const": "clip-start", + "type": "string" + }, + { + "const": "clip-end", + "type": "string" + }, + { + "const": "ellipsis-start", + "type": "string" + }, + { + "const": "ellipsis-middle", + "type": "string" + }, + { + "const": "ellipsis-end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How truncate (or wrap) lines of text longer than the given **lineWidth**; one of:\n\n- null (default) - preserve overflowing characters (and wrap if needed)\n- *clip* or *clip-end* - remove characters from the end\n- *clip-start* - remove characters from the start\n- *ellipsis* or *ellipsis-end* - replace characters from the end with an ellipsis (…)\n- *ellipsis-start* - replace characters from the start with an ellipsis (…)\n- *ellipsis-middle* - replace characters from the middle with an ellipsis (…)\n\nIf no **title** was specified, if text requires truncation, a title containing the non-truncated text will be implicitly added." + }, + "tip": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/TipPointer" + }, + { + "properties": { + "anchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The tip anchor specifies how to orient the tip box relative to its anchor position; it refers to the part of the tip box that is attached to the anchor point. For example, the *top-left* anchor places the top-left corner of tip box near the anchor position, hence placing the tip box below and to the right of the anchor position." + }, + "fontFamily": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font-family][1]; a constant; defaults to the plot’s font family, which is typically [*system-ui*][2].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-family [2]: https://drafts.csswg.org/css-fonts-4/#valdef-font-family-system-ui" + }, + "fontSize": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font size][1] in pixels; either a constant or a channel; defaults to the plot’s font size, which is typically 10. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-size" + }, + "fontStyle": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font style][1]; a constant; defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-style" + }, + "fontVariant": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font variant][1]; a constant; if the **text** channel contains numbers or dates, defaults to *tabular-nums* to facilitate comparing numbers; otherwise defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant" + }, + "fontWeight": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font weight][1]; a constant; defaults to the plot’s font weight, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight" + }, + "format": { + "additionalProperties": false, + "description": "How channel values are formatted for display. If a format is a string, it is interpreted as a (UTC) time format for temporal channels, and otherwise a number format.", + "properties": { + "ariaLabel": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fill": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fillOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fontSize": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fx": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fy": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "geometry": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "height": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "href": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "length": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "opacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "path": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "r": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "rotate": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "src": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "stroke": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeWidth": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "symbol": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "text": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "title": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "weight": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "width": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "z": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + } + }, + "type": "object" + }, + "frameAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The frame anchor specifies defaults for **x** and **y** based on the plot’s frame; it may be one of the four sides (*top*, *right*, *bottom*, *left*), one of the four corners (*top-left*, *top-right*, *bottom-right*,\n*bottom-left*), or the *middle* of the frame. For example, for tips distributed horizontally at the top of the frame:\n\n```js Plot.tip(data, {x: \"date\", frameAnchor: \"top\"}) ```" + }, + "lineHeight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line height in ems; defaults to 1. The line height affects the (typically vertical) separation between adjacent baselines of text, as well as the separation between the text and its anchor point." + }, + "lineWidth": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line width in ems (e.g., 10 for about 20 characters); defaults to infinity, disabling wrapping and clipping.\n\nIf **textOverflow** is null, lines will be wrapped at the specified length. If a line is split at a soft hyphen (\\xad), a hyphen (-) will be displayed at the end of the line. If **textOverflow** is not null, lines will be clipped according to the given strategy." + }, + "monospace": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, changes the default **fontFamily** to *monospace*, and uses simplified monospaced text metrics calculations." + }, + "pathFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The image filter for the tip’s box; defaults to a drop shadow." + }, + "pointer": { + "$ref": "#/definitions/TipPointer" + }, + "pointerSize": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The size of the tip’s pointer in pixels; defaults to 12." + }, + "preferredAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If an explicit tip anchor is not specified, an anchor is chosen automatically such that the tip fits within the plot’s frame; if the preferred anchor fits, it is chosen." + }, + "textAnchor": { + "anyOf": [ + { + "const": "start", + "type": "string" + }, + { + "const": "middle", + "type": "string" + }, + { + "const": "end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [text anchor][1] controls how text is aligned (typically horizontally) relative to its anchor point; it is one of *start*, *end*, or *middle*. If the frame anchor is *left*, *top-left*, or *bottom-left*, the default text anchor is *start*; if the frame anchor is *right*, *top-right*, or\n*bottom-right*, the default is *end*; otherwise it is *middle*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/text-anchor" + }, + "textOverflow": { + "anyOf": [ + { + "type": "null" + }, + { + "const": "clip", + "type": "string" + }, + { + "const": "ellipsis", + "type": "string" + }, + { + "const": "clip-start", + "type": "string" + }, + { + "const": "clip-end", + "type": "string" + }, + { + "const": "ellipsis-start", + "type": "string" + }, + { + "const": "ellipsis-middle", + "type": "string" + }, + { + "const": "ellipsis-end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How truncate (or wrap) lines of text longer than the given **lineWidth**; one of:\n\n- null (default) - preserve overflowing characters (and wrap if needed)\n- *clip* or *clip-end* - remove characters from the end\n- *clip-start* - remove characters from the start\n- *ellipsis* or *ellipsis-end* - replace characters from the end with an ellipsis (…)\n- *ellipsis-start* - replace characters from the start with an ellipsis (…)\n- *ellipsis-middle* - replace characters from the middle with an ellipsis (…)\n\nIf no **title** was specified, if text requires truncation, a title containing the non-truncated text will be implicitly added." + }, + "textPadding": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The padding around the text in pixels; defaults to 8." + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + } + }, + "type": "object" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to generate a tooltip for this mark, and any tip options." + }, + "title": { + "$ref": "#/definitions/ChannelValue", + "description": "The title; a channel specifying accessible, short textual descriptions as strings (possibly with newlines). If the tip option is specified, the title will be displayed with an interactive tooltip instead of using the SVG [title element][1].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/title" + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel specifying the text’s anchor point, typically bound to the *x* scale." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel specifying the text’s anchor point, typically bound to the *y* scale." + }, + "z": { + "$ref": "#/definitions/ChannelValue", + "description": "An optional ordinal channel for grouping data into series." + } + }, + "required": [ + "mark" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "$schema": { + "description": "A [JSON schema](http://json-schema.org/) URL for this specification, such as https://uwdata.github.io/mosaic/schema/latest.json. This property enables validation and autocomplete in editors with JSON schema support.", + "format": "uri", + "type": "string" + }, + "ariaDescription": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-description][1]; a constant textual description.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-description" + }, + "ariaHidden": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-hidden][1] state; a constant indicating whether the element is exposed to an accessibility API.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-hidden" + }, + "ariaLabel": { + "$ref": "#/definitions/ChannelValue", + "description": "The [aria-label][1]; a channel specifying short textual labels representing the value in the accessibility tree.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-label" + }, + "clip": { + "anyOf": [ + { + "const": "frame", + "type": "string" + }, + { + "const": "sphere", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to clip the mark; one of:\n\n- *frame* or true - clip to the plot’s frame (inner area)\n- *sphere* - clip to the projected sphere (*e.g.*, front hemisphere)\n- null or false - do not clip\n\nThe *sphere* clip option requires a geographic projection." + }, + "config": { + "$ref": "#/definitions/Config", + "description": "Configuration options." + }, + "data": { + "$ref": "#/definitions/Data", + "description": "Dataset definitions." + }, + "dx": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The horizontal offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "dy": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The vertical offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "facet": { + "anyOf": [ + { + "const": "auto", + "type": "string" + }, + { + "const": "include", + "type": "string" + }, + { + "const": "exclude", + "type": "string" + }, + { + "const": "super", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to enable or disable faceting; one of:\n\n- *auto* (default) - automatically determine if this mark should be faceted\n- *include* (or true) - draw the subset of the mark’s data in the current facet\n- *exclude* - draw the subset of the mark’s data *not* in the current facet\n- *super* - draw this mark in a single frame that covers all facets\n- null (or false) - repeat this mark’s data across all facets (*i.e.*, no faceting)\n\nWhen a mark uses *super* faceting, it is not allowed to use position scales (*x*, *y*, *fx*, or *fy*); *super* faceting is intended for decorations, such as labels and legends.\n\nWhen top-level faceting is used, the default *auto* setting is equivalent to *include* when the mark data is strictly equal to the top-level facet data; otherwise it is equivalent to null. When the *include* or *exclude* facet mode is chosen, the mark data must be parallel to the top-level facet data: the data must have the same length and order. If the data are not parallel, then the wrong data may be shown in each facet. The default\n*auto* therefore requires strict equality (`===`) for safety, and using the facet data as mark data is recommended when using the *exclude* facet mode. (To construct parallel data safely, consider using [*array*.map][1] on the facet data.)\n\nWhen mark-level faceting is used, the default *auto* setting is equivalent to *include*: the mark will be faceted if either the **fx** or **fy** channel option (or both) is specified. The null or false option will disable faceting, while *exclude* draws the subset of the mark’s data *not* in the current facet.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map" + }, + "facetAnchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "right", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "const": "left", + "type": "string" + }, + { + "const": "top-left", + "type": "string" + }, + { + "const": "top-right", + "type": "string" + }, + { + "const": "bottom-left", + "type": "string" + }, + { + "const": "bottom-right", + "type": "string" + }, + { + "const": "top-empty", + "type": "string" + }, + { + "const": "right-empty", + "type": "string" + }, + { + "const": "bottom-empty", + "type": "string" + }, + { + "const": "left-empty", + "type": "string" + }, + { + "const": "empty", + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to place the mark with respect to facets; one of:\n\n- null (default for most marks) - display the mark in each non-empty facet\n- *top*, *right*, *bottom*, or *left* - display the mark only in facets on the given side\n- *top-empty*, *right-empty*, *bottom-empty*, or *left-empty* (default for axis marks) - display the mark only in facets that have empty space on the given side: either the margin, or an empty facet\n- *empty* - display the mark in empty facets only" + }, + "fill": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill" + }, + "fillOpacity": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill-opacity][1]; a constant number between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill-opacity" + }, + "filter": { + "$ref": "#/definitions/ChannelValue", + "description": "Applies a transform to filter the mark’s index according to the given channel values; only truthy values are retained.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "fontFamily": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font-family][1]; a constant; defaults to the plot’s font family, which is typically [*system-ui*][2].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-family [2]: https://drafts.csswg.org/css-fonts-4/#valdef-font-family-system-ui" + }, + "fontSize": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font size][1] in pixels; either a constant or a channel; defaults to the plot’s font size, which is typically 10. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-size" + }, + "fontStyle": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font style][1]; a constant; defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-style" + }, + "fontVariant": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font variant][1]; a constant; if the **text** channel contains numbers or dates, defaults to *tabular-nums* to facilitate comparing numbers; otherwise defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant" + }, + "fontWeight": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font weight][1]; a constant; defaults to the plot’s font weight, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight" + }, + "frameAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The frame anchor specifies defaults for **x** and **y**, along with\n**textAnchor** and **lineAnchor**, based on the plot’s frame; it may be one of the four sides (*top*, *right*, *bottom*, *left*), one of the four corners (*top-left*, *top-right*, *bottom-right*, *bottom-left*), or the\n*middle* of the frame." + }, + "fx": { + "$ref": "#/definitions/ChannelValue", + "description": "The horizontal facet position channel, for mark-level faceting, bound to the *fx* scale." + }, + "fy": { + "$ref": "#/definitions/ChannelValue", + "description": "The vertical facet position channel, for mark-level faceting, bound to the\n*fy* scale." + }, + "href": { + "$ref": "#/definitions/ChannelValue", + "description": "The [href][1]; a channel specifying URLs for clickable links. May be used in conjunction with the **target** option to open links in another window.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/href" + }, + "imageFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A CSS [filter][1]; a constant string used to adjust the rendering of images, such as *blur(5px)*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/filter" + }, + "interval": { + "anyOf": [ + { + "$ref": "#/definitions/Interval" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "An interval (such as *day* or a number), to transform **y** values to the middle of the interval." + }, + "lineAnchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "middle", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line anchor controls how text is aligned (typically vertically) relative to its anchor point; it is one of *top*, *bottom*, or *middle*. If the frame anchor is *top*, *top-left*, or *top-right*, the default line anchor is *top*; if the frame anchor is *bottom*, *bottom-right*, or\n*bottom-left*, the default is *bottom*; otherwise it is *middle*." + }, + "lineHeight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line height in ems; defaults to 1. The line height affects the (typically vertical) separation between adjacent baselines of text, as well as the separation between the text and its anchor point." + }, + "lineWidth": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line width in ems (e.g., 10 for about 20 characters); defaults to infinity, disabling wrapping and clipping.\n\nIf **textOverflow** is null, lines will be wrapped at the specified length. If a line is split at a soft hyphen (\\xad), a hyphen (-) will be displayed at the end of the line. If **textOverflow** is not null, lines will be clipped according to the given strategy." + }, + "margin": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four mark margins: **marginTop**,\n**marginRight**, **marginBottom**, and **marginLeft**; typically defaults to 0, except for axis marks." + }, + "marginBottom": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s bottom margin; the minimum distance in pixels between the bottom edges of the inner and outer plot area." + }, + "marginLeft": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s left margin; the minimum distance in pixels between the left edges of the inner and outer plot area." + }, + "marginRight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s right margin; the minimum distance in pixels between the right edges of the mark’s inner and outer plot area." + }, + "marginTop": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s top margin; the minimum distance in pixels between the top edges of the inner and outer plot area." + }, + "mark": { + "const": "textX", + "description": "Like text, but **x** defaults to the identity function, assuming that\n*data* = [*x₀*, *x₁*, *x₂*, …]. If an **interval** is specified, such as\n*day*, **y** is transformed to the middle of the interval.", + "type": "string" + }, + "meta": { + "$ref": "#/definitions/Meta", + "description": "Specification metadata." + }, + "mixBlendMode": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [mix-blend-mode][1]; a constant string specifying how to blend content such as *multiply*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode" + }, + "monospace": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, changes the default **fontFamily** to *monospace*, and uses simplified monospaced text metrics calculations." + }, + "opacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally. For faster rendering, prefer the **strokeOpacity** or **fillOpacity** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/opacity" + }, + "paintOrder": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [paint-order][1]; a constant string specifying the order in which the\n**fill**, **stroke**, and any markers are drawn; defaults to *normal*, which draws the fill, then stroke, then markers; defaults to *stroke* for the text mark to create a “halo” around text to improve legibility.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/paint-order" + }, + "params": { + "$ref": "#/definitions/Params", + "description": "Param and Selection definitions." + }, + "plotDefaults": { + "$ref": "#/definitions/PlotAttributes", + "description": "A default set of attributes to apply to all plot components." + }, + "pointerEvents": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [pointer-events][1] property; a constant string such as *none*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/pointer-events" + }, + "reverse": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Applies a transform to reverse the order of the mark’s index, say for reverse input order." + }, + "rotate": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The rotation angle in degrees clockwise; a constant or a channel; defaults to 0°. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel." + }, + "select": { + "$ref": "#/definitions/SelectFilter", + "description": "Applies a filter transform after data is loaded to highlight selected values only. For example, `first` and `last` select the first or last values of series only (using the *z* channel to separate series). Meanwhile, `nearestX` and `nearestY` select the point nearest to the pointer along the *x* or *y* channel dimension. Unlike Mosaic selections, a mark level *select* is internal to the mark only, and does not populate a param or selection value to be shared across clients.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "shapeRendering": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [shape-rendering][1]; a constant string such as *crispEdges*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/shape-rendering" + }, + "sort": { + "anyOf": [ + { + "$ref": "#/definitions/SortOrder" + }, + { + "$ref": "#/definitions/ChannelDomainSort" + } + ], + "description": "Either applies a transform to sort the mark’s index by the specified channel values, or imputes ordinal scale domains from this mark’s channels.\n\nWhen imputing ordinal scale domains from channel values, the **sort** option is an object whose keys are ordinal scale names such as *x* or *fx*, and whose values are channel names such as *y*, *y1*, or *y2*. For example, to impute the *y* scale’s domain from the associated *x* channel values in ascending order:\n\n```js sort: {y: \"x\"} ```\n\nFor different sort options for different scales, replace the channel name with a *value* object and per-scale options:\n\n```js sort: {y: {value: \"-x\"}} ```\n\nWhen sorting the mark’s index, the **sort** option is instead one of:\n\n- a channel value definition for sorting given values in ascending order\n- a {value, order} object for sorting given values\n- a {channel, order} object for sorting the named channel’s values" + }, + "stroke": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke" + }, + "strokeDasharray": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dasharray][1]; a constant number indicating the length in pixels of alternating dashes and gaps, or a constant string of numbers separated by spaces or commas (_e.g._, *10 2* for dashes of 10 pixels separated by gaps of 2 pixels), or *none* (the default) for no dashing\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dasharray" + }, + "strokeDashoffset": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dashoffset][1]; a constant indicating the offset in pixels of the first dash along the stroke; defaults to zero.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dashoffset" + }, + "strokeLinecap": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linecap][1]; a constant specifying how to cap stroked paths, such as *butt*, *round*, or *square*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linecap" + }, + "strokeLinejoin": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linejoin][1]; a constant specifying how to join stroked paths, such as *bevel*, *miter*, *miter-clip*, or *round*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linejoin" + }, + "strokeMiterlimit": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-miterlimit][1]; a constant number specifying how to limit the length of *miter* joins on stroked paths.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-miterlimit" + }, + "strokeOpacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-opacity" + }, + "strokeWidth": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-width][1]; a constant number in pixels, or a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-width" + }, + "target": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [target][1]; a constant string specifying the target window (_e.g._,\n*_blank*) for clickable links; used in conjunction with the **href** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/target" + }, + "text": { + "$ref": "#/definitions/ChannelValue", + "description": "The text contents channel, possibly with line breaks (\\n, \\r\\n, or \\r). If not specified, defaults to the zero-based index [0, 1, 2, …]." + }, + "textAnchor": { + "anyOf": [ + { + "const": "start", + "type": "string" + }, + { + "const": "middle", + "type": "string" + }, + { + "const": "end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [text anchor][1] controls how text is aligned (typically horizontally) relative to its anchor point; it is one of *start*, *end*, or *middle*. If the frame anchor is *left*, *top-left*, or *bottom-left*, the default text anchor is *start*; if the frame anchor is *right*, *top-right*, or\n*bottom-right*, the default is *end*; otherwise it is *middle*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/text-anchor" + }, + "textOverflow": { + "anyOf": [ + { + "type": "null" + }, + { + "const": "clip", + "type": "string" + }, + { + "const": "ellipsis", + "type": "string" + }, + { + "const": "clip-start", + "type": "string" + }, + { + "const": "clip-end", + "type": "string" + }, + { + "const": "ellipsis-start", + "type": "string" + }, + { + "const": "ellipsis-middle", + "type": "string" + }, + { + "const": "ellipsis-end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How truncate (or wrap) lines of text longer than the given **lineWidth**; one of:\n\n- null (default) - preserve overflowing characters (and wrap if needed)\n- *clip* or *clip-end* - remove characters from the end\n- *clip-start* - remove characters from the start\n- *ellipsis* or *ellipsis-end* - replace characters from the end with an ellipsis (…)\n- *ellipsis-start* - replace characters from the start with an ellipsis (…)\n- *ellipsis-middle* - replace characters from the middle with an ellipsis (…)\n\nIf no **title** was specified, if text requires truncation, a title containing the non-truncated text will be implicitly added." + }, + "tip": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/TipPointer" + }, + { + "properties": { + "anchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The tip anchor specifies how to orient the tip box relative to its anchor position; it refers to the part of the tip box that is attached to the anchor point. For example, the *top-left* anchor places the top-left corner of tip box near the anchor position, hence placing the tip box below and to the right of the anchor position." + }, + "fontFamily": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font-family][1]; a constant; defaults to the plot’s font family, which is typically [*system-ui*][2].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-family [2]: https://drafts.csswg.org/css-fonts-4/#valdef-font-family-system-ui" + }, + "fontSize": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font size][1] in pixels; either a constant or a channel; defaults to the plot’s font size, which is typically 10. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-size" + }, + "fontStyle": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font style][1]; a constant; defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-style" + }, + "fontVariant": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font variant][1]; a constant; if the **text** channel contains numbers or dates, defaults to *tabular-nums* to facilitate comparing numbers; otherwise defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant" + }, + "fontWeight": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font weight][1]; a constant; defaults to the plot’s font weight, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight" + }, + "format": { + "additionalProperties": false, + "description": "How channel values are formatted for display. If a format is a string, it is interpreted as a (UTC) time format for temporal channels, and otherwise a number format.", + "properties": { + "ariaLabel": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fill": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fillOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fontSize": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fx": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fy": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "geometry": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "height": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "href": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "length": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "opacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "path": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "r": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "rotate": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "src": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "stroke": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeWidth": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "symbol": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "text": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "title": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "weight": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "width": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "z": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + } + }, + "type": "object" + }, + "frameAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The frame anchor specifies defaults for **x** and **y** based on the plot’s frame; it may be one of the four sides (*top*, *right*, *bottom*, *left*), one of the four corners (*top-left*, *top-right*, *bottom-right*,\n*bottom-left*), or the *middle* of the frame. For example, for tips distributed horizontally at the top of the frame:\n\n```js Plot.tip(data, {x: \"date\", frameAnchor: \"top\"}) ```" + }, + "lineHeight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line height in ems; defaults to 1. The line height affects the (typically vertical) separation between adjacent baselines of text, as well as the separation between the text and its anchor point." + }, + "lineWidth": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line width in ems (e.g., 10 for about 20 characters); defaults to infinity, disabling wrapping and clipping.\n\nIf **textOverflow** is null, lines will be wrapped at the specified length. If a line is split at a soft hyphen (\\xad), a hyphen (-) will be displayed at the end of the line. If **textOverflow** is not null, lines will be clipped according to the given strategy." + }, + "monospace": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, changes the default **fontFamily** to *monospace*, and uses simplified monospaced text metrics calculations." + }, + "pathFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The image filter for the tip’s box; defaults to a drop shadow." + }, + "pointer": { + "$ref": "#/definitions/TipPointer" + }, + "pointerSize": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The size of the tip’s pointer in pixels; defaults to 12." + }, + "preferredAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If an explicit tip anchor is not specified, an anchor is chosen automatically such that the tip fits within the plot’s frame; if the preferred anchor fits, it is chosen." + }, + "textAnchor": { + "anyOf": [ + { + "const": "start", + "type": "string" + }, + { + "const": "middle", + "type": "string" + }, + { + "const": "end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [text anchor][1] controls how text is aligned (typically horizontally) relative to its anchor point; it is one of *start*, *end*, or *middle*. If the frame anchor is *left*, *top-left*, or *bottom-left*, the default text anchor is *start*; if the frame anchor is *right*, *top-right*, or\n*bottom-right*, the default is *end*; otherwise it is *middle*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/text-anchor" + }, + "textOverflow": { + "anyOf": [ + { + "type": "null" + }, + { + "const": "clip", + "type": "string" + }, + { + "const": "ellipsis", + "type": "string" + }, + { + "const": "clip-start", + "type": "string" + }, + { + "const": "clip-end", + "type": "string" + }, + { + "const": "ellipsis-start", + "type": "string" + }, + { + "const": "ellipsis-middle", + "type": "string" + }, + { + "const": "ellipsis-end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How truncate (or wrap) lines of text longer than the given **lineWidth**; one of:\n\n- null (default) - preserve overflowing characters (and wrap if needed)\n- *clip* or *clip-end* - remove characters from the end\n- *clip-start* - remove characters from the start\n- *ellipsis* or *ellipsis-end* - replace characters from the end with an ellipsis (…)\n- *ellipsis-start* - replace characters from the start with an ellipsis (…)\n- *ellipsis-middle* - replace characters from the middle with an ellipsis (…)\n\nIf no **title** was specified, if text requires truncation, a title containing the non-truncated text will be implicitly added." + }, + "textPadding": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The padding around the text in pixels; defaults to 8." + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + } + }, + "type": "object" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to generate a tooltip for this mark, and any tip options." + }, + "title": { + "$ref": "#/definitions/ChannelValue", + "description": "The title; a channel specifying accessible, short textual descriptions as strings (possibly with newlines). If the tip option is specified, the title will be displayed with an interactive tooltip instead of using the SVG [title element][1].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/title" + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel specifying the text’s anchor point, typically bound to the *x* scale." + }, + "y": { + "$ref": "#/definitions/ChannelValueIntervalSpec", + "description": "The vertical position of the text’s anchor point, typically bound to the\n*y* scale." + }, + "z": { + "$ref": "#/definitions/ChannelValue", + "description": "An optional ordinal channel for grouping data into series." + } + }, + "required": [ + "mark" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "$schema": { + "description": "A [JSON schema](http://json-schema.org/) URL for this specification, such as https://uwdata.github.io/mosaic/schema/latest.json. This property enables validation and autocomplete in editors with JSON schema support.", + "format": "uri", + "type": "string" + }, + "ariaDescription": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-description][1]; a constant textual description.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-description" + }, + "ariaHidden": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-hidden][1] state; a constant indicating whether the element is exposed to an accessibility API.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-hidden" + }, + "ariaLabel": { + "$ref": "#/definitions/ChannelValue", + "description": "The [aria-label][1]; a channel specifying short textual labels representing the value in the accessibility tree.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-label" + }, + "clip": { + "anyOf": [ + { + "const": "frame", + "type": "string" + }, + { + "const": "sphere", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to clip the mark; one of:\n\n- *frame* or true - clip to the plot’s frame (inner area)\n- *sphere* - clip to the projected sphere (*e.g.*, front hemisphere)\n- null or false - do not clip\n\nThe *sphere* clip option requires a geographic projection." + }, + "config": { + "$ref": "#/definitions/Config", + "description": "Configuration options." + }, + "data": { + "$ref": "#/definitions/Data", + "description": "Dataset definitions." + }, + "dx": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The horizontal offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "dy": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The vertical offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "facet": { + "anyOf": [ + { + "const": "auto", + "type": "string" + }, + { + "const": "include", + "type": "string" + }, + { + "const": "exclude", + "type": "string" + }, + { + "const": "super", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to enable or disable faceting; one of:\n\n- *auto* (default) - automatically determine if this mark should be faceted\n- *include* (or true) - draw the subset of the mark’s data in the current facet\n- *exclude* - draw the subset of the mark’s data *not* in the current facet\n- *super* - draw this mark in a single frame that covers all facets\n- null (or false) - repeat this mark’s data across all facets (*i.e.*, no faceting)\n\nWhen a mark uses *super* faceting, it is not allowed to use position scales (*x*, *y*, *fx*, or *fy*); *super* faceting is intended for decorations, such as labels and legends.\n\nWhen top-level faceting is used, the default *auto* setting is equivalent to *include* when the mark data is strictly equal to the top-level facet data; otherwise it is equivalent to null. When the *include* or *exclude* facet mode is chosen, the mark data must be parallel to the top-level facet data: the data must have the same length and order. If the data are not parallel, then the wrong data may be shown in each facet. The default\n*auto* therefore requires strict equality (`===`) for safety, and using the facet data as mark data is recommended when using the *exclude* facet mode. (To construct parallel data safely, consider using [*array*.map][1] on the facet data.)\n\nWhen mark-level faceting is used, the default *auto* setting is equivalent to *include*: the mark will be faceted if either the **fx** or **fy** channel option (or both) is specified. The null or false option will disable faceting, while *exclude* draws the subset of the mark’s data *not* in the current facet.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map" + }, + "facetAnchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "right", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "const": "left", + "type": "string" + }, + { + "const": "top-left", + "type": "string" + }, + { + "const": "top-right", + "type": "string" + }, + { + "const": "bottom-left", + "type": "string" + }, + { + "const": "bottom-right", + "type": "string" + }, + { + "const": "top-empty", + "type": "string" + }, + { + "const": "right-empty", + "type": "string" + }, + { + "const": "bottom-empty", + "type": "string" + }, + { + "const": "left-empty", + "type": "string" + }, + { + "const": "empty", + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to place the mark with respect to facets; one of:\n\n- null (default for most marks) - display the mark in each non-empty facet\n- *top*, *right*, *bottom*, or *left* - display the mark only in facets on the given side\n- *top-empty*, *right-empty*, *bottom-empty*, or *left-empty* (default for axis marks) - display the mark only in facets that have empty space on the given side: either the margin, or an empty facet\n- *empty* - display the mark in empty facets only" + }, + "fill": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill" + }, + "fillOpacity": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill-opacity][1]; a constant number between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill-opacity" + }, + "filter": { + "$ref": "#/definitions/ChannelValue", + "description": "Applies a transform to filter the mark’s index according to the given channel values; only truthy values are retained.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "fontFamily": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font-family][1]; a constant; defaults to the plot’s font family, which is typically [*system-ui*][2].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-family [2]: https://drafts.csswg.org/css-fonts-4/#valdef-font-family-system-ui" + }, + "fontSize": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font size][1] in pixels; either a constant or a channel; defaults to the plot’s font size, which is typically 10. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-size" + }, + "fontStyle": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font style][1]; a constant; defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-style" + }, + "fontVariant": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font variant][1]; a constant; if the **text** channel contains numbers or dates, defaults to *tabular-nums* to facilitate comparing numbers; otherwise defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant" + }, + "fontWeight": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font weight][1]; a constant; defaults to the plot’s font weight, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight" + }, + "frameAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The frame anchor specifies defaults for **x** and **y**, along with\n**textAnchor** and **lineAnchor**, based on the plot’s frame; it may be one of the four sides (*top*, *right*, *bottom*, *left*), one of the four corners (*top-left*, *top-right*, *bottom-right*, *bottom-left*), or the\n*middle* of the frame." + }, + "fx": { + "$ref": "#/definitions/ChannelValue", + "description": "The horizontal facet position channel, for mark-level faceting, bound to the *fx* scale." + }, + "fy": { + "$ref": "#/definitions/ChannelValue", + "description": "The vertical facet position channel, for mark-level faceting, bound to the\n*fy* scale." + }, + "href": { + "$ref": "#/definitions/ChannelValue", + "description": "The [href][1]; a channel specifying URLs for clickable links. May be used in conjunction with the **target** option to open links in another window.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/href" + }, + "imageFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A CSS [filter][1]; a constant string used to adjust the rendering of images, such as *blur(5px)*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/filter" + }, + "interval": { + "$ref": "#/definitions/Interval", + "description": "An interval (such as *day* or a number), to transform **x** values to the middle of the interval." + }, + "lineAnchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "middle", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line anchor controls how text is aligned (typically vertically) relative to its anchor point; it is one of *top*, *bottom*, or *middle*. If the frame anchor is *top*, *top-left*, or *top-right*, the default line anchor is *top*; if the frame anchor is *bottom*, *bottom-right*, or\n*bottom-left*, the default is *bottom*; otherwise it is *middle*." + }, + "lineHeight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line height in ems; defaults to 1. The line height affects the (typically vertical) separation between adjacent baselines of text, as well as the separation between the text and its anchor point." + }, + "lineWidth": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line width in ems (e.g., 10 for about 20 characters); defaults to infinity, disabling wrapping and clipping.\n\nIf **textOverflow** is null, lines will be wrapped at the specified length. If a line is split at a soft hyphen (\\xad), a hyphen (-) will be displayed at the end of the line. If **textOverflow** is not null, lines will be clipped according to the given strategy." + }, + "margin": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four mark margins: **marginTop**,\n**marginRight**, **marginBottom**, and **marginLeft**; typically defaults to 0, except for axis marks." + }, + "marginBottom": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s bottom margin; the minimum distance in pixels between the bottom edges of the inner and outer plot area." + }, + "marginLeft": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s left margin; the minimum distance in pixels between the left edges of the inner and outer plot area." + }, + "marginRight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s right margin; the minimum distance in pixels between the right edges of the mark’s inner and outer plot area." + }, + "marginTop": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s top margin; the minimum distance in pixels between the top edges of the inner and outer plot area." + }, + "mark": { + "const": "textY", + "description": "Like text, but **y** defaults to the identity function, assuming that\n*data* = [*y₀*, *y₁*, *y₂*, …]. If an **interval** is specified, such as\n*day*, **x** is transformed to the middle of the interval.", + "type": "string" + }, + "meta": { + "$ref": "#/definitions/Meta", + "description": "Specification metadata." + }, + "mixBlendMode": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [mix-blend-mode][1]; a constant string specifying how to blend content such as *multiply*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode" + }, + "monospace": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, changes the default **fontFamily** to *monospace*, and uses simplified monospaced text metrics calculations." + }, + "opacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally. For faster rendering, prefer the **strokeOpacity** or **fillOpacity** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/opacity" + }, + "paintOrder": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [paint-order][1]; a constant string specifying the order in which the\n**fill**, **stroke**, and any markers are drawn; defaults to *normal*, which draws the fill, then stroke, then markers; defaults to *stroke* for the text mark to create a “halo” around text to improve legibility.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/paint-order" + }, + "params": { + "$ref": "#/definitions/Params", + "description": "Param and Selection definitions." + }, + "plotDefaults": { + "$ref": "#/definitions/PlotAttributes", + "description": "A default set of attributes to apply to all plot components." + }, + "pointerEvents": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [pointer-events][1] property; a constant string such as *none*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/pointer-events" + }, + "reverse": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Applies a transform to reverse the order of the mark’s index, say for reverse input order." + }, + "rotate": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The rotation angle in degrees clockwise; a constant or a channel; defaults to 0°. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel." + }, + "select": { + "$ref": "#/definitions/SelectFilter", + "description": "Applies a filter transform after data is loaded to highlight selected values only. For example, `first` and `last` select the first or last values of series only (using the *z* channel to separate series). Meanwhile, `nearestX` and `nearestY` select the point nearest to the pointer along the *x* or *y* channel dimension. Unlike Mosaic selections, a mark level *select* is internal to the mark only, and does not populate a param or selection value to be shared across clients.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "shapeRendering": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [shape-rendering][1]; a constant string such as *crispEdges*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/shape-rendering" + }, + "sort": { + "anyOf": [ + { + "$ref": "#/definitions/SortOrder" + }, + { + "$ref": "#/definitions/ChannelDomainSort" + } + ], + "description": "Either applies a transform to sort the mark’s index by the specified channel values, or imputes ordinal scale domains from this mark’s channels.\n\nWhen imputing ordinal scale domains from channel values, the **sort** option is an object whose keys are ordinal scale names such as *x* or *fx*, and whose values are channel names such as *y*, *y1*, or *y2*. For example, to impute the *y* scale’s domain from the associated *x* channel values in ascending order:\n\n```js sort: {y: \"x\"} ```\n\nFor different sort options for different scales, replace the channel name with a *value* object and per-scale options:\n\n```js sort: {y: {value: \"-x\"}} ```\n\nWhen sorting the mark’s index, the **sort** option is instead one of:\n\n- a channel value definition for sorting given values in ascending order\n- a {value, order} object for sorting given values\n- a {channel, order} object for sorting the named channel’s values" + }, + "stroke": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke" + }, + "strokeDasharray": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dasharray][1]; a constant number indicating the length in pixels of alternating dashes and gaps, or a constant string of numbers separated by spaces or commas (_e.g._, *10 2* for dashes of 10 pixels separated by gaps of 2 pixels), or *none* (the default) for no dashing\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dasharray" + }, + "strokeDashoffset": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dashoffset][1]; a constant indicating the offset in pixels of the first dash along the stroke; defaults to zero.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dashoffset" + }, + "strokeLinecap": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linecap][1]; a constant specifying how to cap stroked paths, such as *butt*, *round*, or *square*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linecap" + }, + "strokeLinejoin": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linejoin][1]; a constant specifying how to join stroked paths, such as *bevel*, *miter*, *miter-clip*, or *round*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linejoin" + }, + "strokeMiterlimit": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-miterlimit][1]; a constant number specifying how to limit the length of *miter* joins on stroked paths.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-miterlimit" + }, + "strokeOpacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-opacity" + }, + "strokeWidth": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-width][1]; a constant number in pixels, or a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-width" + }, + "target": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [target][1]; a constant string specifying the target window (_e.g._,\n*_blank*) for clickable links; used in conjunction with the **href** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/target" + }, + "text": { + "$ref": "#/definitions/ChannelValue", + "description": "The text contents channel, possibly with line breaks (\\n, \\r\\n, or \\r). If not specified, defaults to the zero-based index [0, 1, 2, …]." + }, + "textAnchor": { + "anyOf": [ + { + "const": "start", + "type": "string" + }, + { + "const": "middle", + "type": "string" + }, + { + "const": "end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [text anchor][1] controls how text is aligned (typically horizontally) relative to its anchor point; it is one of *start*, *end*, or *middle*. If the frame anchor is *left*, *top-left*, or *bottom-left*, the default text anchor is *start*; if the frame anchor is *right*, *top-right*, or\n*bottom-right*, the default is *end*; otherwise it is *middle*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/text-anchor" + }, + "textOverflow": { + "anyOf": [ + { + "type": "null" + }, + { + "const": "clip", + "type": "string" + }, + { + "const": "ellipsis", + "type": "string" + }, + { + "const": "clip-start", + "type": "string" + }, + { + "const": "clip-end", + "type": "string" + }, + { + "const": "ellipsis-start", + "type": "string" + }, + { + "const": "ellipsis-middle", + "type": "string" + }, + { + "const": "ellipsis-end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How truncate (or wrap) lines of text longer than the given **lineWidth**; one of:\n\n- null (default) - preserve overflowing characters (and wrap if needed)\n- *clip* or *clip-end* - remove characters from the end\n- *clip-start* - remove characters from the start\n- *ellipsis* or *ellipsis-end* - replace characters from the end with an ellipsis (…)\n- *ellipsis-start* - replace characters from the start with an ellipsis (…)\n- *ellipsis-middle* - replace characters from the middle with an ellipsis (…)\n\nIf no **title** was specified, if text requires truncation, a title containing the non-truncated text will be implicitly added." + }, + "tip": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/TipPointer" + }, + { + "properties": { + "anchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The tip anchor specifies how to orient the tip box relative to its anchor position; it refers to the part of the tip box that is attached to the anchor point. For example, the *top-left* anchor places the top-left corner of tip box near the anchor position, hence placing the tip box below and to the right of the anchor position." + }, + "fontFamily": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font-family][1]; a constant; defaults to the plot’s font family, which is typically [*system-ui*][2].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-family [2]: https://drafts.csswg.org/css-fonts-4/#valdef-font-family-system-ui" + }, + "fontSize": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font size][1] in pixels; either a constant or a channel; defaults to the plot’s font size, which is typically 10. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-size" + }, + "fontStyle": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font style][1]; a constant; defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-style" + }, + "fontVariant": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font variant][1]; a constant; if the **text** channel contains numbers or dates, defaults to *tabular-nums* to facilitate comparing numbers; otherwise defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant" + }, + "fontWeight": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font weight][1]; a constant; defaults to the plot’s font weight, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight" + }, + "format": { + "additionalProperties": false, + "description": "How channel values are formatted for display. If a format is a string, it is interpreted as a (UTC) time format for temporal channels, and otherwise a number format.", + "properties": { + "ariaLabel": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fill": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fillOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fontSize": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fx": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fy": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "geometry": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "height": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "href": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "length": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "opacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "path": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "r": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "rotate": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "src": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "stroke": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeWidth": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "symbol": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "text": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "title": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "weight": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "width": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "z": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + } + }, + "type": "object" + }, + "frameAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The frame anchor specifies defaults for **x** and **y** based on the plot’s frame; it may be one of the four sides (*top*, *right*, *bottom*, *left*), one of the four corners (*top-left*, *top-right*, *bottom-right*,\n*bottom-left*), or the *middle* of the frame. For example, for tips distributed horizontally at the top of the frame:\n\n```js Plot.tip(data, {x: \"date\", frameAnchor: \"top\"}) ```" + }, + "lineHeight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line height in ems; defaults to 1. The line height affects the (typically vertical) separation between adjacent baselines of text, as well as the separation between the text and its anchor point." + }, + "lineWidth": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line width in ems (e.g., 10 for about 20 characters); defaults to infinity, disabling wrapping and clipping.\n\nIf **textOverflow** is null, lines will be wrapped at the specified length. If a line is split at a soft hyphen (\\xad), a hyphen (-) will be displayed at the end of the line. If **textOverflow** is not null, lines will be clipped according to the given strategy." + }, + "monospace": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, changes the default **fontFamily** to *monospace*, and uses simplified monospaced text metrics calculations." + }, + "pathFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The image filter for the tip’s box; defaults to a drop shadow." + }, + "pointer": { + "$ref": "#/definitions/TipPointer" + }, + "pointerSize": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The size of the tip’s pointer in pixels; defaults to 12." + }, + "preferredAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If an explicit tip anchor is not specified, an anchor is chosen automatically such that the tip fits within the plot’s frame; if the preferred anchor fits, it is chosen." + }, + "textAnchor": { + "anyOf": [ + { + "const": "start", + "type": "string" + }, + { + "const": "middle", + "type": "string" + }, + { + "const": "end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [text anchor][1] controls how text is aligned (typically horizontally) relative to its anchor point; it is one of *start*, *end*, or *middle*. If the frame anchor is *left*, *top-left*, or *bottom-left*, the default text anchor is *start*; if the frame anchor is *right*, *top-right*, or\n*bottom-right*, the default is *end*; otherwise it is *middle*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/text-anchor" + }, + "textOverflow": { + "anyOf": [ + { + "type": "null" + }, + { + "const": "clip", + "type": "string" + }, + { + "const": "ellipsis", + "type": "string" + }, + { + "const": "clip-start", + "type": "string" + }, + { + "const": "clip-end", + "type": "string" + }, + { + "const": "ellipsis-start", + "type": "string" + }, + { + "const": "ellipsis-middle", + "type": "string" + }, + { + "const": "ellipsis-end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How truncate (or wrap) lines of text longer than the given **lineWidth**; one of:\n\n- null (default) - preserve overflowing characters (and wrap if needed)\n- *clip* or *clip-end* - remove characters from the end\n- *clip-start* - remove characters from the start\n- *ellipsis* or *ellipsis-end* - replace characters from the end with an ellipsis (…)\n- *ellipsis-start* - replace characters from the start with an ellipsis (…)\n- *ellipsis-middle* - replace characters from the middle with an ellipsis (…)\n\nIf no **title** was specified, if text requires truncation, a title containing the non-truncated text will be implicitly added." + }, + "textPadding": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The padding around the text in pixels; defaults to 8." + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + } + }, + "type": "object" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to generate a tooltip for this mark, and any tip options." + }, + "title": { + "$ref": "#/definitions/ChannelValue", + "description": "The title; a channel specifying accessible, short textual descriptions as strings (possibly with newlines). If the tip option is specified, the title will be displayed with an interactive tooltip instead of using the SVG [title element][1].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/title" + }, + "x": { + "$ref": "#/definitions/ChannelValueIntervalSpec", + "description": "The horizontal position of the text’s anchor point, typically bound to the\n*x* scale." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel specifying the text’s anchor point, typically bound to the *y* scale." + }, + "z": { + "$ref": "#/definitions/ChannelValue", + "description": "An optional ordinal channel for grouping data into series." + } + }, + "required": [ + "mark" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "$schema": { + "description": "A [JSON schema](http://json-schema.org/) URL for this specification, such as https://uwdata.github.io/mosaic/schema/latest.json. This property enables validation and autocomplete in editors with JSON schema support.", + "format": "uri", + "type": "string" + }, + "ariaDescription": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-description][1]; a constant textual description.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-description" + }, + "ariaHidden": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-hidden][1] state; a constant indicating whether the element is exposed to an accessibility API.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-hidden" + }, + "ariaLabel": { + "$ref": "#/definitions/ChannelValue", + "description": "The [aria-label][1]; a channel specifying short textual labels representing the value in the accessibility tree.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-label" + }, + "clip": { + "anyOf": [ + { + "const": "frame", + "type": "string" + }, + { + "const": "sphere", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to clip the mark; one of:\n\n- *frame* or true - clip to the plot’s frame (inner area)\n- *sphere* - clip to the projected sphere (*e.g.*, front hemisphere)\n- null or false - do not clip\n\nThe *sphere* clip option requires a geographic projection." + }, + "config": { + "$ref": "#/definitions/Config", + "description": "Configuration options." + }, + "data": { + "$ref": "#/definitions/Data", + "description": "Dataset definitions." + }, + "dx": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The horizontal offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "dy": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The vertical offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "facet": { + "anyOf": [ + { + "const": "auto", + "type": "string" + }, + { + "const": "include", + "type": "string" + }, + { + "const": "exclude", + "type": "string" + }, + { + "const": "super", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to enable or disable faceting; one of:\n\n- *auto* (default) - automatically determine if this mark should be faceted\n- *include* (or true) - draw the subset of the mark’s data in the current facet\n- *exclude* - draw the subset of the mark’s data *not* in the current facet\n- *super* - draw this mark in a single frame that covers all facets\n- null (or false) - repeat this mark’s data across all facets (*i.e.*, no faceting)\n\nWhen a mark uses *super* faceting, it is not allowed to use position scales (*x*, *y*, *fx*, or *fy*); *super* faceting is intended for decorations, such as labels and legends.\n\nWhen top-level faceting is used, the default *auto* setting is equivalent to *include* when the mark data is strictly equal to the top-level facet data; otherwise it is equivalent to null. When the *include* or *exclude* facet mode is chosen, the mark data must be parallel to the top-level facet data: the data must have the same length and order. If the data are not parallel, then the wrong data may be shown in each facet. The default\n*auto* therefore requires strict equality (`===`) for safety, and using the facet data as mark data is recommended when using the *exclude* facet mode. (To construct parallel data safely, consider using [*array*.map][1] on the facet data.)\n\nWhen mark-level faceting is used, the default *auto* setting is equivalent to *include*: the mark will be faceted if either the **fx** or **fy** channel option (or both) is specified. The null or false option will disable faceting, while *exclude* draws the subset of the mark’s data *not* in the current facet.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map" + }, + "facetAnchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "right", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "const": "left", + "type": "string" + }, + { + "const": "top-left", + "type": "string" + }, + { + "const": "top-right", + "type": "string" + }, + { + "const": "bottom-left", + "type": "string" + }, + { + "const": "bottom-right", + "type": "string" + }, + { + "const": "top-empty", + "type": "string" + }, + { + "const": "right-empty", + "type": "string" + }, + { + "const": "bottom-empty", + "type": "string" + }, + { + "const": "left-empty", + "type": "string" + }, + { + "const": "empty", + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to place the mark with respect to facets; one of:\n\n- null (default for most marks) - display the mark in each non-empty facet\n- *top*, *right*, *bottom*, or *left* - display the mark only in facets on the given side\n- *top-empty*, *right-empty*, *bottom-empty*, or *left-empty* (default for axis marks) - display the mark only in facets that have empty space on the given side: either the margin, or an empty facet\n- *empty* - display the mark in empty facets only" + }, + "fill": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill" + }, + "fillOpacity": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill-opacity][1]; a constant number between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill-opacity" + }, + "filter": { + "$ref": "#/definitions/ChannelValue", + "description": "Applies a transform to filter the mark’s index according to the given channel values; only truthy values are retained.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "fx": { + "$ref": "#/definitions/ChannelValue", + "description": "The horizontal facet position channel, for mark-level faceting, bound to the *fx* scale." + }, + "fy": { + "$ref": "#/definitions/ChannelValue", + "description": "The vertical facet position channel, for mark-level faceting, bound to the\n*fy* scale." + }, + "href": { + "$ref": "#/definitions/ChannelValue", + "description": "The [href][1]; a channel specifying URLs for clickable links. May be used in conjunction with the **target** option to open links in another window.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/href" + }, + "imageFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A CSS [filter][1]; a constant string used to adjust the rendering of images, such as *blur(5px)*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/filter" + }, + "inset": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four insets: **insetTop**,\n**insetRight**, **insetBottom**, and **insetLeft**. All insets typically default to zero, though not always (say when using bin transform). A positive inset reduces effective area, while a negative inset increases it." + }, + "insetBottom": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Insets the bottom edge by the specified number of pixels. A positive value insets towards the top edge (reducing effective area), while a negative value insets away from the top edge (increasing it)." + }, + "insetTop": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Insets the top edge by the specified number of pixels. A positive value insets towards the bottom edge (reducing effective area), while a negative value insets away from the bottom edge (increasing it)." + }, + "margin": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four mark margins: **marginTop**,\n**marginRight**, **marginBottom**, and **marginLeft**; typically defaults to 0, except for axis marks." + }, + "marginBottom": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s bottom margin; the minimum distance in pixels between the bottom edges of the inner and outer plot area." + }, + "marginLeft": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s left margin; the minimum distance in pixels between the left edges of the inner and outer plot area." + }, + "marginRight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s right margin; the minimum distance in pixels between the right edges of the mark’s inner and outer plot area." + }, + "marginTop": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s top margin; the minimum distance in pixels between the top edges of the inner and outer plot area." + }, + "mark": { + "const": "tickX", + "description": "A horizontally-positioned tickX mark (a vertical line, |). The **x** channel specifies the tick’s horizontal position and defaults to identity, assuming that *data* = [*x₀*, *x₁*, *x₂*, …]; the optional **y** ordinal channel specifies its vertical position.\n\nIf *y* represents quantitative or temporal values, use a ruleX mark instead.", + "type": "string" + }, + "marker": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for markerStart, markerMid, and markerEnd; one of:\n\n- a marker name such as *arrow* or *circle*\n- *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*" + }, + "markerEnd": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The marker for the ending point of a line segment; one of:\n\n- a marker name such as *arrow* or *circle*\n* *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*" + }, + "markerMid": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The marker for any middle (interior) points of a line segment. If the line segment only has a start and end point, this option has no effect. One of:\n\n- a marker name such as *arrow* or *circle*\n* *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*\n* a function - a custom marker function; see below" + }, + "markerStart": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The marker for the starting point of a line segment; one of:\n\n- a marker name such as *arrow* or *circle*\n* *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*" + }, + "meta": { + "$ref": "#/definitions/Meta", + "description": "Specification metadata." + }, + "mixBlendMode": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [mix-blend-mode][1]; a constant string specifying how to blend content such as *multiply*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode" + }, + "opacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally. For faster rendering, prefer the **strokeOpacity** or **fillOpacity** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/opacity" + }, + "paintOrder": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [paint-order][1]; a constant string specifying the order in which the\n**fill**, **stroke**, and any markers are drawn; defaults to *normal*, which draws the fill, then stroke, then markers; defaults to *stroke* for the text mark to create a “halo” around text to improve legibility.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/paint-order" + }, + "params": { + "$ref": "#/definitions/Params", + "description": "Param and Selection definitions." + }, + "plotDefaults": { + "$ref": "#/definitions/PlotAttributes", + "description": "A default set of attributes to apply to all plot components." + }, + "pointerEvents": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [pointer-events][1] property; a constant string such as *none*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/pointer-events" + }, + "reverse": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Applies a transform to reverse the order of the mark’s index, say for reverse input order." + }, + "select": { + "$ref": "#/definitions/SelectFilter", + "description": "Applies a filter transform after data is loaded to highlight selected values only. For example, `first` and `last` select the first or last values of series only (using the *z* channel to separate series). Meanwhile, `nearestX` and `nearestY` select the point nearest to the pointer along the *x* or *y* channel dimension. Unlike Mosaic selections, a mark level *select* is internal to the mark only, and does not populate a param or selection value to be shared across clients.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "shapeRendering": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [shape-rendering][1]; a constant string such as *crispEdges*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/shape-rendering" + }, + "sort": { + "anyOf": [ + { + "$ref": "#/definitions/SortOrder" + }, + { + "$ref": "#/definitions/ChannelDomainSort" + } + ], + "description": "Either applies a transform to sort the mark’s index by the specified channel values, or imputes ordinal scale domains from this mark’s channels.\n\nWhen imputing ordinal scale domains from channel values, the **sort** option is an object whose keys are ordinal scale names such as *x* or *fx*, and whose values are channel names such as *y*, *y1*, or *y2*. For example, to impute the *y* scale’s domain from the associated *x* channel values in ascending order:\n\n```js sort: {y: \"x\"} ```\n\nFor different sort options for different scales, replace the channel name with a *value* object and per-scale options:\n\n```js sort: {y: {value: \"-x\"}} ```\n\nWhen sorting the mark’s index, the **sort** option is instead one of:\n\n- a channel value definition for sorting given values in ascending order\n- a {value, order} object for sorting given values\n- a {channel, order} object for sorting the named channel’s values" + }, + "stroke": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke" + }, + "strokeDasharray": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dasharray][1]; a constant number indicating the length in pixels of alternating dashes and gaps, or a constant string of numbers separated by spaces or commas (_e.g._, *10 2* for dashes of 10 pixels separated by gaps of 2 pixels), or *none* (the default) for no dashing\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dasharray" + }, + "strokeDashoffset": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dashoffset][1]; a constant indicating the offset in pixels of the first dash along the stroke; defaults to zero.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dashoffset" + }, + "strokeLinecap": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linecap][1]; a constant specifying how to cap stroked paths, such as *butt*, *round*, or *square*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linecap" + }, + "strokeLinejoin": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linejoin][1]; a constant specifying how to join stroked paths, such as *bevel*, *miter*, *miter-clip*, or *round*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linejoin" + }, + "strokeMiterlimit": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-miterlimit][1]; a constant number specifying how to limit the length of *miter* joins on stroked paths.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-miterlimit" + }, + "strokeOpacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-opacity" + }, + "strokeWidth": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-width][1]; a constant number in pixels, or a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-width" + }, + "target": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [target][1]; a constant string specifying the target window (_e.g._,\n*_blank*) for clickable links; used in conjunction with the **href** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/target" + }, + "tip": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/TipPointer" + }, + { + "properties": { + "anchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The tip anchor specifies how to orient the tip box relative to its anchor position; it refers to the part of the tip box that is attached to the anchor point. For example, the *top-left* anchor places the top-left corner of tip box near the anchor position, hence placing the tip box below and to the right of the anchor position." + }, + "fontFamily": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font-family][1]; a constant; defaults to the plot’s font family, which is typically [*system-ui*][2].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-family [2]: https://drafts.csswg.org/css-fonts-4/#valdef-font-family-system-ui" + }, + "fontSize": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font size][1] in pixels; either a constant or a channel; defaults to the plot’s font size, which is typically 10. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-size" + }, + "fontStyle": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font style][1]; a constant; defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-style" + }, + "fontVariant": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font variant][1]; a constant; if the **text** channel contains numbers or dates, defaults to *tabular-nums* to facilitate comparing numbers; otherwise defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant" + }, + "fontWeight": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font weight][1]; a constant; defaults to the plot’s font weight, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight" + }, + "format": { + "additionalProperties": false, + "description": "How channel values are formatted for display. If a format is a string, it is interpreted as a (UTC) time format for temporal channels, and otherwise a number format.", + "properties": { + "ariaLabel": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fill": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fillOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fontSize": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fx": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fy": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "geometry": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "height": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "href": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "length": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "opacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "path": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "r": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "rotate": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "src": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "stroke": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeWidth": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "symbol": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "text": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "title": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "weight": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "width": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "z": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + } + }, + "type": "object" + }, + "frameAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The frame anchor specifies defaults for **x** and **y** based on the plot’s frame; it may be one of the four sides (*top*, *right*, *bottom*, *left*), one of the four corners (*top-left*, *top-right*, *bottom-right*,\n*bottom-left*), or the *middle* of the frame. For example, for tips distributed horizontally at the top of the frame:\n\n```js Plot.tip(data, {x: \"date\", frameAnchor: \"top\"}) ```" + }, + "lineHeight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line height in ems; defaults to 1. The line height affects the (typically vertical) separation between adjacent baselines of text, as well as the separation between the text and its anchor point." + }, + "lineWidth": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line width in ems (e.g., 10 for about 20 characters); defaults to infinity, disabling wrapping and clipping.\n\nIf **textOverflow** is null, lines will be wrapped at the specified length. If a line is split at a soft hyphen (\\xad), a hyphen (-) will be displayed at the end of the line. If **textOverflow** is not null, lines will be clipped according to the given strategy." + }, + "monospace": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, changes the default **fontFamily** to *monospace*, and uses simplified monospaced text metrics calculations." + }, + "pathFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The image filter for the tip’s box; defaults to a drop shadow." + }, + "pointer": { + "$ref": "#/definitions/TipPointer" + }, + "pointerSize": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The size of the tip’s pointer in pixels; defaults to 12." + }, + "preferredAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If an explicit tip anchor is not specified, an anchor is chosen automatically such that the tip fits within the plot’s frame; if the preferred anchor fits, it is chosen." + }, + "textAnchor": { + "anyOf": [ + { + "const": "start", + "type": "string" + }, + { + "const": "middle", + "type": "string" + }, + { + "const": "end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [text anchor][1] controls how text is aligned (typically horizontally) relative to its anchor point; it is one of *start*, *end*, or *middle*. If the frame anchor is *left*, *top-left*, or *bottom-left*, the default text anchor is *start*; if the frame anchor is *right*, *top-right*, or\n*bottom-right*, the default is *end*; otherwise it is *middle*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/text-anchor" + }, + "textOverflow": { + "anyOf": [ + { + "type": "null" + }, + { + "const": "clip", + "type": "string" + }, + { + "const": "ellipsis", + "type": "string" + }, + { + "const": "clip-start", + "type": "string" + }, + { + "const": "clip-end", + "type": "string" + }, + { + "const": "ellipsis-start", + "type": "string" + }, + { + "const": "ellipsis-middle", + "type": "string" + }, + { + "const": "ellipsis-end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How truncate (or wrap) lines of text longer than the given **lineWidth**; one of:\n\n- null (default) - preserve overflowing characters (and wrap if needed)\n- *clip* or *clip-end* - remove characters from the end\n- *clip-start* - remove characters from the start\n- *ellipsis* or *ellipsis-end* - replace characters from the end with an ellipsis (…)\n- *ellipsis-start* - replace characters from the start with an ellipsis (…)\n- *ellipsis-middle* - replace characters from the middle with an ellipsis (…)\n\nIf no **title** was specified, if text requires truncation, a title containing the non-truncated text will be implicitly added." + }, + "textPadding": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The padding around the text in pixels; defaults to 8." + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + } + }, + "type": "object" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to generate a tooltip for this mark, and any tip options." + }, + "title": { + "$ref": "#/definitions/ChannelValue", + "description": "The title; a channel specifying accessible, short textual descriptions as strings (possibly with newlines). If the tip option is specified, the title will be displayed with an interactive tooltip instead of using the SVG [title element][1].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/title" + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The required horizontal position of the tick; a channel typically bound to the *x* scale." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The optional vertical position of the tick; an ordinal channel typically bound to the *y* scale. If not specified, the tick spans the vertical extent of the frame; otherwise the *y* scale must be a *band* scale.\n\nIf *y* represents quantitative or temporal values, use a ruleX mark instead." + } + }, + "required": [ + "data", + "mark" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "$schema": { + "description": "A [JSON schema](http://json-schema.org/) URL for this specification, such as https://uwdata.github.io/mosaic/schema/latest.json. This property enables validation and autocomplete in editors with JSON schema support.", + "format": "uri", + "type": "string" + }, + "ariaDescription": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-description][1]; a constant textual description.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-description" + }, + "ariaHidden": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-hidden][1] state; a constant indicating whether the element is exposed to an accessibility API.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-hidden" + }, + "ariaLabel": { + "$ref": "#/definitions/ChannelValue", + "description": "The [aria-label][1]; a channel specifying short textual labels representing the value in the accessibility tree.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-label" + }, + "clip": { + "anyOf": [ + { + "const": "frame", + "type": "string" + }, + { + "const": "sphere", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to clip the mark; one of:\n\n- *frame* or true - clip to the plot’s frame (inner area)\n- *sphere* - clip to the projected sphere (*e.g.*, front hemisphere)\n- null or false - do not clip\n\nThe *sphere* clip option requires a geographic projection." + }, + "config": { + "$ref": "#/definitions/Config", + "description": "Configuration options." + }, + "data": { + "$ref": "#/definitions/Data", + "description": "Dataset definitions." + }, + "dx": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The horizontal offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "dy": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The vertical offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "facet": { + "anyOf": [ + { + "const": "auto", + "type": "string" + }, + { + "const": "include", + "type": "string" + }, + { + "const": "exclude", + "type": "string" + }, + { + "const": "super", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to enable or disable faceting; one of:\n\n- *auto* (default) - automatically determine if this mark should be faceted\n- *include* (or true) - draw the subset of the mark’s data in the current facet\n- *exclude* - draw the subset of the mark’s data *not* in the current facet\n- *super* - draw this mark in a single frame that covers all facets\n- null (or false) - repeat this mark’s data across all facets (*i.e.*, no faceting)\n\nWhen a mark uses *super* faceting, it is not allowed to use position scales (*x*, *y*, *fx*, or *fy*); *super* faceting is intended for decorations, such as labels and legends.\n\nWhen top-level faceting is used, the default *auto* setting is equivalent to *include* when the mark data is strictly equal to the top-level facet data; otherwise it is equivalent to null. When the *include* or *exclude* facet mode is chosen, the mark data must be parallel to the top-level facet data: the data must have the same length and order. If the data are not parallel, then the wrong data may be shown in each facet. The default\n*auto* therefore requires strict equality (`===`) for safety, and using the facet data as mark data is recommended when using the *exclude* facet mode. (To construct parallel data safely, consider using [*array*.map][1] on the facet data.)\n\nWhen mark-level faceting is used, the default *auto* setting is equivalent to *include*: the mark will be faceted if either the **fx** or **fy** channel option (or both) is specified. The null or false option will disable faceting, while *exclude* draws the subset of the mark’s data *not* in the current facet.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map" + }, + "facetAnchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "right", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "const": "left", + "type": "string" + }, + { + "const": "top-left", + "type": "string" + }, + { + "const": "top-right", + "type": "string" + }, + { + "const": "bottom-left", + "type": "string" + }, + { + "const": "bottom-right", + "type": "string" + }, + { + "const": "top-empty", + "type": "string" + }, + { + "const": "right-empty", + "type": "string" + }, + { + "const": "bottom-empty", + "type": "string" + }, + { + "const": "left-empty", + "type": "string" + }, + { + "const": "empty", + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to place the mark with respect to facets; one of:\n\n- null (default for most marks) - display the mark in each non-empty facet\n- *top*, *right*, *bottom*, or *left* - display the mark only in facets on the given side\n- *top-empty*, *right-empty*, *bottom-empty*, or *left-empty* (default for axis marks) - display the mark only in facets that have empty space on the given side: either the margin, or an empty facet\n- *empty* - display the mark in empty facets only" + }, + "fill": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill" + }, + "fillOpacity": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill-opacity][1]; a constant number between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill-opacity" + }, + "filter": { + "$ref": "#/definitions/ChannelValue", + "description": "Applies a transform to filter the mark’s index according to the given channel values; only truthy values are retained.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "fx": { + "$ref": "#/definitions/ChannelValue", + "description": "The horizontal facet position channel, for mark-level faceting, bound to the *fx* scale." + }, + "fy": { + "$ref": "#/definitions/ChannelValue", + "description": "The vertical facet position channel, for mark-level faceting, bound to the\n*fy* scale." + }, + "href": { + "$ref": "#/definitions/ChannelValue", + "description": "The [href][1]; a channel specifying URLs for clickable links. May be used in conjunction with the **target** option to open links in another window.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/href" + }, + "imageFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A CSS [filter][1]; a constant string used to adjust the rendering of images, such as *blur(5px)*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/filter" + }, + "inset": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four insets: **insetTop**,\n**insetRight**, **insetBottom**, and **insetLeft**. All insets typically default to zero, though not always (say when using bin transform). A positive inset reduces effective area, while a negative inset increases it." + }, + "insetLeft": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Insets the left edge by the specified number of pixels. A positive value insets towards the right edge (reducing effective area), while a negative value insets away from the right edge (increasing it)." + }, + "insetRight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Insets the right edge by the specified number of pixels. A positive value insets towards the left edge (reducing effective area), while a negative value insets away from the left edge (increasing it)." + }, + "margin": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four mark margins: **marginTop**,\n**marginRight**, **marginBottom**, and **marginLeft**; typically defaults to 0, except for axis marks." + }, + "marginBottom": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s bottom margin; the minimum distance in pixels between the bottom edges of the inner and outer plot area." + }, + "marginLeft": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s left margin; the minimum distance in pixels between the left edges of the inner and outer plot area." + }, + "marginRight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s right margin; the minimum distance in pixels between the right edges of the mark’s inner and outer plot area." + }, + "marginTop": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s top margin; the minimum distance in pixels between the top edges of the inner and outer plot area." + }, + "mark": { + "const": "tickY", + "description": "A vertically-positioned tickY mark (a horizontal line, —). The **y** channel specifies the tick's vertical position and defaults to identity, assuming that *data* = [*y₀*, *y₁*, *y₂*, …]; the optional **x** ordinal channel specifies its horizontal position.\n\nIf *x* represents quantitative or temporal values, use a ruleY mark instead.", + "type": "string" + }, + "marker": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for markerStart, markerMid, and markerEnd; one of:\n\n- a marker name such as *arrow* or *circle*\n- *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*" + }, + "markerEnd": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The marker for the ending point of a line segment; one of:\n\n- a marker name such as *arrow* or *circle*\n* *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*" + }, + "markerMid": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The marker for any middle (interior) points of a line segment. If the line segment only has a start and end point, this option has no effect. One of:\n\n- a marker name such as *arrow* or *circle*\n* *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*\n* a function - a custom marker function; see below" + }, + "markerStart": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The marker for the starting point of a line segment; one of:\n\n- a marker name such as *arrow* or *circle*\n* *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*" + }, + "meta": { + "$ref": "#/definitions/Meta", + "description": "Specification metadata." + }, + "mixBlendMode": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [mix-blend-mode][1]; a constant string specifying how to blend content such as *multiply*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode" + }, + "opacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally. For faster rendering, prefer the **strokeOpacity** or **fillOpacity** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/opacity" + }, + "paintOrder": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [paint-order][1]; a constant string specifying the order in which the\n**fill**, **stroke**, and any markers are drawn; defaults to *normal*, which draws the fill, then stroke, then markers; defaults to *stroke* for the text mark to create a “halo” around text to improve legibility.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/paint-order" + }, + "params": { + "$ref": "#/definitions/Params", + "description": "Param and Selection definitions." + }, + "plotDefaults": { + "$ref": "#/definitions/PlotAttributes", + "description": "A default set of attributes to apply to all plot components." + }, + "pointerEvents": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [pointer-events][1] property; a constant string such as *none*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/pointer-events" + }, + "reverse": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Applies a transform to reverse the order of the mark’s index, say for reverse input order." + }, + "select": { + "$ref": "#/definitions/SelectFilter", + "description": "Applies a filter transform after data is loaded to highlight selected values only. For example, `first` and `last` select the first or last values of series only (using the *z* channel to separate series). Meanwhile, `nearestX` and `nearestY` select the point nearest to the pointer along the *x* or *y* channel dimension. Unlike Mosaic selections, a mark level *select* is internal to the mark only, and does not populate a param or selection value to be shared across clients.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "shapeRendering": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [shape-rendering][1]; a constant string such as *crispEdges*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/shape-rendering" + }, + "sort": { + "anyOf": [ + { + "$ref": "#/definitions/SortOrder" + }, + { + "$ref": "#/definitions/ChannelDomainSort" + } + ], + "description": "Either applies a transform to sort the mark’s index by the specified channel values, or imputes ordinal scale domains from this mark’s channels.\n\nWhen imputing ordinal scale domains from channel values, the **sort** option is an object whose keys are ordinal scale names such as *x* or *fx*, and whose values are channel names such as *y*, *y1*, or *y2*. For example, to impute the *y* scale’s domain from the associated *x* channel values in ascending order:\n\n```js sort: {y: \"x\"} ```\n\nFor different sort options for different scales, replace the channel name with a *value* object and per-scale options:\n\n```js sort: {y: {value: \"-x\"}} ```\n\nWhen sorting the mark’s index, the **sort** option is instead one of:\n\n- a channel value definition for sorting given values in ascending order\n- a {value, order} object for sorting given values\n- a {channel, order} object for sorting the named channel’s values" + }, + "stroke": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke" + }, + "strokeDasharray": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dasharray][1]; a constant number indicating the length in pixels of alternating dashes and gaps, or a constant string of numbers separated by spaces or commas (_e.g._, *10 2* for dashes of 10 pixels separated by gaps of 2 pixels), or *none* (the default) for no dashing\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dasharray" + }, + "strokeDashoffset": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dashoffset][1]; a constant indicating the offset in pixels of the first dash along the stroke; defaults to zero.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dashoffset" + }, + "strokeLinecap": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linecap][1]; a constant specifying how to cap stroked paths, such as *butt*, *round*, or *square*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linecap" + }, + "strokeLinejoin": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linejoin][1]; a constant specifying how to join stroked paths, such as *bevel*, *miter*, *miter-clip*, or *round*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linejoin" + }, + "strokeMiterlimit": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-miterlimit][1]; a constant number specifying how to limit the length of *miter* joins on stroked paths.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-miterlimit" + }, + "strokeOpacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-opacity" + }, + "strokeWidth": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-width][1]; a constant number in pixels, or a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-width" + }, + "target": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [target][1]; a constant string specifying the target window (_e.g._,\n*_blank*) for clickable links; used in conjunction with the **href** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/target" + }, + "tip": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/TipPointer" + }, + { + "properties": { + "anchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The tip anchor specifies how to orient the tip box relative to its anchor position; it refers to the part of the tip box that is attached to the anchor point. For example, the *top-left* anchor places the top-left corner of tip box near the anchor position, hence placing the tip box below and to the right of the anchor position." + }, + "fontFamily": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font-family][1]; a constant; defaults to the plot’s font family, which is typically [*system-ui*][2].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-family [2]: https://drafts.csswg.org/css-fonts-4/#valdef-font-family-system-ui" + }, + "fontSize": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font size][1] in pixels; either a constant or a channel; defaults to the plot’s font size, which is typically 10. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-size" + }, + "fontStyle": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font style][1]; a constant; defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-style" + }, + "fontVariant": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font variant][1]; a constant; if the **text** channel contains numbers or dates, defaults to *tabular-nums* to facilitate comparing numbers; otherwise defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant" + }, + "fontWeight": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font weight][1]; a constant; defaults to the plot’s font weight, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight" + }, + "format": { + "additionalProperties": false, + "description": "How channel values are formatted for display. If a format is a string, it is interpreted as a (UTC) time format for temporal channels, and otherwise a number format.", + "properties": { + "ariaLabel": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fill": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fillOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fontSize": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fx": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fy": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "geometry": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "height": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "href": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "length": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "opacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "path": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "r": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "rotate": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "src": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "stroke": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeWidth": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "symbol": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "text": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "title": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "weight": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "width": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "z": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + } + }, + "type": "object" + }, + "frameAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The frame anchor specifies defaults for **x** and **y** based on the plot’s frame; it may be one of the four sides (*top*, *right*, *bottom*, *left*), one of the four corners (*top-left*, *top-right*, *bottom-right*,\n*bottom-left*), or the *middle* of the frame. For example, for tips distributed horizontally at the top of the frame:\n\n```js Plot.tip(data, {x: \"date\", frameAnchor: \"top\"}) ```" + }, + "lineHeight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line height in ems; defaults to 1. The line height affects the (typically vertical) separation between adjacent baselines of text, as well as the separation between the text and its anchor point." + }, + "lineWidth": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line width in ems (e.g., 10 for about 20 characters); defaults to infinity, disabling wrapping and clipping.\n\nIf **textOverflow** is null, lines will be wrapped at the specified length. If a line is split at a soft hyphen (\\xad), a hyphen (-) will be displayed at the end of the line. If **textOverflow** is not null, lines will be clipped according to the given strategy." + }, + "monospace": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, changes the default **fontFamily** to *monospace*, and uses simplified monospaced text metrics calculations." + }, + "pathFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The image filter for the tip’s box; defaults to a drop shadow." + }, + "pointer": { + "$ref": "#/definitions/TipPointer" + }, + "pointerSize": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The size of the tip’s pointer in pixels; defaults to 12." + }, + "preferredAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If an explicit tip anchor is not specified, an anchor is chosen automatically such that the tip fits within the plot’s frame; if the preferred anchor fits, it is chosen." + }, + "textAnchor": { + "anyOf": [ + { + "const": "start", + "type": "string" + }, + { + "const": "middle", + "type": "string" + }, + { + "const": "end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [text anchor][1] controls how text is aligned (typically horizontally) relative to its anchor point; it is one of *start*, *end*, or *middle*. If the frame anchor is *left*, *top-left*, or *bottom-left*, the default text anchor is *start*; if the frame anchor is *right*, *top-right*, or\n*bottom-right*, the default is *end*; otherwise it is *middle*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/text-anchor" + }, + "textOverflow": { + "anyOf": [ + { + "type": "null" + }, + { + "const": "clip", + "type": "string" + }, + { + "const": "ellipsis", + "type": "string" + }, + { + "const": "clip-start", + "type": "string" + }, + { + "const": "clip-end", + "type": "string" + }, + { + "const": "ellipsis-start", + "type": "string" + }, + { + "const": "ellipsis-middle", + "type": "string" + }, + { + "const": "ellipsis-end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How truncate (or wrap) lines of text longer than the given **lineWidth**; one of:\n\n- null (default) - preserve overflowing characters (and wrap if needed)\n- *clip* or *clip-end* - remove characters from the end\n- *clip-start* - remove characters from the start\n- *ellipsis* or *ellipsis-end* - replace characters from the end with an ellipsis (…)\n- *ellipsis-start* - replace characters from the start with an ellipsis (…)\n- *ellipsis-middle* - replace characters from the middle with an ellipsis (…)\n\nIf no **title** was specified, if text requires truncation, a title containing the non-truncated text will be implicitly added." + }, + "textPadding": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The padding around the text in pixels; defaults to 8." + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + } + }, + "type": "object" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to generate a tooltip for this mark, and any tip options." + }, + "title": { + "$ref": "#/definitions/ChannelValue", + "description": "The title; a channel specifying accessible, short textual descriptions as strings (possibly with newlines). If the tip option is specified, the title will be displayed with an interactive tooltip instead of using the SVG [title element][1].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/title" + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The optional horizontal position of the tick; an ordinal channel typically bound to the *x* scale. If not specified, the tick spans the horizontal extent of the frame; otherwise the *x* scale must be a *band* scale.\n\nIf *x* represents quantitative or temporal values, use a ruleY mark instead." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The required vertical position of the tick; a channel typically bound to the *y* scale." + } + }, + "required": [ + "data", + "mark" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "$schema": { + "description": "A [JSON schema](http://json-schema.org/) URL for this specification, such as https://uwdata.github.io/mosaic/schema/latest.json. This property enables validation and autocomplete in editors with JSON schema support.", + "format": "uri", + "type": "string" + }, + "anchor": { + "anyOf": [ + { + "const": "start", + "type": "string" + }, + { + "const": "middle", + "type": "string" + }, + { + "const": "end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The vector’s position along its orientation relative to its anchor point; a constant. Assuming a default **rotate** angle of 0°, one of:\n\n- *start* - from [*x*, *y*] to [*x*, *y* - *l*]\n- *middle* (default) - from [*x*, *y* + *l* / 2] to [*x*, *y* - *l* / 2]\n- *end* - from [*x*, *y* + *l*] to [*x*, *y*]\n\nwhere [*x*, *y*] is the vector’s anchor point and *l* is the vector’s (possibly scaled) length in pixels." + }, + "ariaDescription": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-description][1]; a constant textual description.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-description" + }, + "ariaHidden": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-hidden][1] state; a constant indicating whether the element is exposed to an accessibility API.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-hidden" + }, + "ariaLabel": { + "$ref": "#/definitions/ChannelValue", + "description": "The [aria-label][1]; a channel specifying short textual labels representing the value in the accessibility tree.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-label" + }, + "clip": { + "anyOf": [ + { + "const": "frame", + "type": "string" + }, + { + "const": "sphere", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to clip the mark; one of:\n\n- *frame* or true - clip to the plot’s frame (inner area)\n- *sphere* - clip to the projected sphere (*e.g.*, front hemisphere)\n- null or false - do not clip\n\nThe *sphere* clip option requires a geographic projection." + }, + "config": { + "$ref": "#/definitions/Config", + "description": "Configuration options." + }, + "data": { + "$ref": "#/definitions/Data", + "description": "Dataset definitions." + }, + "dx": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The horizontal offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "dy": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The vertical offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "facet": { + "anyOf": [ + { + "const": "auto", + "type": "string" + }, + { + "const": "include", + "type": "string" + }, + { + "const": "exclude", + "type": "string" + }, + { + "const": "super", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to enable or disable faceting; one of:\n\n- *auto* (default) - automatically determine if this mark should be faceted\n- *include* (or true) - draw the subset of the mark’s data in the current facet\n- *exclude* - draw the subset of the mark’s data *not* in the current facet\n- *super* - draw this mark in a single frame that covers all facets\n- null (or false) - repeat this mark’s data across all facets (*i.e.*, no faceting)\n\nWhen a mark uses *super* faceting, it is not allowed to use position scales (*x*, *y*, *fx*, or *fy*); *super* faceting is intended for decorations, such as labels and legends.\n\nWhen top-level faceting is used, the default *auto* setting is equivalent to *include* when the mark data is strictly equal to the top-level facet data; otherwise it is equivalent to null. When the *include* or *exclude* facet mode is chosen, the mark data must be parallel to the top-level facet data: the data must have the same length and order. If the data are not parallel, then the wrong data may be shown in each facet. The default\n*auto* therefore requires strict equality (`===`) for safety, and using the facet data as mark data is recommended when using the *exclude* facet mode. (To construct parallel data safely, consider using [*array*.map][1] on the facet data.)\n\nWhen mark-level faceting is used, the default *auto* setting is equivalent to *include*: the mark will be faceted if either the **fx** or **fy** channel option (or both) is specified. The null or false option will disable faceting, while *exclude* draws the subset of the mark’s data *not* in the current facet.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map" + }, + "facetAnchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "right", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "const": "left", + "type": "string" + }, + { + "const": "top-left", + "type": "string" + }, + { + "const": "top-right", + "type": "string" + }, + { + "const": "bottom-left", + "type": "string" + }, + { + "const": "bottom-right", + "type": "string" + }, + { + "const": "top-empty", + "type": "string" + }, + { + "const": "right-empty", + "type": "string" + }, + { + "const": "bottom-empty", + "type": "string" + }, + { + "const": "left-empty", + "type": "string" + }, + { + "const": "empty", + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to place the mark with respect to facets; one of:\n\n- null (default for most marks) - display the mark in each non-empty facet\n- *top*, *right*, *bottom*, or *left* - display the mark only in facets on the given side\n- *top-empty*, *right-empty*, *bottom-empty*, or *left-empty* (default for axis marks) - display the mark only in facets that have empty space on the given side: either the margin, or an empty facet\n- *empty* - display the mark in empty facets only" + }, + "fill": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill" + }, + "fillOpacity": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill-opacity][1]; a constant number between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill-opacity" + }, + "filter": { + "$ref": "#/definitions/ChannelValue", + "description": "Applies a transform to filter the mark’s index according to the given channel values; only truthy values are retained.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "frameAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The vector’s frame anchor, to default **x** and **y** relative to the frame; a constant representing one of the frame corners (*top-left*,\n*top-right*, *bottom-right*, *bottom-left*), sides (*top*, *right*,\n*bottom*, *left*), or *middle* (default). Has no effect if both **x** and **y** are specified." + }, + "fx": { + "$ref": "#/definitions/ChannelValue", + "description": "The horizontal facet position channel, for mark-level faceting, bound to the *fx* scale." + }, + "fy": { + "$ref": "#/definitions/ChannelValue", + "description": "The vertical facet position channel, for mark-level faceting, bound to the\n*fy* scale." + }, + "href": { + "$ref": "#/definitions/ChannelValue", + "description": "The [href][1]; a channel specifying URLs for clickable links. May be used in conjunction with the **target** option to open links in another window.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/href" + }, + "imageFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A CSS [filter][1]; a constant string used to adjust the rendering of images, such as *blur(5px)*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/filter" + }, + "length": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vector’s length; either an optional channel bound to the *length* scale or a constant number in pixels. Defaults to 12 pixels." + }, + "margin": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four mark margins: **marginTop**,\n**marginRight**, **marginBottom**, and **marginLeft**; typically defaults to 0, except for axis marks." + }, + "marginBottom": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s bottom margin; the minimum distance in pixels between the bottom edges of the inner and outer plot area." + }, + "marginLeft": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s left margin; the minimum distance in pixels between the left edges of the inner and outer plot area." + }, + "marginRight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s right margin; the minimum distance in pixels between the right edges of the mark’s inner and outer plot area." + }, + "marginTop": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s top margin; the minimum distance in pixels between the top edges of the inner and outer plot area." + }, + "mark": { + "const": "vector", + "description": "A vector mark.\n\nIf none of **frameAnchor**, **x**, and **y** are specified, then **x** and\n**y** default to accessors assuming that *data* contains tuples [[*x₀*,\n*y₀*], [*x₁*, *y₁*], [*x₂*, *y₂*], …]", + "type": "string" + }, + "meta": { + "$ref": "#/definitions/Meta", + "description": "Specification metadata." + }, + "mixBlendMode": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [mix-blend-mode][1]; a constant string specifying how to blend content such as *multiply*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode" + }, + "opacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally. For faster rendering, prefer the **strokeOpacity** or **fillOpacity** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/opacity" + }, + "paintOrder": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [paint-order][1]; a constant string specifying the order in which the\n**fill**, **stroke**, and any markers are drawn; defaults to *normal*, which draws the fill, then stroke, then markers; defaults to *stroke* for the text mark to create a “halo” around text to improve legibility.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/paint-order" + }, + "params": { + "$ref": "#/definitions/Params", + "description": "Param and Selection definitions." + }, + "plotDefaults": { + "$ref": "#/definitions/PlotAttributes", + "description": "A default set of attributes to apply to all plot components." + }, + "pointerEvents": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [pointer-events][1] property; a constant string such as *none*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/pointer-events" + }, + "r": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The vector shape’s radius, such as half the width of the *arrow*’s head or the *spike*’s base; a constant number in pixels. Defaults to 3.5 pixels." + }, + "reverse": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Applies a transform to reverse the order of the mark’s index, say for reverse input order." + }, + "rotate": { + "$ref": "#/definitions/ChannelValue", + "description": "The vector’s orientation (rotation angle); either a constant number in degrees clockwise, or an optional channel (with no associated scale). Defaults to 0 degrees with the vector pointing up." + }, + "select": { + "$ref": "#/definitions/SelectFilter", + "description": "Applies a filter transform after data is loaded to highlight selected values only. For example, `first` and `last` select the first or last values of series only (using the *z* channel to separate series). Meanwhile, `nearestX` and `nearestY` select the point nearest to the pointer along the *x* or *y* channel dimension. Unlike Mosaic selections, a mark level *select* is internal to the mark only, and does not populate a param or selection value to be shared across clients.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "shape": { + "anyOf": [ + { + "$ref": "#/definitions/VectorShape" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The shape of the vector; a constant. Defaults to *arrow*." + }, + "shapeRendering": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [shape-rendering][1]; a constant string such as *crispEdges*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/shape-rendering" + }, + "sort": { + "anyOf": [ + { + "$ref": "#/definitions/SortOrder" + }, + { + "$ref": "#/definitions/ChannelDomainSort" + } + ], + "description": "Either applies a transform to sort the mark’s index by the specified channel values, or imputes ordinal scale domains from this mark’s channels.\n\nWhen imputing ordinal scale domains from channel values, the **sort** option is an object whose keys are ordinal scale names such as *x* or *fx*, and whose values are channel names such as *y*, *y1*, or *y2*. For example, to impute the *y* scale’s domain from the associated *x* channel values in ascending order:\n\n```js sort: {y: \"x\"} ```\n\nFor different sort options for different scales, replace the channel name with a *value* object and per-scale options:\n\n```js sort: {y: {value: \"-x\"}} ```\n\nWhen sorting the mark’s index, the **sort** option is instead one of:\n\n- a channel value definition for sorting given values in ascending order\n- a {value, order} object for sorting given values\n- a {channel, order} object for sorting the named channel’s values" + }, + "stroke": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke" + }, + "strokeDasharray": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dasharray][1]; a constant number indicating the length in pixels of alternating dashes and gaps, or a constant string of numbers separated by spaces or commas (_e.g._, *10 2* for dashes of 10 pixels separated by gaps of 2 pixels), or *none* (the default) for no dashing\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dasharray" + }, + "strokeDashoffset": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dashoffset][1]; a constant indicating the offset in pixels of the first dash along the stroke; defaults to zero.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dashoffset" + }, + "strokeLinecap": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linecap][1]; a constant specifying how to cap stroked paths, such as *butt*, *round*, or *square*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linecap" + }, + "strokeLinejoin": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linejoin][1]; a constant specifying how to join stroked paths, such as *bevel*, *miter*, *miter-clip*, or *round*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linejoin" + }, + "strokeMiterlimit": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-miterlimit][1]; a constant number specifying how to limit the length of *miter* joins on stroked paths.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-miterlimit" + }, + "strokeOpacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-opacity" + }, + "strokeWidth": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-width][1]; a constant number in pixels, or a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-width" + }, + "target": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [target][1]; a constant string specifying the target window (_e.g._,\n*_blank*) for clickable links; used in conjunction with the **href** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/target" + }, + "tip": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/TipPointer" + }, + { + "properties": { + "anchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The tip anchor specifies how to orient the tip box relative to its anchor position; it refers to the part of the tip box that is attached to the anchor point. For example, the *top-left* anchor places the top-left corner of tip box near the anchor position, hence placing the tip box below and to the right of the anchor position." + }, + "fontFamily": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font-family][1]; a constant; defaults to the plot’s font family, which is typically [*system-ui*][2].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-family [2]: https://drafts.csswg.org/css-fonts-4/#valdef-font-family-system-ui" + }, + "fontSize": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font size][1] in pixels; either a constant or a channel; defaults to the plot’s font size, which is typically 10. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-size" + }, + "fontStyle": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font style][1]; a constant; defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-style" + }, + "fontVariant": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font variant][1]; a constant; if the **text** channel contains numbers or dates, defaults to *tabular-nums* to facilitate comparing numbers; otherwise defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant" + }, + "fontWeight": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font weight][1]; a constant; defaults to the plot’s font weight, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight" + }, + "format": { + "additionalProperties": false, + "description": "How channel values are formatted for display. If a format is a string, it is interpreted as a (UTC) time format for temporal channels, and otherwise a number format.", + "properties": { + "ariaLabel": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fill": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fillOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fontSize": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fx": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fy": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "geometry": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "height": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "href": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "length": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "opacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "path": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "r": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "rotate": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "src": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "stroke": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeWidth": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "symbol": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "text": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "title": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "weight": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "width": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "z": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + } + }, + "type": "object" + }, + "frameAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The frame anchor specifies defaults for **x** and **y** based on the plot’s frame; it may be one of the four sides (*top*, *right*, *bottom*, *left*), one of the four corners (*top-left*, *top-right*, *bottom-right*,\n*bottom-left*), or the *middle* of the frame. For example, for tips distributed horizontally at the top of the frame:\n\n```js Plot.tip(data, {x: \"date\", frameAnchor: \"top\"}) ```" + }, + "lineHeight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line height in ems; defaults to 1. The line height affects the (typically vertical) separation between adjacent baselines of text, as well as the separation between the text and its anchor point." + }, + "lineWidth": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line width in ems (e.g., 10 for about 20 characters); defaults to infinity, disabling wrapping and clipping.\n\nIf **textOverflow** is null, lines will be wrapped at the specified length. If a line is split at a soft hyphen (\\xad), a hyphen (-) will be displayed at the end of the line. If **textOverflow** is not null, lines will be clipped according to the given strategy." + }, + "monospace": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, changes the default **fontFamily** to *monospace*, and uses simplified monospaced text metrics calculations." + }, + "pathFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The image filter for the tip’s box; defaults to a drop shadow." + }, + "pointer": { + "$ref": "#/definitions/TipPointer" + }, + "pointerSize": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The size of the tip’s pointer in pixels; defaults to 12." + }, + "preferredAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If an explicit tip anchor is not specified, an anchor is chosen automatically such that the tip fits within the plot’s frame; if the preferred anchor fits, it is chosen." + }, + "textAnchor": { + "anyOf": [ + { + "const": "start", + "type": "string" + }, + { + "const": "middle", + "type": "string" + }, + { + "const": "end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [text anchor][1] controls how text is aligned (typically horizontally) relative to its anchor point; it is one of *start*, *end*, or *middle*. If the frame anchor is *left*, *top-left*, or *bottom-left*, the default text anchor is *start*; if the frame anchor is *right*, *top-right*, or\n*bottom-right*, the default is *end*; otherwise it is *middle*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/text-anchor" + }, + "textOverflow": { + "anyOf": [ + { + "type": "null" + }, + { + "const": "clip", + "type": "string" + }, + { + "const": "ellipsis", + "type": "string" + }, + { + "const": "clip-start", + "type": "string" + }, + { + "const": "clip-end", + "type": "string" + }, + { + "const": "ellipsis-start", + "type": "string" + }, + { + "const": "ellipsis-middle", + "type": "string" + }, + { + "const": "ellipsis-end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How truncate (or wrap) lines of text longer than the given **lineWidth**; one of:\n\n- null (default) - preserve overflowing characters (and wrap if needed)\n- *clip* or *clip-end* - remove characters from the end\n- *clip-start* - remove characters from the start\n- *ellipsis* or *ellipsis-end* - replace characters from the end with an ellipsis (…)\n- *ellipsis-start* - replace characters from the start with an ellipsis (…)\n- *ellipsis-middle* - replace characters from the middle with an ellipsis (…)\n\nIf no **title** was specified, if text requires truncation, a title containing the non-truncated text will be implicitly added." + }, + "textPadding": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The padding around the text in pixels; defaults to 8." + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + } + }, + "type": "object" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to generate a tooltip for this mark, and any tip options." + }, + "title": { + "$ref": "#/definitions/ChannelValue", + "description": "The title; a channel specifying accessible, short textual descriptions as strings (possibly with newlines). If the tip option is specified, the title will be displayed with an interactive tooltip instead of using the SVG [title element][1].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/title" + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position of the vector’s anchor point; an optional channel bound to the *x* scale. Default depends on the **frameAnchor**." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position of the vector’s anchor point; an optional channel bound to the *y* scale. Default depends on the **frameAnchor**." + } + }, + "required": [ + "data", + "mark" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "$schema": { + "description": "A [JSON schema](http://json-schema.org/) URL for this specification, such as https://uwdata.github.io/mosaic/schema/latest.json. This property enables validation and autocomplete in editors with JSON schema support.", + "format": "uri", + "type": "string" + }, + "anchor": { + "anyOf": [ + { + "const": "start", + "type": "string" + }, + { + "const": "middle", + "type": "string" + }, + { + "const": "end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The vector’s position along its orientation relative to its anchor point; a constant. Assuming a default **rotate** angle of 0°, one of:\n\n- *start* - from [*x*, *y*] to [*x*, *y* - *l*]\n- *middle* (default) - from [*x*, *y* + *l* / 2] to [*x*, *y* - *l* / 2]\n- *end* - from [*x*, *y* + *l*] to [*x*, *y*]\n\nwhere [*x*, *y*] is the vector’s anchor point and *l* is the vector’s (possibly scaled) length in pixels." + }, + "ariaDescription": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-description][1]; a constant textual description.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-description" + }, + "ariaHidden": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-hidden][1] state; a constant indicating whether the element is exposed to an accessibility API.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-hidden" + }, + "ariaLabel": { + "$ref": "#/definitions/ChannelValue", + "description": "The [aria-label][1]; a channel specifying short textual labels representing the value in the accessibility tree.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-label" + }, + "clip": { + "anyOf": [ + { + "const": "frame", + "type": "string" + }, + { + "const": "sphere", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to clip the mark; one of:\n\n- *frame* or true - clip to the plot’s frame (inner area)\n- *sphere* - clip to the projected sphere (*e.g.*, front hemisphere)\n- null or false - do not clip\n\nThe *sphere* clip option requires a geographic projection." + }, + "config": { + "$ref": "#/definitions/Config", + "description": "Configuration options." + }, + "data": { + "$ref": "#/definitions/Data", + "description": "Dataset definitions." + }, + "dx": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The horizontal offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "dy": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The vertical offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "facet": { + "anyOf": [ + { + "const": "auto", + "type": "string" + }, + { + "const": "include", + "type": "string" + }, + { + "const": "exclude", + "type": "string" + }, + { + "const": "super", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to enable or disable faceting; one of:\n\n- *auto* (default) - automatically determine if this mark should be faceted\n- *include* (or true) - draw the subset of the mark’s data in the current facet\n- *exclude* - draw the subset of the mark’s data *not* in the current facet\n- *super* - draw this mark in a single frame that covers all facets\n- null (or false) - repeat this mark’s data across all facets (*i.e.*, no faceting)\n\nWhen a mark uses *super* faceting, it is not allowed to use position scales (*x*, *y*, *fx*, or *fy*); *super* faceting is intended for decorations, such as labels and legends.\n\nWhen top-level faceting is used, the default *auto* setting is equivalent to *include* when the mark data is strictly equal to the top-level facet data; otherwise it is equivalent to null. When the *include* or *exclude* facet mode is chosen, the mark data must be parallel to the top-level facet data: the data must have the same length and order. If the data are not parallel, then the wrong data may be shown in each facet. The default\n*auto* therefore requires strict equality (`===`) for safety, and using the facet data as mark data is recommended when using the *exclude* facet mode. (To construct parallel data safely, consider using [*array*.map][1] on the facet data.)\n\nWhen mark-level faceting is used, the default *auto* setting is equivalent to *include*: the mark will be faceted if either the **fx** or **fy** channel option (or both) is specified. The null or false option will disable faceting, while *exclude* draws the subset of the mark’s data *not* in the current facet.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map" + }, + "facetAnchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "right", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "const": "left", + "type": "string" + }, + { + "const": "top-left", + "type": "string" + }, + { + "const": "top-right", + "type": "string" + }, + { + "const": "bottom-left", + "type": "string" + }, + { + "const": "bottom-right", + "type": "string" + }, + { + "const": "top-empty", + "type": "string" + }, + { + "const": "right-empty", + "type": "string" + }, + { + "const": "bottom-empty", + "type": "string" + }, + { + "const": "left-empty", + "type": "string" + }, + { + "const": "empty", + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to place the mark with respect to facets; one of:\n\n- null (default for most marks) - display the mark in each non-empty facet\n- *top*, *right*, *bottom*, or *left* - display the mark only in facets on the given side\n- *top-empty*, *right-empty*, *bottom-empty*, or *left-empty* (default for axis marks) - display the mark only in facets that have empty space on the given side: either the margin, or an empty facet\n- *empty* - display the mark in empty facets only" + }, + "fill": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill" + }, + "fillOpacity": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill-opacity][1]; a constant number between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill-opacity" + }, + "filter": { + "$ref": "#/definitions/ChannelValue", + "description": "Applies a transform to filter the mark’s index according to the given channel values; only truthy values are retained.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "frameAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The vector’s frame anchor, to default **x** and **y** relative to the frame; a constant representing one of the frame corners (*top-left*,\n*top-right*, *bottom-right*, *bottom-left*), sides (*top*, *right*,\n*bottom*, *left*), or *middle* (default). Has no effect if both **x** and **y** are specified." + }, + "fx": { + "$ref": "#/definitions/ChannelValue", + "description": "The horizontal facet position channel, for mark-level faceting, bound to the *fx* scale." + }, + "fy": { + "$ref": "#/definitions/ChannelValue", + "description": "The vertical facet position channel, for mark-level faceting, bound to the\n*fy* scale." + }, + "href": { + "$ref": "#/definitions/ChannelValue", + "description": "The [href][1]; a channel specifying URLs for clickable links. May be used in conjunction with the **target** option to open links in another window.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/href" + }, + "imageFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A CSS [filter][1]; a constant string used to adjust the rendering of images, such as *blur(5px)*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/filter" + }, + "length": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vector’s length; either an optional channel bound to the *length* scale or a constant number in pixels. Defaults to 12 pixels." + }, + "margin": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four mark margins: **marginTop**,\n**marginRight**, **marginBottom**, and **marginLeft**; typically defaults to 0, except for axis marks." + }, + "marginBottom": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s bottom margin; the minimum distance in pixels between the bottom edges of the inner and outer plot area." + }, + "marginLeft": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s left margin; the minimum distance in pixels between the left edges of the inner and outer plot area." + }, + "marginRight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s right margin; the minimum distance in pixels between the right edges of the mark’s inner and outer plot area." + }, + "marginTop": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s top margin; the minimum distance in pixels between the top edges of the inner and outer plot area." + }, + "mark": { + "const": "vectorX", + "description": "Like vector, but **x** instead defaults to the identity function and **y** defaults to null, assuming that *data* is an array of numbers [*x₀*, *x₁*,\n*x₂*, …].", + "type": "string" + }, + "meta": { + "$ref": "#/definitions/Meta", + "description": "Specification metadata." + }, + "mixBlendMode": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [mix-blend-mode][1]; a constant string specifying how to blend content such as *multiply*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode" + }, + "opacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally. For faster rendering, prefer the **strokeOpacity** or **fillOpacity** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/opacity" + }, + "paintOrder": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [paint-order][1]; a constant string specifying the order in which the\n**fill**, **stroke**, and any markers are drawn; defaults to *normal*, which draws the fill, then stroke, then markers; defaults to *stroke* for the text mark to create a “halo” around text to improve legibility.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/paint-order" + }, + "params": { + "$ref": "#/definitions/Params", + "description": "Param and Selection definitions." + }, + "plotDefaults": { + "$ref": "#/definitions/PlotAttributes", + "description": "A default set of attributes to apply to all plot components." + }, + "pointerEvents": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [pointer-events][1] property; a constant string such as *none*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/pointer-events" + }, + "r": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The vector shape’s radius, such as half the width of the *arrow*’s head or the *spike*’s base; a constant number in pixels. Defaults to 3.5 pixels." + }, + "reverse": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Applies a transform to reverse the order of the mark’s index, say for reverse input order." + }, + "rotate": { + "$ref": "#/definitions/ChannelValue", + "description": "The vector’s orientation (rotation angle); either a constant number in degrees clockwise, or an optional channel (with no associated scale). Defaults to 0 degrees with the vector pointing up." + }, + "select": { + "$ref": "#/definitions/SelectFilter", + "description": "Applies a filter transform after data is loaded to highlight selected values only. For example, `first` and `last` select the first or last values of series only (using the *z* channel to separate series). Meanwhile, `nearestX` and `nearestY` select the point nearest to the pointer along the *x* or *y* channel dimension. Unlike Mosaic selections, a mark level *select* is internal to the mark only, and does not populate a param or selection value to be shared across clients.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "shape": { + "anyOf": [ + { + "$ref": "#/definitions/VectorShape" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The shape of the vector; a constant. Defaults to *arrow*." + }, + "shapeRendering": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [shape-rendering][1]; a constant string such as *crispEdges*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/shape-rendering" + }, + "sort": { + "anyOf": [ + { + "$ref": "#/definitions/SortOrder" + }, + { + "$ref": "#/definitions/ChannelDomainSort" + } + ], + "description": "Either applies a transform to sort the mark’s index by the specified channel values, or imputes ordinal scale domains from this mark’s channels.\n\nWhen imputing ordinal scale domains from channel values, the **sort** option is an object whose keys are ordinal scale names such as *x* or *fx*, and whose values are channel names such as *y*, *y1*, or *y2*. For example, to impute the *y* scale’s domain from the associated *x* channel values in ascending order:\n\n```js sort: {y: \"x\"} ```\n\nFor different sort options for different scales, replace the channel name with a *value* object and per-scale options:\n\n```js sort: {y: {value: \"-x\"}} ```\n\nWhen sorting the mark’s index, the **sort** option is instead one of:\n\n- a channel value definition for sorting given values in ascending order\n- a {value, order} object for sorting given values\n- a {channel, order} object for sorting the named channel’s values" + }, + "stroke": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke" + }, + "strokeDasharray": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dasharray][1]; a constant number indicating the length in pixels of alternating dashes and gaps, or a constant string of numbers separated by spaces or commas (_e.g._, *10 2* for dashes of 10 pixels separated by gaps of 2 pixels), or *none* (the default) for no dashing\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dasharray" + }, + "strokeDashoffset": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dashoffset][1]; a constant indicating the offset in pixels of the first dash along the stroke; defaults to zero.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dashoffset" + }, + "strokeLinecap": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linecap][1]; a constant specifying how to cap stroked paths, such as *butt*, *round*, or *square*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linecap" + }, + "strokeLinejoin": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linejoin][1]; a constant specifying how to join stroked paths, such as *bevel*, *miter*, *miter-clip*, or *round*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linejoin" + }, + "strokeMiterlimit": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-miterlimit][1]; a constant number specifying how to limit the length of *miter* joins on stroked paths.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-miterlimit" + }, + "strokeOpacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-opacity" + }, + "strokeWidth": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-width][1]; a constant number in pixels, or a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-width" + }, + "target": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [target][1]; a constant string specifying the target window (_e.g._,\n*_blank*) for clickable links; used in conjunction with the **href** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/target" + }, + "tip": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/TipPointer" + }, + { + "properties": { + "anchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The tip anchor specifies how to orient the tip box relative to its anchor position; it refers to the part of the tip box that is attached to the anchor point. For example, the *top-left* anchor places the top-left corner of tip box near the anchor position, hence placing the tip box below and to the right of the anchor position." + }, + "fontFamily": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font-family][1]; a constant; defaults to the plot’s font family, which is typically [*system-ui*][2].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-family [2]: https://drafts.csswg.org/css-fonts-4/#valdef-font-family-system-ui" + }, + "fontSize": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font size][1] in pixels; either a constant or a channel; defaults to the plot’s font size, which is typically 10. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-size" + }, + "fontStyle": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font style][1]; a constant; defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-style" + }, + "fontVariant": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font variant][1]; a constant; if the **text** channel contains numbers or dates, defaults to *tabular-nums* to facilitate comparing numbers; otherwise defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant" + }, + "fontWeight": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font weight][1]; a constant; defaults to the plot’s font weight, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight" + }, + "format": { + "additionalProperties": false, + "description": "How channel values are formatted for display. If a format is a string, it is interpreted as a (UTC) time format for temporal channels, and otherwise a number format.", + "properties": { + "ariaLabel": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fill": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fillOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fontSize": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fx": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fy": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "geometry": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "height": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "href": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "length": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "opacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "path": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "r": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "rotate": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "src": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "stroke": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeWidth": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "symbol": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "text": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "title": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "weight": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "width": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "z": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + } + }, + "type": "object" + }, + "frameAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The frame anchor specifies defaults for **x** and **y** based on the plot’s frame; it may be one of the four sides (*top*, *right*, *bottom*, *left*), one of the four corners (*top-left*, *top-right*, *bottom-right*,\n*bottom-left*), or the *middle* of the frame. For example, for tips distributed horizontally at the top of the frame:\n\n```js Plot.tip(data, {x: \"date\", frameAnchor: \"top\"}) ```" + }, + "lineHeight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line height in ems; defaults to 1. The line height affects the (typically vertical) separation between adjacent baselines of text, as well as the separation between the text and its anchor point." + }, + "lineWidth": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line width in ems (e.g., 10 for about 20 characters); defaults to infinity, disabling wrapping and clipping.\n\nIf **textOverflow** is null, lines will be wrapped at the specified length. If a line is split at a soft hyphen (\\xad), a hyphen (-) will be displayed at the end of the line. If **textOverflow** is not null, lines will be clipped according to the given strategy." + }, + "monospace": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, changes the default **fontFamily** to *monospace*, and uses simplified monospaced text metrics calculations." + }, + "pathFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The image filter for the tip’s box; defaults to a drop shadow." + }, + "pointer": { + "$ref": "#/definitions/TipPointer" + }, + "pointerSize": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The size of the tip’s pointer in pixels; defaults to 12." + }, + "preferredAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If an explicit tip anchor is not specified, an anchor is chosen automatically such that the tip fits within the plot’s frame; if the preferred anchor fits, it is chosen." + }, + "textAnchor": { + "anyOf": [ + { + "const": "start", + "type": "string" + }, + { + "const": "middle", + "type": "string" + }, + { + "const": "end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [text anchor][1] controls how text is aligned (typically horizontally) relative to its anchor point; it is one of *start*, *end*, or *middle*. If the frame anchor is *left*, *top-left*, or *bottom-left*, the default text anchor is *start*; if the frame anchor is *right*, *top-right*, or\n*bottom-right*, the default is *end*; otherwise it is *middle*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/text-anchor" + }, + "textOverflow": { + "anyOf": [ + { + "type": "null" + }, + { + "const": "clip", + "type": "string" + }, + { + "const": "ellipsis", + "type": "string" + }, + { + "const": "clip-start", + "type": "string" + }, + { + "const": "clip-end", + "type": "string" + }, + { + "const": "ellipsis-start", + "type": "string" + }, + { + "const": "ellipsis-middle", + "type": "string" + }, + { + "const": "ellipsis-end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How truncate (or wrap) lines of text longer than the given **lineWidth**; one of:\n\n- null (default) - preserve overflowing characters (and wrap if needed)\n- *clip* or *clip-end* - remove characters from the end\n- *clip-start* - remove characters from the start\n- *ellipsis* or *ellipsis-end* - replace characters from the end with an ellipsis (…)\n- *ellipsis-start* - replace characters from the start with an ellipsis (…)\n- *ellipsis-middle* - replace characters from the middle with an ellipsis (…)\n\nIf no **title** was specified, if text requires truncation, a title containing the non-truncated text will be implicitly added." + }, + "textPadding": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The padding around the text in pixels; defaults to 8." + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + } + }, + "type": "object" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to generate a tooltip for this mark, and any tip options." + }, + "title": { + "$ref": "#/definitions/ChannelValue", + "description": "The title; a channel specifying accessible, short textual descriptions as strings (possibly with newlines). If the tip option is specified, the title will be displayed with an interactive tooltip instead of using the SVG [title element][1].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/title" + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position of the vector’s anchor point; an optional channel bound to the *x* scale. Default depends on the **frameAnchor**." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position of the vector’s anchor point; an optional channel bound to the *y* scale. Default depends on the **frameAnchor**." + } + }, + "required": [ + "data", + "mark" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "$schema": { + "description": "A [JSON schema](http://json-schema.org/) URL for this specification, such as https://uwdata.github.io/mosaic/schema/latest.json. This property enables validation and autocomplete in editors with JSON schema support.", + "format": "uri", + "type": "string" + }, + "anchor": { + "anyOf": [ + { + "const": "start", + "type": "string" + }, + { + "const": "middle", + "type": "string" + }, + { + "const": "end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The vector’s position along its orientation relative to its anchor point; a constant. Assuming a default **rotate** angle of 0°, one of:\n\n- *start* - from [*x*, *y*] to [*x*, *y* - *l*]\n- *middle* (default) - from [*x*, *y* + *l* / 2] to [*x*, *y* - *l* / 2]\n- *end* - from [*x*, *y* + *l*] to [*x*, *y*]\n\nwhere [*x*, *y*] is the vector’s anchor point and *l* is the vector’s (possibly scaled) length in pixels." + }, + "ariaDescription": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-description][1]; a constant textual description.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-description" + }, + "ariaHidden": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-hidden][1] state; a constant indicating whether the element is exposed to an accessibility API.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-hidden" + }, + "ariaLabel": { + "$ref": "#/definitions/ChannelValue", + "description": "The [aria-label][1]; a channel specifying short textual labels representing the value in the accessibility tree.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-label" + }, + "clip": { + "anyOf": [ + { + "const": "frame", + "type": "string" + }, + { + "const": "sphere", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to clip the mark; one of:\n\n- *frame* or true - clip to the plot’s frame (inner area)\n- *sphere* - clip to the projected sphere (*e.g.*, front hemisphere)\n- null or false - do not clip\n\nThe *sphere* clip option requires a geographic projection." + }, + "config": { + "$ref": "#/definitions/Config", + "description": "Configuration options." + }, + "data": { + "$ref": "#/definitions/Data", + "description": "Dataset definitions." + }, + "dx": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The horizontal offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "dy": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The vertical offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "facet": { + "anyOf": [ + { + "const": "auto", + "type": "string" + }, + { + "const": "include", + "type": "string" + }, + { + "const": "exclude", + "type": "string" + }, + { + "const": "super", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to enable or disable faceting; one of:\n\n- *auto* (default) - automatically determine if this mark should be faceted\n- *include* (or true) - draw the subset of the mark’s data in the current facet\n- *exclude* - draw the subset of the mark’s data *not* in the current facet\n- *super* - draw this mark in a single frame that covers all facets\n- null (or false) - repeat this mark’s data across all facets (*i.e.*, no faceting)\n\nWhen a mark uses *super* faceting, it is not allowed to use position scales (*x*, *y*, *fx*, or *fy*); *super* faceting is intended for decorations, such as labels and legends.\n\nWhen top-level faceting is used, the default *auto* setting is equivalent to *include* when the mark data is strictly equal to the top-level facet data; otherwise it is equivalent to null. When the *include* or *exclude* facet mode is chosen, the mark data must be parallel to the top-level facet data: the data must have the same length and order. If the data are not parallel, then the wrong data may be shown in each facet. The default\n*auto* therefore requires strict equality (`===`) for safety, and using the facet data as mark data is recommended when using the *exclude* facet mode. (To construct parallel data safely, consider using [*array*.map][1] on the facet data.)\n\nWhen mark-level faceting is used, the default *auto* setting is equivalent to *include*: the mark will be faceted if either the **fx** or **fy** channel option (or both) is specified. The null or false option will disable faceting, while *exclude* draws the subset of the mark’s data *not* in the current facet.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map" + }, + "facetAnchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "right", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "const": "left", + "type": "string" + }, + { + "const": "top-left", + "type": "string" + }, + { + "const": "top-right", + "type": "string" + }, + { + "const": "bottom-left", + "type": "string" + }, + { + "const": "bottom-right", + "type": "string" + }, + { + "const": "top-empty", + "type": "string" + }, + { + "const": "right-empty", + "type": "string" + }, + { + "const": "bottom-empty", + "type": "string" + }, + { + "const": "left-empty", + "type": "string" + }, + { + "const": "empty", + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to place the mark with respect to facets; one of:\n\n- null (default for most marks) - display the mark in each non-empty facet\n- *top*, *right*, *bottom*, or *left* - display the mark only in facets on the given side\n- *top-empty*, *right-empty*, *bottom-empty*, or *left-empty* (default for axis marks) - display the mark only in facets that have empty space on the given side: either the margin, or an empty facet\n- *empty* - display the mark in empty facets only" + }, + "fill": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill" + }, + "fillOpacity": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill-opacity][1]; a constant number between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill-opacity" + }, + "filter": { + "$ref": "#/definitions/ChannelValue", + "description": "Applies a transform to filter the mark’s index according to the given channel values; only truthy values are retained.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "frameAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The vector’s frame anchor, to default **x** and **y** relative to the frame; a constant representing one of the frame corners (*top-left*,\n*top-right*, *bottom-right*, *bottom-left*), sides (*top*, *right*,\n*bottom*, *left*), or *middle* (default). Has no effect if both **x** and **y** are specified." + }, + "fx": { + "$ref": "#/definitions/ChannelValue", + "description": "The horizontal facet position channel, for mark-level faceting, bound to the *fx* scale." + }, + "fy": { + "$ref": "#/definitions/ChannelValue", + "description": "The vertical facet position channel, for mark-level faceting, bound to the\n*fy* scale." + }, + "href": { + "$ref": "#/definitions/ChannelValue", + "description": "The [href][1]; a channel specifying URLs for clickable links. May be used in conjunction with the **target** option to open links in another window.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/href" + }, + "imageFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A CSS [filter][1]; a constant string used to adjust the rendering of images, such as *blur(5px)*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/filter" + }, + "length": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vector’s length; either an optional channel bound to the *length* scale or a constant number in pixels. Defaults to 12 pixels." + }, + "margin": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four mark margins: **marginTop**,\n**marginRight**, **marginBottom**, and **marginLeft**; typically defaults to 0, except for axis marks." + }, + "marginBottom": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s bottom margin; the minimum distance in pixels between the bottom edges of the inner and outer plot area." + }, + "marginLeft": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s left margin; the minimum distance in pixels between the left edges of the inner and outer plot area." + }, + "marginRight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s right margin; the minimum distance in pixels between the right edges of the mark’s inner and outer plot area." + }, + "marginTop": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s top margin; the minimum distance in pixels between the top edges of the inner and outer plot area." + }, + "mark": { + "const": "vectorY", + "description": "Like vector, but **y** instead defaults to the identity function and **x** defaults to null, assuming that *data* is an array of numbers [*y₀*, *y₁*,\n*y₂*, …].", + "type": "string" + }, + "meta": { + "$ref": "#/definitions/Meta", + "description": "Specification metadata." + }, + "mixBlendMode": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [mix-blend-mode][1]; a constant string specifying how to blend content such as *multiply*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode" + }, + "opacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally. For faster rendering, prefer the **strokeOpacity** or **fillOpacity** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/opacity" + }, + "paintOrder": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [paint-order][1]; a constant string specifying the order in which the\n**fill**, **stroke**, and any markers are drawn; defaults to *normal*, which draws the fill, then stroke, then markers; defaults to *stroke* for the text mark to create a “halo” around text to improve legibility.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/paint-order" + }, + "params": { + "$ref": "#/definitions/Params", + "description": "Param and Selection definitions." + }, + "plotDefaults": { + "$ref": "#/definitions/PlotAttributes", + "description": "A default set of attributes to apply to all plot components." + }, + "pointerEvents": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [pointer-events][1] property; a constant string such as *none*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/pointer-events" + }, + "r": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The vector shape’s radius, such as half the width of the *arrow*’s head or the *spike*’s base; a constant number in pixels. Defaults to 3.5 pixels." + }, + "reverse": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Applies a transform to reverse the order of the mark’s index, say for reverse input order." + }, + "rotate": { + "$ref": "#/definitions/ChannelValue", + "description": "The vector’s orientation (rotation angle); either a constant number in degrees clockwise, or an optional channel (with no associated scale). Defaults to 0 degrees with the vector pointing up." + }, + "select": { + "$ref": "#/definitions/SelectFilter", + "description": "Applies a filter transform after data is loaded to highlight selected values only. For example, `first` and `last` select the first or last values of series only (using the *z* channel to separate series). Meanwhile, `nearestX` and `nearestY` select the point nearest to the pointer along the *x* or *y* channel dimension. Unlike Mosaic selections, a mark level *select* is internal to the mark only, and does not populate a param or selection value to be shared across clients.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "shape": { + "anyOf": [ + { + "$ref": "#/definitions/VectorShape" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The shape of the vector; a constant. Defaults to *arrow*." + }, + "shapeRendering": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [shape-rendering][1]; a constant string such as *crispEdges*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/shape-rendering" + }, + "sort": { + "anyOf": [ + { + "$ref": "#/definitions/SortOrder" + }, + { + "$ref": "#/definitions/ChannelDomainSort" + } + ], + "description": "Either applies a transform to sort the mark’s index by the specified channel values, or imputes ordinal scale domains from this mark’s channels.\n\nWhen imputing ordinal scale domains from channel values, the **sort** option is an object whose keys are ordinal scale names such as *x* or *fx*, and whose values are channel names such as *y*, *y1*, or *y2*. For example, to impute the *y* scale’s domain from the associated *x* channel values in ascending order:\n\n```js sort: {y: \"x\"} ```\n\nFor different sort options for different scales, replace the channel name with a *value* object and per-scale options:\n\n```js sort: {y: {value: \"-x\"}} ```\n\nWhen sorting the mark’s index, the **sort** option is instead one of:\n\n- a channel value definition for sorting given values in ascending order\n- a {value, order} object for sorting given values\n- a {channel, order} object for sorting the named channel’s values" + }, + "stroke": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke" + }, + "strokeDasharray": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dasharray][1]; a constant number indicating the length in pixels of alternating dashes and gaps, or a constant string of numbers separated by spaces or commas (_e.g._, *10 2* for dashes of 10 pixels separated by gaps of 2 pixels), or *none* (the default) for no dashing\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dasharray" + }, + "strokeDashoffset": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dashoffset][1]; a constant indicating the offset in pixels of the first dash along the stroke; defaults to zero.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dashoffset" + }, + "strokeLinecap": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linecap][1]; a constant specifying how to cap stroked paths, such as *butt*, *round*, or *square*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linecap" + }, + "strokeLinejoin": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linejoin][1]; a constant specifying how to join stroked paths, such as *bevel*, *miter*, *miter-clip*, or *round*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linejoin" + }, + "strokeMiterlimit": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-miterlimit][1]; a constant number specifying how to limit the length of *miter* joins on stroked paths.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-miterlimit" + }, + "strokeOpacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-opacity" + }, + "strokeWidth": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-width][1]; a constant number in pixels, or a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-width" + }, + "target": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [target][1]; a constant string specifying the target window (_e.g._,\n*_blank*) for clickable links; used in conjunction with the **href** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/target" + }, + "tip": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/TipPointer" + }, + { + "properties": { + "anchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The tip anchor specifies how to orient the tip box relative to its anchor position; it refers to the part of the tip box that is attached to the anchor point. For example, the *top-left* anchor places the top-left corner of tip box near the anchor position, hence placing the tip box below and to the right of the anchor position." + }, + "fontFamily": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font-family][1]; a constant; defaults to the plot’s font family, which is typically [*system-ui*][2].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-family [2]: https://drafts.csswg.org/css-fonts-4/#valdef-font-family-system-ui" + }, + "fontSize": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font size][1] in pixels; either a constant or a channel; defaults to the plot’s font size, which is typically 10. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-size" + }, + "fontStyle": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font style][1]; a constant; defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-style" + }, + "fontVariant": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font variant][1]; a constant; if the **text** channel contains numbers or dates, defaults to *tabular-nums* to facilitate comparing numbers; otherwise defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant" + }, + "fontWeight": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font weight][1]; a constant; defaults to the plot’s font weight, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight" + }, + "format": { + "additionalProperties": false, + "description": "How channel values are formatted for display. If a format is a string, it is interpreted as a (UTC) time format for temporal channels, and otherwise a number format.", + "properties": { + "ariaLabel": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fill": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fillOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fontSize": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fx": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fy": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "geometry": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "height": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "href": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "length": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "opacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "path": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "r": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "rotate": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "src": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "stroke": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeWidth": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "symbol": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "text": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "title": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "weight": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "width": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "z": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + } + }, + "type": "object" + }, + "frameAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The frame anchor specifies defaults for **x** and **y** based on the plot’s frame; it may be one of the four sides (*top*, *right*, *bottom*, *left*), one of the four corners (*top-left*, *top-right*, *bottom-right*,\n*bottom-left*), or the *middle* of the frame. For example, for tips distributed horizontally at the top of the frame:\n\n```js Plot.tip(data, {x: \"date\", frameAnchor: \"top\"}) ```" + }, + "lineHeight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line height in ems; defaults to 1. The line height affects the (typically vertical) separation between adjacent baselines of text, as well as the separation between the text and its anchor point." + }, + "lineWidth": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line width in ems (e.g., 10 for about 20 characters); defaults to infinity, disabling wrapping and clipping.\n\nIf **textOverflow** is null, lines will be wrapped at the specified length. If a line is split at a soft hyphen (\\xad), a hyphen (-) will be displayed at the end of the line. If **textOverflow** is not null, lines will be clipped according to the given strategy." + }, + "monospace": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, changes the default **fontFamily** to *monospace*, and uses simplified monospaced text metrics calculations." + }, + "pathFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The image filter for the tip’s box; defaults to a drop shadow." + }, + "pointer": { + "$ref": "#/definitions/TipPointer" + }, + "pointerSize": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The size of the tip’s pointer in pixels; defaults to 12." + }, + "preferredAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If an explicit tip anchor is not specified, an anchor is chosen automatically such that the tip fits within the plot’s frame; if the preferred anchor fits, it is chosen." + }, + "textAnchor": { + "anyOf": [ + { + "const": "start", + "type": "string" + }, + { + "const": "middle", + "type": "string" + }, + { + "const": "end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [text anchor][1] controls how text is aligned (typically horizontally) relative to its anchor point; it is one of *start*, *end*, or *middle*. If the frame anchor is *left*, *top-left*, or *bottom-left*, the default text anchor is *start*; if the frame anchor is *right*, *top-right*, or\n*bottom-right*, the default is *end*; otherwise it is *middle*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/text-anchor" + }, + "textOverflow": { + "anyOf": [ + { + "type": "null" + }, + { + "const": "clip", + "type": "string" + }, + { + "const": "ellipsis", + "type": "string" + }, + { + "const": "clip-start", + "type": "string" + }, + { + "const": "clip-end", + "type": "string" + }, + { + "const": "ellipsis-start", + "type": "string" + }, + { + "const": "ellipsis-middle", + "type": "string" + }, + { + "const": "ellipsis-end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How truncate (or wrap) lines of text longer than the given **lineWidth**; one of:\n\n- null (default) - preserve overflowing characters (and wrap if needed)\n- *clip* or *clip-end* - remove characters from the end\n- *clip-start* - remove characters from the start\n- *ellipsis* or *ellipsis-end* - replace characters from the end with an ellipsis (…)\n- *ellipsis-start* - replace characters from the start with an ellipsis (…)\n- *ellipsis-middle* - replace characters from the middle with an ellipsis (…)\n\nIf no **title** was specified, if text requires truncation, a title containing the non-truncated text will be implicitly added." + }, + "textPadding": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The padding around the text in pixels; defaults to 8." + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + } + }, + "type": "object" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to generate a tooltip for this mark, and any tip options." + }, + "title": { + "$ref": "#/definitions/ChannelValue", + "description": "The title; a channel specifying accessible, short textual descriptions as strings (possibly with newlines). If the tip option is specified, the title will be displayed with an interactive tooltip instead of using the SVG [title element][1].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/title" + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position of the vector’s anchor point; an optional channel bound to the *x* scale. Default depends on the **frameAnchor**." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position of the vector’s anchor point; an optional channel bound to the *y* scale. Default depends on the **frameAnchor**." + } + }, + "required": [ + "data", + "mark" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "$schema": { + "description": "A [JSON schema](http://json-schema.org/) URL for this specification, such as https://uwdata.github.io/mosaic/schema/latest.json. This property enables validation and autocomplete in editors with JSON schema support.", + "format": "uri", + "type": "string" + }, + "anchor": { + "anyOf": [ + { + "const": "start", + "type": "string" + }, + { + "const": "middle", + "type": "string" + }, + { + "const": "end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The vector’s position along its orientation relative to its anchor point; a constant. Assuming a default **rotate** angle of 0°, one of:\n\n- *start* - from [*x*, *y*] to [*x*, *y* - *l*]\n- *middle* (default) - from [*x*, *y* + *l* / 2] to [*x*, *y* - *l* / 2]\n- *end* - from [*x*, *y* + *l*] to [*x*, *y*]\n\nwhere [*x*, *y*] is the vector’s anchor point and *l* is the vector’s (possibly scaled) length in pixels." + }, + "ariaDescription": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-description][1]; a constant textual description.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-description" + }, + "ariaHidden": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-hidden][1] state; a constant indicating whether the element is exposed to an accessibility API.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-hidden" + }, + "ariaLabel": { + "$ref": "#/definitions/ChannelValue", + "description": "The [aria-label][1]; a channel specifying short textual labels representing the value in the accessibility tree.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-label" + }, + "clip": { + "anyOf": [ + { + "const": "frame", + "type": "string" + }, + { + "const": "sphere", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to clip the mark; one of:\n\n- *frame* or true - clip to the plot’s frame (inner area)\n- *sphere* - clip to the projected sphere (*e.g.*, front hemisphere)\n- null or false - do not clip\n\nThe *sphere* clip option requires a geographic projection." + }, + "config": { + "$ref": "#/definitions/Config", + "description": "Configuration options." + }, + "data": { + "$ref": "#/definitions/Data", + "description": "Dataset definitions." + }, + "dx": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The horizontal offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "dy": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The vertical offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "facet": { + "anyOf": [ + { + "const": "auto", + "type": "string" + }, + { + "const": "include", + "type": "string" + }, + { + "const": "exclude", + "type": "string" + }, + { + "const": "super", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to enable or disable faceting; one of:\n\n- *auto* (default) - automatically determine if this mark should be faceted\n- *include* (or true) - draw the subset of the mark’s data in the current facet\n- *exclude* - draw the subset of the mark’s data *not* in the current facet\n- *super* - draw this mark in a single frame that covers all facets\n- null (or false) - repeat this mark’s data across all facets (*i.e.*, no faceting)\n\nWhen a mark uses *super* faceting, it is not allowed to use position scales (*x*, *y*, *fx*, or *fy*); *super* faceting is intended for decorations, such as labels and legends.\n\nWhen top-level faceting is used, the default *auto* setting is equivalent to *include* when the mark data is strictly equal to the top-level facet data; otherwise it is equivalent to null. When the *include* or *exclude* facet mode is chosen, the mark data must be parallel to the top-level facet data: the data must have the same length and order. If the data are not parallel, then the wrong data may be shown in each facet. The default\n*auto* therefore requires strict equality (`===`) for safety, and using the facet data as mark data is recommended when using the *exclude* facet mode. (To construct parallel data safely, consider using [*array*.map][1] on the facet data.)\n\nWhen mark-level faceting is used, the default *auto* setting is equivalent to *include*: the mark will be faceted if either the **fx** or **fy** channel option (or both) is specified. The null or false option will disable faceting, while *exclude* draws the subset of the mark’s data *not* in the current facet.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map" + }, + "facetAnchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "right", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "const": "left", + "type": "string" + }, + { + "const": "top-left", + "type": "string" + }, + { + "const": "top-right", + "type": "string" + }, + { + "const": "bottom-left", + "type": "string" + }, + { + "const": "bottom-right", + "type": "string" + }, + { + "const": "top-empty", + "type": "string" + }, + { + "const": "right-empty", + "type": "string" + }, + { + "const": "bottom-empty", + "type": "string" + }, + { + "const": "left-empty", + "type": "string" + }, + { + "const": "empty", + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to place the mark with respect to facets; one of:\n\n- null (default for most marks) - display the mark in each non-empty facet\n- *top*, *right*, *bottom*, or *left* - display the mark only in facets on the given side\n- *top-empty*, *right-empty*, *bottom-empty*, or *left-empty* (default for axis marks) - display the mark only in facets that have empty space on the given side: either the margin, or an empty facet\n- *empty* - display the mark in empty facets only" + }, + "fill": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill" + }, + "fillOpacity": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill-opacity][1]; a constant number between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill-opacity" + }, + "filter": { + "$ref": "#/definitions/ChannelValue", + "description": "Applies a transform to filter the mark’s index according to the given channel values; only truthy values are retained.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "frameAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The vector’s frame anchor, to default **x** and **y** relative to the frame; a constant representing one of the frame corners (*top-left*,\n*top-right*, *bottom-right*, *bottom-left*), sides (*top*, *right*,\n*bottom*, *left*), or *middle* (default). Has no effect if both **x** and **y** are specified." + }, + "fx": { + "$ref": "#/definitions/ChannelValue", + "description": "The horizontal facet position channel, for mark-level faceting, bound to the *fx* scale." + }, + "fy": { + "$ref": "#/definitions/ChannelValue", + "description": "The vertical facet position channel, for mark-level faceting, bound to the\n*fy* scale." + }, + "href": { + "$ref": "#/definitions/ChannelValue", + "description": "The [href][1]; a channel specifying URLs for clickable links. May be used in conjunction with the **target** option to open links in another window.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/href" + }, + "imageFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A CSS [filter][1]; a constant string used to adjust the rendering of images, such as *blur(5px)*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/filter" + }, + "length": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vector’s length; either an optional channel bound to the *length* scale or a constant number in pixels. Defaults to 12 pixels." + }, + "margin": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four mark margins: **marginTop**,\n**marginRight**, **marginBottom**, and **marginLeft**; typically defaults to 0, except for axis marks." + }, + "marginBottom": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s bottom margin; the minimum distance in pixels between the bottom edges of the inner and outer plot area." + }, + "marginLeft": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s left margin; the minimum distance in pixels between the left edges of the inner and outer plot area." + }, + "marginRight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s right margin; the minimum distance in pixels between the right edges of the mark’s inner and outer plot area." + }, + "marginTop": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s top margin; the minimum distance in pixels between the top edges of the inner and outer plot area." + }, + "mark": { + "const": "spike", + "description": "Like vector, but with default *options* suitable for drawing a spike map.", + "type": "string" + }, + "meta": { + "$ref": "#/definitions/Meta", + "description": "Specification metadata." + }, + "mixBlendMode": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [mix-blend-mode][1]; a constant string specifying how to blend content such as *multiply*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode" + }, + "opacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally. For faster rendering, prefer the **strokeOpacity** or **fillOpacity** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/opacity" + }, + "paintOrder": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [paint-order][1]; a constant string specifying the order in which the\n**fill**, **stroke**, and any markers are drawn; defaults to *normal*, which draws the fill, then stroke, then markers; defaults to *stroke* for the text mark to create a “halo” around text to improve legibility.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/paint-order" + }, + "params": { + "$ref": "#/definitions/Params", + "description": "Param and Selection definitions." + }, + "plotDefaults": { + "$ref": "#/definitions/PlotAttributes", + "description": "A default set of attributes to apply to all plot components." + }, + "pointerEvents": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [pointer-events][1] property; a constant string such as *none*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/pointer-events" + }, + "r": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The vector shape’s radius, such as half the width of the *arrow*’s head or the *spike*’s base; a constant number in pixels. Defaults to 3.5 pixels." + }, + "reverse": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Applies a transform to reverse the order of the mark’s index, say for reverse input order." + }, + "rotate": { + "$ref": "#/definitions/ChannelValue", + "description": "The vector’s orientation (rotation angle); either a constant number in degrees clockwise, or an optional channel (with no associated scale). Defaults to 0 degrees with the vector pointing up." + }, + "select": { + "$ref": "#/definitions/SelectFilter", + "description": "Applies a filter transform after data is loaded to highlight selected values only. For example, `first` and `last` select the first or last values of series only (using the *z* channel to separate series). Meanwhile, `nearestX` and `nearestY` select the point nearest to the pointer along the *x* or *y* channel dimension. Unlike Mosaic selections, a mark level *select* is internal to the mark only, and does not populate a param or selection value to be shared across clients.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "shape": { + "anyOf": [ + { + "$ref": "#/definitions/VectorShape" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The shape of the vector; a constant. Defaults to *arrow*." + }, + "shapeRendering": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [shape-rendering][1]; a constant string such as *crispEdges*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/shape-rendering" + }, + "sort": { + "anyOf": [ + { + "$ref": "#/definitions/SortOrder" + }, + { + "$ref": "#/definitions/ChannelDomainSort" + } + ], + "description": "Either applies a transform to sort the mark’s index by the specified channel values, or imputes ordinal scale domains from this mark’s channels.\n\nWhen imputing ordinal scale domains from channel values, the **sort** option is an object whose keys are ordinal scale names such as *x* or *fx*, and whose values are channel names such as *y*, *y1*, or *y2*. For example, to impute the *y* scale’s domain from the associated *x* channel values in ascending order:\n\n```js sort: {y: \"x\"} ```\n\nFor different sort options for different scales, replace the channel name with a *value* object and per-scale options:\n\n```js sort: {y: {value: \"-x\"}} ```\n\nWhen sorting the mark’s index, the **sort** option is instead one of:\n\n- a channel value definition for sorting given values in ascending order\n- a {value, order} object for sorting given values\n- a {channel, order} object for sorting the named channel’s values" + }, + "stroke": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke" + }, + "strokeDasharray": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dasharray][1]; a constant number indicating the length in pixels of alternating dashes and gaps, or a constant string of numbers separated by spaces or commas (_e.g._, *10 2* for dashes of 10 pixels separated by gaps of 2 pixels), or *none* (the default) for no dashing\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dasharray" + }, + "strokeDashoffset": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dashoffset][1]; a constant indicating the offset in pixels of the first dash along the stroke; defaults to zero.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dashoffset" + }, + "strokeLinecap": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linecap][1]; a constant specifying how to cap stroked paths, such as *butt*, *round*, or *square*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linecap" + }, + "strokeLinejoin": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linejoin][1]; a constant specifying how to join stroked paths, such as *bevel*, *miter*, *miter-clip*, or *round*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linejoin" + }, + "strokeMiterlimit": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-miterlimit][1]; a constant number specifying how to limit the length of *miter* joins on stroked paths.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-miterlimit" + }, + "strokeOpacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-opacity" + }, + "strokeWidth": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-width][1]; a constant number in pixels, or a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-width" + }, + "target": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [target][1]; a constant string specifying the target window (_e.g._,\n*_blank*) for clickable links; used in conjunction with the **href** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/target" + }, + "tip": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/TipPointer" + }, + { + "properties": { + "anchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The tip anchor specifies how to orient the tip box relative to its anchor position; it refers to the part of the tip box that is attached to the anchor point. For example, the *top-left* anchor places the top-left corner of tip box near the anchor position, hence placing the tip box below and to the right of the anchor position." + }, + "fontFamily": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font-family][1]; a constant; defaults to the plot’s font family, which is typically [*system-ui*][2].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-family [2]: https://drafts.csswg.org/css-fonts-4/#valdef-font-family-system-ui" + }, + "fontSize": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font size][1] in pixels; either a constant or a channel; defaults to the plot’s font size, which is typically 10. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-size" + }, + "fontStyle": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font style][1]; a constant; defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-style" + }, + "fontVariant": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font variant][1]; a constant; if the **text** channel contains numbers or dates, defaults to *tabular-nums* to facilitate comparing numbers; otherwise defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant" + }, + "fontWeight": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font weight][1]; a constant; defaults to the plot’s font weight, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight" + }, + "format": { + "additionalProperties": false, + "description": "How channel values are formatted for display. If a format is a string, it is interpreted as a (UTC) time format for temporal channels, and otherwise a number format.", + "properties": { + "ariaLabel": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fill": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fillOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fontSize": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fx": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fy": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "geometry": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "height": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "href": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "length": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "opacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "path": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "r": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "rotate": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "src": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "stroke": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeWidth": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "symbol": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "text": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "title": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "weight": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "width": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "z": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + } + }, + "type": "object" + }, + "frameAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The frame anchor specifies defaults for **x** and **y** based on the plot’s frame; it may be one of the four sides (*top*, *right*, *bottom*, *left*), one of the four corners (*top-left*, *top-right*, *bottom-right*,\n*bottom-left*), or the *middle* of the frame. For example, for tips distributed horizontally at the top of the frame:\n\n```js Plot.tip(data, {x: \"date\", frameAnchor: \"top\"}) ```" + }, + "lineHeight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line height in ems; defaults to 1. The line height affects the (typically vertical) separation between adjacent baselines of text, as well as the separation between the text and its anchor point." + }, + "lineWidth": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line width in ems (e.g., 10 for about 20 characters); defaults to infinity, disabling wrapping and clipping.\n\nIf **textOverflow** is null, lines will be wrapped at the specified length. If a line is split at a soft hyphen (\\xad), a hyphen (-) will be displayed at the end of the line. If **textOverflow** is not null, lines will be clipped according to the given strategy." + }, + "monospace": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, changes the default **fontFamily** to *monospace*, and uses simplified monospaced text metrics calculations." + }, + "pathFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The image filter for the tip’s box; defaults to a drop shadow." + }, + "pointer": { + "$ref": "#/definitions/TipPointer" + }, + "pointerSize": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The size of the tip’s pointer in pixels; defaults to 12." + }, + "preferredAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If an explicit tip anchor is not specified, an anchor is chosen automatically such that the tip fits within the plot’s frame; if the preferred anchor fits, it is chosen." + }, + "textAnchor": { + "anyOf": [ + { + "const": "start", + "type": "string" + }, + { + "const": "middle", + "type": "string" + }, + { + "const": "end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [text anchor][1] controls how text is aligned (typically horizontally) relative to its anchor point; it is one of *start*, *end*, or *middle*. If the frame anchor is *left*, *top-left*, or *bottom-left*, the default text anchor is *start*; if the frame anchor is *right*, *top-right*, or\n*bottom-right*, the default is *end*; otherwise it is *middle*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/text-anchor" + }, + "textOverflow": { + "anyOf": [ + { + "type": "null" + }, + { + "const": "clip", + "type": "string" + }, + { + "const": "ellipsis", + "type": "string" + }, + { + "const": "clip-start", + "type": "string" + }, + { + "const": "clip-end", + "type": "string" + }, + { + "const": "ellipsis-start", + "type": "string" + }, + { + "const": "ellipsis-middle", + "type": "string" + }, + { + "const": "ellipsis-end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How truncate (or wrap) lines of text longer than the given **lineWidth**; one of:\n\n- null (default) - preserve overflowing characters (and wrap if needed)\n- *clip* or *clip-end* - remove characters from the end\n- *clip-start* - remove characters from the start\n- *ellipsis* or *ellipsis-end* - replace characters from the end with an ellipsis (…)\n- *ellipsis-start* - replace characters from the start with an ellipsis (…)\n- *ellipsis-middle* - replace characters from the middle with an ellipsis (…)\n\nIf no **title** was specified, if text requires truncation, a title containing the non-truncated text will be implicitly added." + }, + "textPadding": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The padding around the text in pixels; defaults to 8." + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + } + }, + "type": "object" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to generate a tooltip for this mark, and any tip options." + }, + "title": { + "$ref": "#/definitions/ChannelValue", + "description": "The title; a channel specifying accessible, short textual descriptions as strings (possibly with newlines). If the tip option is specified, the title will be displayed with an interactive tooltip instead of using the SVG [title element][1].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/title" + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position of the vector’s anchor point; an optional channel bound to the *x* scale. Default depends on the **frameAnchor**." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position of the vector’s anchor point; an optional channel bound to the *y* scale. Default depends on the **frameAnchor**." + } + }, + "required": [ + "data", + "mark" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "$schema": { + "description": "A [JSON schema](http://json-schema.org/) URL for this specification, such as https://uwdata.github.io/mosaic/schema/latest.json. This property enables validation and autocomplete in editors with JSON schema support.", + "format": "uri", + "type": "string" + }, + "as": { + "$ref": "#/definitions/ParamRef", + "description": "The output selection. If specified, the legend is interactive, using a `toggle` interaction for discrete legends or an `intervalX` interaction for continuous legends." + }, + "columns": { + "description": "The number of columns to use to layout a discrete legend.", + "type": "number" + }, + "config": { + "$ref": "#/definitions/Config", + "description": "Configuration options." + }, + "data": { + "$ref": "#/definitions/Data", + "description": "Dataset definitions." + }, + "field": { + "description": "The data field over which to generate output selection clauses. If unspecified, a matching field is retrieved from existing plot marks.", + "type": "string" + }, + "for": { + "description": "The name of the plot this legend applies to. A plot must include a `name` attribute to be referenced.", + "type": "string" + }, + "height": { + "description": "The height of a continuous legend, in pixels.", + "type": "number" + }, + "label": { + "description": "The legend label.", + "type": "string" + }, + "legend": { + "description": "A legend of the given type. The valid types are `\"color\"`, `\"opacity\"`, and `\"symbol\"`.", + "enum": [ + "color", + "opacity", + "symbol" + ], + "type": "string" + }, + "marginBottom": { + "description": "The bottom margin of the legend component, in pixels.", + "type": "number" + }, + "marginLeft": { + "description": "The left margin of the legend component, in pixels.", + "type": "number" + }, + "marginRight": { + "description": "The right margin of the legend component, in pixels.", + "type": "number" + }, + "marginTop": { + "description": "The top margin of the legend component, in pixels.", + "type": "number" + }, + "meta": { + "$ref": "#/definitions/Meta", + "description": "Specification metadata." + }, + "params": { + "$ref": "#/definitions/Params", + "description": "Param and Selection definitions." + }, + "plotDefaults": { + "$ref": "#/definitions/PlotAttributes", + "description": "A default set of attributes to apply to all plot components." + }, + "tickSize": { + "description": "The size of legend ticks in a continuous legend, in pixels.", + "type": "number" + }, + "width": { + "description": "The width of a continuous legend, in pixels.", + "type": "number" + } + }, + "required": [ + "for", + "legend" + ], + "type": "object" + } + ], + "description": "A declarative Mosaic specification." + }, + "Sphere": { + "additionalProperties": false, + "description": "The sphere mark.", + "properties": { + "ariaDescription": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-description][1]; a constant textual description.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-description" + }, + "ariaHidden": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-hidden][1] state; a constant indicating whether the element is exposed to an accessibility API.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-hidden" + }, + "ariaLabel": { + "$ref": "#/definitions/ChannelValue", + "description": "The [aria-label][1]; a channel specifying short textual labels representing the value in the accessibility tree.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-label" + }, + "clip": { + "anyOf": [ + { + "const": "frame", + "type": "string" + }, + { + "const": "sphere", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to clip the mark; one of:\n\n- *frame* or true - clip to the plot’s frame (inner area)\n- *sphere* - clip to the projected sphere (*e.g.*, front hemisphere)\n- null or false - do not clip\n\nThe *sphere* clip option requires a geographic projection." + }, + "dx": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The horizontal offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "dy": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The vertical offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "facet": { + "anyOf": [ + { + "const": "auto", + "type": "string" + }, + { + "const": "include", + "type": "string" + }, + { + "const": "exclude", + "type": "string" + }, + { + "const": "super", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to enable or disable faceting; one of:\n\n- *auto* (default) - automatically determine if this mark should be faceted\n- *include* (or true) - draw the subset of the mark’s data in the current facet\n- *exclude* - draw the subset of the mark’s data *not* in the current facet\n- *super* - draw this mark in a single frame that covers all facets\n- null (or false) - repeat this mark’s data across all facets (*i.e.*, no faceting)\n\nWhen a mark uses *super* faceting, it is not allowed to use position scales (*x*, *y*, *fx*, or *fy*); *super* faceting is intended for decorations, such as labels and legends.\n\nWhen top-level faceting is used, the default *auto* setting is equivalent to *include* when the mark data is strictly equal to the top-level facet data; otherwise it is equivalent to null. When the *include* or *exclude* facet mode is chosen, the mark data must be parallel to the top-level facet data: the data must have the same length and order. If the data are not parallel, then the wrong data may be shown in each facet. The default\n*auto* therefore requires strict equality (`===`) for safety, and using the facet data as mark data is recommended when using the *exclude* facet mode. (To construct parallel data safely, consider using [*array*.map][1] on the facet data.)\n\nWhen mark-level faceting is used, the default *auto* setting is equivalent to *include*: the mark will be faceted if either the **fx** or **fy** channel option (or both) is specified. The null or false option will disable faceting, while *exclude* draws the subset of the mark’s data *not* in the current facet.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map" + }, + "facetAnchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "right", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "const": "left", + "type": "string" + }, + { + "const": "top-left", + "type": "string" + }, + { + "const": "top-right", + "type": "string" + }, + { + "const": "bottom-left", + "type": "string" + }, + { + "const": "bottom-right", + "type": "string" + }, + { + "const": "top-empty", + "type": "string" + }, + { + "const": "right-empty", + "type": "string" + }, + { + "const": "bottom-empty", + "type": "string" + }, + { + "const": "left-empty", + "type": "string" + }, + { + "const": "empty", + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to place the mark with respect to facets; one of:\n\n- null (default for most marks) - display the mark in each non-empty facet\n- *top*, *right*, *bottom*, or *left* - display the mark only in facets on the given side\n- *top-empty*, *right-empty*, *bottom-empty*, or *left-empty* (default for axis marks) - display the mark only in facets that have empty space on the given side: either the margin, or an empty facet\n- *empty* - display the mark in empty facets only" + }, + "fill": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill" + }, + "fillOpacity": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill-opacity][1]; a constant number between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill-opacity" + }, + "filter": { + "$ref": "#/definitions/ChannelValue", + "description": "Applies a transform to filter the mark’s index according to the given channel values; only truthy values are retained.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "fx": { + "$ref": "#/definitions/ChannelValue", + "description": "The horizontal facet position channel, for mark-level faceting, bound to the *fx* scale." + }, + "fy": { + "$ref": "#/definitions/ChannelValue", + "description": "The vertical facet position channel, for mark-level faceting, bound to the\n*fy* scale." + }, + "href": { + "$ref": "#/definitions/ChannelValue", + "description": "The [href][1]; a channel specifying URLs for clickable links. May be used in conjunction with the **target** option to open links in another window.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/href" + }, + "imageFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A CSS [filter][1]; a constant string used to adjust the rendering of images, such as *blur(5px)*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/filter" + }, + "margin": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four mark margins: **marginTop**,\n**marginRight**, **marginBottom**, and **marginLeft**; typically defaults to 0, except for axis marks." + }, + "marginBottom": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s bottom margin; the minimum distance in pixels between the bottom edges of the inner and outer plot area." + }, + "marginLeft": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s left margin; the minimum distance in pixels between the left edges of the inner and outer plot area." + }, + "marginRight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s right margin; the minimum distance in pixels between the right edges of the mark’s inner and outer plot area." + }, + "marginTop": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s top margin; the minimum distance in pixels between the top edges of the inner and outer plot area." + }, + "mark": { + "const": "sphere", + "description": "A geo mark whose *data* is the outline of the sphere on the projection’s plane. (For use with a spherical **projection** only.)", + "type": "string" + }, + "mixBlendMode": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [mix-blend-mode][1]; a constant string specifying how to blend content such as *multiply*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode" + }, + "opacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally. For faster rendering, prefer the **strokeOpacity** or **fillOpacity** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/opacity" + }, + "paintOrder": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [paint-order][1]; a constant string specifying the order in which the\n**fill**, **stroke**, and any markers are drawn; defaults to *normal*, which draws the fill, then stroke, then markers; defaults to *stroke* for the text mark to create a “halo” around text to improve legibility.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/paint-order" + }, + "pointerEvents": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [pointer-events][1] property; a constant string such as *none*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/pointer-events" + }, + "reverse": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Applies a transform to reverse the order of the mark’s index, say for reverse input order." + }, + "select": { + "$ref": "#/definitions/SelectFilter", + "description": "Applies a filter transform after data is loaded to highlight selected values only. For example, `first` and `last` select the first or last values of series only (using the *z* channel to separate series). Meanwhile, `nearestX` and `nearestY` select the point nearest to the pointer along the *x* or *y* channel dimension. Unlike Mosaic selections, a mark level *select* is internal to the mark only, and does not populate a param or selection value to be shared across clients.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "shapeRendering": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [shape-rendering][1]; a constant string such as *crispEdges*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/shape-rendering" + }, + "sort": { + "anyOf": [ + { + "$ref": "#/definitions/SortOrder" + }, + { + "$ref": "#/definitions/ChannelDomainSort" + } + ], + "description": "Either applies a transform to sort the mark’s index by the specified channel values, or imputes ordinal scale domains from this mark’s channels.\n\nWhen imputing ordinal scale domains from channel values, the **sort** option is an object whose keys are ordinal scale names such as *x* or *fx*, and whose values are channel names such as *y*, *y1*, or *y2*. For example, to impute the *y* scale’s domain from the associated *x* channel values in ascending order:\n\n```js sort: {y: \"x\"} ```\n\nFor different sort options for different scales, replace the channel name with a *value* object and per-scale options:\n\n```js sort: {y: {value: \"-x\"}} ```\n\nWhen sorting the mark’s index, the **sort** option is instead one of:\n\n- a channel value definition for sorting given values in ascending order\n- a {value, order} object for sorting given values\n- a {channel, order} object for sorting the named channel’s values" + }, + "stroke": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke" + }, + "strokeDasharray": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dasharray][1]; a constant number indicating the length in pixels of alternating dashes and gaps, or a constant string of numbers separated by spaces or commas (_e.g._, *10 2* for dashes of 10 pixels separated by gaps of 2 pixels), or *none* (the default) for no dashing\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dasharray" + }, + "strokeDashoffset": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dashoffset][1]; a constant indicating the offset in pixels of the first dash along the stroke; defaults to zero.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dashoffset" + }, + "strokeLinecap": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linecap][1]; a constant specifying how to cap stroked paths, such as *butt*, *round*, or *square*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linecap" + }, + "strokeLinejoin": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linejoin][1]; a constant specifying how to join stroked paths, such as *bevel*, *miter*, *miter-clip*, or *round*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linejoin" + }, + "strokeMiterlimit": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-miterlimit][1]; a constant number specifying how to limit the length of *miter* joins on stroked paths.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-miterlimit" + }, + "strokeOpacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-opacity" + }, + "strokeWidth": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-width][1]; a constant number in pixels, or a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-width" + }, + "target": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [target][1]; a constant string specifying the target window (_e.g._,\n*_blank*) for clickable links; used in conjunction with the **href** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/target" + }, + "tip": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/TipPointer" + }, + { + "properties": { + "anchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The tip anchor specifies how to orient the tip box relative to its anchor position; it refers to the part of the tip box that is attached to the anchor point. For example, the *top-left* anchor places the top-left corner of tip box near the anchor position, hence placing the tip box below and to the right of the anchor position." + }, + "fontFamily": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font-family][1]; a constant; defaults to the plot’s font family, which is typically [*system-ui*][2].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-family [2]: https://drafts.csswg.org/css-fonts-4/#valdef-font-family-system-ui" + }, + "fontSize": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font size][1] in pixels; either a constant or a channel; defaults to the plot’s font size, which is typically 10. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-size" + }, + "fontStyle": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font style][1]; a constant; defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-style" + }, + "fontVariant": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font variant][1]; a constant; if the **text** channel contains numbers or dates, defaults to *tabular-nums* to facilitate comparing numbers; otherwise defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant" + }, + "fontWeight": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font weight][1]; a constant; defaults to the plot’s font weight, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight" + }, + "format": { + "additionalProperties": false, + "description": "How channel values are formatted for display. If a format is a string, it is interpreted as a (UTC) time format for temporal channels, and otherwise a number format.", + "properties": { + "ariaLabel": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fill": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fillOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fontSize": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fx": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fy": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "geometry": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "height": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "href": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "length": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "opacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "path": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "r": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "rotate": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "src": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "stroke": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeWidth": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "symbol": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "text": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "title": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "weight": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "width": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "z": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + } + }, + "type": "object" + }, + "frameAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The frame anchor specifies defaults for **x** and **y** based on the plot’s frame; it may be one of the four sides (*top*, *right*, *bottom*, *left*), one of the four corners (*top-left*, *top-right*, *bottom-right*,\n*bottom-left*), or the *middle* of the frame. For example, for tips distributed horizontally at the top of the frame:\n\n```js Plot.tip(data, {x: \"date\", frameAnchor: \"top\"}) ```" + }, + "lineHeight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line height in ems; defaults to 1. The line height affects the (typically vertical) separation between adjacent baselines of text, as well as the separation between the text and its anchor point." + }, + "lineWidth": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line width in ems (e.g., 10 for about 20 characters); defaults to infinity, disabling wrapping and clipping.\n\nIf **textOverflow** is null, lines will be wrapped at the specified length. If a line is split at a soft hyphen (\\xad), a hyphen (-) will be displayed at the end of the line. If **textOverflow** is not null, lines will be clipped according to the given strategy." + }, + "monospace": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, changes the default **fontFamily** to *monospace*, and uses simplified monospaced text metrics calculations." + }, + "pathFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The image filter for the tip’s box; defaults to a drop shadow." + }, + "pointer": { + "$ref": "#/definitions/TipPointer" + }, + "pointerSize": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The size of the tip’s pointer in pixels; defaults to 12." + }, + "preferredAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If an explicit tip anchor is not specified, an anchor is chosen automatically such that the tip fits within the plot’s frame; if the preferred anchor fits, it is chosen." + }, + "textAnchor": { + "anyOf": [ + { + "const": "start", + "type": "string" + }, + { + "const": "middle", + "type": "string" + }, + { + "const": "end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [text anchor][1] controls how text is aligned (typically horizontally) relative to its anchor point; it is one of *start*, *end*, or *middle*. If the frame anchor is *left*, *top-left*, or *bottom-left*, the default text anchor is *start*; if the frame anchor is *right*, *top-right*, or\n*bottom-right*, the default is *end*; otherwise it is *middle*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/text-anchor" + }, + "textOverflow": { + "anyOf": [ + { + "type": "null" + }, + { + "const": "clip", + "type": "string" + }, + { + "const": "ellipsis", + "type": "string" + }, + { + "const": "clip-start", + "type": "string" + }, + { + "const": "clip-end", + "type": "string" + }, + { + "const": "ellipsis-start", + "type": "string" + }, + { + "const": "ellipsis-middle", + "type": "string" + }, + { + "const": "ellipsis-end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How truncate (or wrap) lines of text longer than the given **lineWidth**; one of:\n\n- null (default) - preserve overflowing characters (and wrap if needed)\n- *clip* or *clip-end* - remove characters from the end\n- *clip-start* - remove characters from the start\n- *ellipsis* or *ellipsis-end* - replace characters from the end with an ellipsis (…)\n- *ellipsis-start* - replace characters from the start with an ellipsis (…)\n- *ellipsis-middle* - replace characters from the middle with an ellipsis (…)\n\nIf no **title** was specified, if text requires truncation, a title containing the non-truncated text will be implicitly added." + }, + "textPadding": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The padding around the text in pixels; defaults to 8." + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + } + }, + "type": "object" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to generate a tooltip for this mark, and any tip options." + }, + "title": { + "$ref": "#/definitions/ChannelValue", + "description": "The title; a channel specifying accessible, short textual descriptions as strings (possibly with newlines). If the tip option is specified, the title will be displayed with an interactive tooltip instead of using the SVG [title element][1].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/title" + } + }, + "required": [ + "mark" + ], + "type": "object" + }, + "Spike": { + "additionalProperties": false, + "description": "The spike mark.", + "properties": { + "anchor": { + "anyOf": [ + { + "const": "start", + "type": "string" + }, + { + "const": "middle", + "type": "string" + }, + { + "const": "end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The vector’s position along its orientation relative to its anchor point; a constant. Assuming a default **rotate** angle of 0°, one of:\n\n- *start* - from [*x*, *y*] to [*x*, *y* - *l*]\n- *middle* (default) - from [*x*, *y* + *l* / 2] to [*x*, *y* - *l* / 2]\n- *end* - from [*x*, *y* + *l*] to [*x*, *y*]\n\nwhere [*x*, *y*] is the vector’s anchor point and *l* is the vector’s (possibly scaled) length in pixels." + }, + "ariaDescription": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-description][1]; a constant textual description.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-description" + }, + "ariaHidden": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-hidden][1] state; a constant indicating whether the element is exposed to an accessibility API.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-hidden" + }, + "ariaLabel": { + "$ref": "#/definitions/ChannelValue", + "description": "The [aria-label][1]; a channel specifying short textual labels representing the value in the accessibility tree.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-label" + }, + "clip": { + "anyOf": [ + { + "const": "frame", + "type": "string" + }, + { + "const": "sphere", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to clip the mark; one of:\n\n- *frame* or true - clip to the plot’s frame (inner area)\n- *sphere* - clip to the projected sphere (*e.g.*, front hemisphere)\n- null or false - do not clip\n\nThe *sphere* clip option requires a geographic projection." + }, + "data": { + "$ref": "#/definitions/PlotMarkData", + "description": "The data source for the mark." + }, + "dx": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The horizontal offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "dy": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The vertical offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "facet": { + "anyOf": [ + { + "const": "auto", + "type": "string" + }, + { + "const": "include", + "type": "string" + }, + { + "const": "exclude", + "type": "string" + }, + { + "const": "super", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to enable or disable faceting; one of:\n\n- *auto* (default) - automatically determine if this mark should be faceted\n- *include* (or true) - draw the subset of the mark’s data in the current facet\n- *exclude* - draw the subset of the mark’s data *not* in the current facet\n- *super* - draw this mark in a single frame that covers all facets\n- null (or false) - repeat this mark’s data across all facets (*i.e.*, no faceting)\n\nWhen a mark uses *super* faceting, it is not allowed to use position scales (*x*, *y*, *fx*, or *fy*); *super* faceting is intended for decorations, such as labels and legends.\n\nWhen top-level faceting is used, the default *auto* setting is equivalent to *include* when the mark data is strictly equal to the top-level facet data; otherwise it is equivalent to null. When the *include* or *exclude* facet mode is chosen, the mark data must be parallel to the top-level facet data: the data must have the same length and order. If the data are not parallel, then the wrong data may be shown in each facet. The default\n*auto* therefore requires strict equality (`===`) for safety, and using the facet data as mark data is recommended when using the *exclude* facet mode. (To construct parallel data safely, consider using [*array*.map][1] on the facet data.)\n\nWhen mark-level faceting is used, the default *auto* setting is equivalent to *include*: the mark will be faceted if either the **fx** or **fy** channel option (or both) is specified. The null or false option will disable faceting, while *exclude* draws the subset of the mark’s data *not* in the current facet.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map" + }, + "facetAnchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "right", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "const": "left", + "type": "string" + }, + { + "const": "top-left", + "type": "string" + }, + { + "const": "top-right", + "type": "string" + }, + { + "const": "bottom-left", + "type": "string" + }, + { + "const": "bottom-right", + "type": "string" + }, + { + "const": "top-empty", + "type": "string" + }, + { + "const": "right-empty", + "type": "string" + }, + { + "const": "bottom-empty", + "type": "string" + }, + { + "const": "left-empty", + "type": "string" + }, + { + "const": "empty", + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to place the mark with respect to facets; one of:\n\n- null (default for most marks) - display the mark in each non-empty facet\n- *top*, *right*, *bottom*, or *left* - display the mark only in facets on the given side\n- *top-empty*, *right-empty*, *bottom-empty*, or *left-empty* (default for axis marks) - display the mark only in facets that have empty space on the given side: either the margin, or an empty facet\n- *empty* - display the mark in empty facets only" + }, + "fill": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill" + }, + "fillOpacity": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill-opacity][1]; a constant number between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill-opacity" + }, + "filter": { + "$ref": "#/definitions/ChannelValue", + "description": "Applies a transform to filter the mark’s index according to the given channel values; only truthy values are retained.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "frameAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The vector’s frame anchor, to default **x** and **y** relative to the frame; a constant representing one of the frame corners (*top-left*,\n*top-right*, *bottom-right*, *bottom-left*), sides (*top*, *right*,\n*bottom*, *left*), or *middle* (default). Has no effect if both **x** and **y** are specified." + }, + "fx": { + "$ref": "#/definitions/ChannelValue", + "description": "The horizontal facet position channel, for mark-level faceting, bound to the *fx* scale." + }, + "fy": { + "$ref": "#/definitions/ChannelValue", + "description": "The vertical facet position channel, for mark-level faceting, bound to the\n*fy* scale." + }, + "href": { + "$ref": "#/definitions/ChannelValue", + "description": "The [href][1]; a channel specifying URLs for clickable links. May be used in conjunction with the **target** option to open links in another window.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/href" + }, + "imageFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A CSS [filter][1]; a constant string used to adjust the rendering of images, such as *blur(5px)*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/filter" + }, + "length": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vector’s length; either an optional channel bound to the *length* scale or a constant number in pixels. Defaults to 12 pixels." + }, + "margin": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four mark margins: **marginTop**,\n**marginRight**, **marginBottom**, and **marginLeft**; typically defaults to 0, except for axis marks." + }, + "marginBottom": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s bottom margin; the minimum distance in pixels between the bottom edges of the inner and outer plot area." + }, + "marginLeft": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s left margin; the minimum distance in pixels between the left edges of the inner and outer plot area." + }, + "marginRight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s right margin; the minimum distance in pixels between the right edges of the mark’s inner and outer plot area." + }, + "marginTop": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s top margin; the minimum distance in pixels between the top edges of the inner and outer plot area." + }, + "mark": { + "const": "spike", + "description": "Like vector, but with default *options* suitable for drawing a spike map.", + "type": "string" + }, + "mixBlendMode": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [mix-blend-mode][1]; a constant string specifying how to blend content such as *multiply*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode" + }, + "opacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally. For faster rendering, prefer the **strokeOpacity** or **fillOpacity** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/opacity" + }, + "paintOrder": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [paint-order][1]; a constant string specifying the order in which the\n**fill**, **stroke**, and any markers are drawn; defaults to *normal*, which draws the fill, then stroke, then markers; defaults to *stroke* for the text mark to create a “halo” around text to improve legibility.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/paint-order" + }, + "pointerEvents": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [pointer-events][1] property; a constant string such as *none*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/pointer-events" + }, + "r": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The vector shape’s radius, such as half the width of the *arrow*’s head or the *spike*’s base; a constant number in pixels. Defaults to 3.5 pixels." + }, + "reverse": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Applies a transform to reverse the order of the mark’s index, say for reverse input order." + }, + "rotate": { + "$ref": "#/definitions/ChannelValue", + "description": "The vector’s orientation (rotation angle); either a constant number in degrees clockwise, or an optional channel (with no associated scale). Defaults to 0 degrees with the vector pointing up." + }, + "select": { + "$ref": "#/definitions/SelectFilter", + "description": "Applies a filter transform after data is loaded to highlight selected values only. For example, `first` and `last` select the first or last values of series only (using the *z* channel to separate series). Meanwhile, `nearestX` and `nearestY` select the point nearest to the pointer along the *x* or *y* channel dimension. Unlike Mosaic selections, a mark level *select* is internal to the mark only, and does not populate a param or selection value to be shared across clients.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "shape": { + "anyOf": [ + { + "$ref": "#/definitions/VectorShape" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The shape of the vector; a constant. Defaults to *arrow*." + }, + "shapeRendering": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [shape-rendering][1]; a constant string such as *crispEdges*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/shape-rendering" + }, + "sort": { + "anyOf": [ + { + "$ref": "#/definitions/SortOrder" + }, + { + "$ref": "#/definitions/ChannelDomainSort" + } + ], + "description": "Either applies a transform to sort the mark’s index by the specified channel values, or imputes ordinal scale domains from this mark’s channels.\n\nWhen imputing ordinal scale domains from channel values, the **sort** option is an object whose keys are ordinal scale names such as *x* or *fx*, and whose values are channel names such as *y*, *y1*, or *y2*. For example, to impute the *y* scale’s domain from the associated *x* channel values in ascending order:\n\n```js sort: {y: \"x\"} ```\n\nFor different sort options for different scales, replace the channel name with a *value* object and per-scale options:\n\n```js sort: {y: {value: \"-x\"}} ```\n\nWhen sorting the mark’s index, the **sort** option is instead one of:\n\n- a channel value definition for sorting given values in ascending order\n- a {value, order} object for sorting given values\n- a {channel, order} object for sorting the named channel’s values" + }, + "stroke": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke" + }, + "strokeDasharray": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dasharray][1]; a constant number indicating the length in pixels of alternating dashes and gaps, or a constant string of numbers separated by spaces or commas (_e.g._, *10 2* for dashes of 10 pixels separated by gaps of 2 pixels), or *none* (the default) for no dashing\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dasharray" + }, + "strokeDashoffset": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dashoffset][1]; a constant indicating the offset in pixels of the first dash along the stroke; defaults to zero.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dashoffset" + }, + "strokeLinecap": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linecap][1]; a constant specifying how to cap stroked paths, such as *butt*, *round*, or *square*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linecap" + }, + "strokeLinejoin": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linejoin][1]; a constant specifying how to join stroked paths, such as *bevel*, *miter*, *miter-clip*, or *round*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linejoin" + }, + "strokeMiterlimit": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-miterlimit][1]; a constant number specifying how to limit the length of *miter* joins on stroked paths.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-miterlimit" + }, + "strokeOpacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-opacity" + }, + "strokeWidth": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-width][1]; a constant number in pixels, or a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-width" + }, + "target": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [target][1]; a constant string specifying the target window (_e.g._,\n*_blank*) for clickable links; used in conjunction with the **href** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/target" + }, + "tip": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/TipPointer" + }, + { + "properties": { + "anchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The tip anchor specifies how to orient the tip box relative to its anchor position; it refers to the part of the tip box that is attached to the anchor point. For example, the *top-left* anchor places the top-left corner of tip box near the anchor position, hence placing the tip box below and to the right of the anchor position." + }, + "fontFamily": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font-family][1]; a constant; defaults to the plot’s font family, which is typically [*system-ui*][2].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-family [2]: https://drafts.csswg.org/css-fonts-4/#valdef-font-family-system-ui" + }, + "fontSize": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font size][1] in pixels; either a constant or a channel; defaults to the plot’s font size, which is typically 10. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-size" + }, + "fontStyle": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font style][1]; a constant; defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-style" + }, + "fontVariant": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font variant][1]; a constant; if the **text** channel contains numbers or dates, defaults to *tabular-nums* to facilitate comparing numbers; otherwise defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant" + }, + "fontWeight": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font weight][1]; a constant; defaults to the plot’s font weight, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight" + }, + "format": { + "additionalProperties": false, + "description": "How channel values are formatted for display. If a format is a string, it is interpreted as a (UTC) time format for temporal channels, and otherwise a number format.", + "properties": { + "ariaLabel": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fill": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fillOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fontSize": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fx": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fy": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "geometry": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "height": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "href": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "length": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "opacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "path": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "r": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "rotate": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "src": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "stroke": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeWidth": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "symbol": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "text": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "title": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "weight": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "width": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "z": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + } + }, + "type": "object" + }, + "frameAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The frame anchor specifies defaults for **x** and **y** based on the plot’s frame; it may be one of the four sides (*top*, *right*, *bottom*, *left*), one of the four corners (*top-left*, *top-right*, *bottom-right*,\n*bottom-left*), or the *middle* of the frame. For example, for tips distributed horizontally at the top of the frame:\n\n```js Plot.tip(data, {x: \"date\", frameAnchor: \"top\"}) ```" + }, + "lineHeight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line height in ems; defaults to 1. The line height affects the (typically vertical) separation between adjacent baselines of text, as well as the separation between the text and its anchor point." + }, + "lineWidth": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line width in ems (e.g., 10 for about 20 characters); defaults to infinity, disabling wrapping and clipping.\n\nIf **textOverflow** is null, lines will be wrapped at the specified length. If a line is split at a soft hyphen (\\xad), a hyphen (-) will be displayed at the end of the line. If **textOverflow** is not null, lines will be clipped according to the given strategy." + }, + "monospace": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, changes the default **fontFamily** to *monospace*, and uses simplified monospaced text metrics calculations." + }, + "pathFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The image filter for the tip’s box; defaults to a drop shadow." + }, + "pointer": { + "$ref": "#/definitions/TipPointer" + }, + "pointerSize": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The size of the tip’s pointer in pixels; defaults to 12." + }, + "preferredAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If an explicit tip anchor is not specified, an anchor is chosen automatically such that the tip fits within the plot’s frame; if the preferred anchor fits, it is chosen." + }, + "textAnchor": { + "anyOf": [ + { + "const": "start", + "type": "string" + }, + { + "const": "middle", + "type": "string" + }, + { + "const": "end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [text anchor][1] controls how text is aligned (typically horizontally) relative to its anchor point; it is one of *start*, *end*, or *middle*. If the frame anchor is *left*, *top-left*, or *bottom-left*, the default text anchor is *start*; if the frame anchor is *right*, *top-right*, or\n*bottom-right*, the default is *end*; otherwise it is *middle*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/text-anchor" + }, + "textOverflow": { + "anyOf": [ + { + "type": "null" + }, + { + "const": "clip", + "type": "string" + }, + { + "const": "ellipsis", + "type": "string" + }, + { + "const": "clip-start", + "type": "string" + }, + { + "const": "clip-end", + "type": "string" + }, + { + "const": "ellipsis-start", + "type": "string" + }, + { + "const": "ellipsis-middle", + "type": "string" + }, + { + "const": "ellipsis-end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How truncate (or wrap) lines of text longer than the given **lineWidth**; one of:\n\n- null (default) - preserve overflowing characters (and wrap if needed)\n- *clip* or *clip-end* - remove characters from the end\n- *clip-start* - remove characters from the start\n- *ellipsis* or *ellipsis-end* - replace characters from the end with an ellipsis (…)\n- *ellipsis-start* - replace characters from the start with an ellipsis (…)\n- *ellipsis-middle* - replace characters from the middle with an ellipsis (…)\n\nIf no **title** was specified, if text requires truncation, a title containing the non-truncated text will be implicitly added." + }, + "textPadding": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The padding around the text in pixels; defaults to 8." + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + } + }, + "type": "object" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to generate a tooltip for this mark, and any tip options." + }, + "title": { + "$ref": "#/definitions/ChannelValue", + "description": "The title; a channel specifying accessible, short textual descriptions as strings (possibly with newlines). If the tip option is specified, the title will be displayed with an interactive tooltip instead of using the SVG [title element][1].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/title" + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position of the vector’s anchor point; an optional channel bound to the *x* scale. Default depends on the **frameAnchor**." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position of the vector’s anchor point; an optional channel bound to the *y* scale. Default depends on the **frameAnchor**." + } + }, + "required": [ + "data", + "mark" + ], + "type": "object" + }, + "StackOffset": { + "$ref": "#/definitions/StackOffsetName", + "description": "A stack offset method; one of:\n\n- *normalize* - rescale each stack to fill [0, 1]\n- *center* - align the centers of all stacks\n- *wiggle* - translate stacks to minimize apparent movement\n\nIf a given stack has zero total value, the *normalize* offset will not adjust the stack’s position. Both the *center* and *wiggle* offsets ensure that the lowest element across stacks starts at zero for better default axes. The\n*wiggle* offset is recommended for streamgraphs in conjunction with the\n*inside-out* order. For more, see [Byron & Wattenberg][1].\n\n[1]: https://leebyron.com/streamgraph/" + }, + "StackOffsetName": { + "description": "A built-in stack offset method; one of:\n\n- *normalize* - rescale each stack to fill [0, 1]\n- *center* - align the centers of all stacks\n- *wiggle* - translate stacks to minimize apparent movement\n\nIf a given stack has zero total value, the *normalize* offset will not adjust the stack’s position. Both the *center* and *wiggle* offsets ensure that the lowest element across stacks starts at zero for better default axes. The\n*wiggle* offset is recommended for streamgraphs in conjunction with the\n*inside-out* order. For more, see [Byron & Wattenberg][1].\n\n[1]: https://leebyron.com/streamgraph/", + "enum": [ + "center", + "normalize", + "wiggle" + ], + "type": "string" + }, + "StackOrder": { + "anyOf": [ + { + "$ref": "#/definitions/StackOrderName" + }, + { + "const": "-value", + "type": "string" + }, + { + "const": "-x", + "type": "string" + }, + { + "const": "-y", + "type": "string" + }, + { + "const": "-z", + "type": "string" + }, + { + "const": "-sum", + "type": "string" + }, + { + "const": "-appearance", + "type": "string" + }, + { + "const": "-inside-out", + "type": "string" + }, + { + "type": "string" + }, + { + "items": {}, + "type": "array" + } + ], + "description": "How to order layers prior to stacking; one of:\n\n- a named stack order method such as *inside-out* or *sum*\n- a field name, for natural order of the corresponding values\n- an array of explicit **z** values in the desired order" + }, + "StackOrderName": { + "description": "The built-in stack order methods; one of:\n\n- *x* - alias of *value*; for stackX only\n- *y* - alias of *value*; for stackY only\n- *value* - ascending value (or descending with **reverse**)\n- *sum* - total value per series\n- *appearance* - position of maximum value per series\n- *inside-out* (default with *wiggle*) - order the earliest-appearing series on the inside\n\nThe *inside-out* order is recommended for streamgraphs in conjunction with the *wiggle* offset. For more, see [Byron & Wattenberg][1].\n\n[1]: https://leebyron.com/streamgraph/", + "enum": [ + "value", + "x", + "y", + "z", + "sum", + "appearance", + "inside-out" + ], + "type": "string" + }, + "Stddev": { + "additionalProperties": false, + "properties": { + "distinct": { + "type": "boolean" + }, + "orderby": { + "anyOf": [ + { + "$ref": "#/definitions/TransformField" + }, + { + "items": { + "$ref": "#/definitions/TransformField" + }, + "type": "array" + } + ] + }, + "partitionby": { + "anyOf": [ + { + "$ref": "#/definitions/TransformField" + }, + { + "items": { + "$ref": "#/definitions/TransformField" + }, + "type": "array" + } + ] + }, + "range": { + "anyOf": [ + { + "items": { + "type": [ + "number", + "null" + ] + }, + "type": "array" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "rows": { + "anyOf": [ + { + "items": { + "type": [ + "number", + "null" + ] + }, + "type": "array" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "stddev": { + "anyOf": [ + { + "description": "A transform argument.", + "type": [ + "string", + "number", + "boolean" + ] + }, + { + "items": { + "description": "A transform argument.", + "type": [ + "string", + "number", + "boolean" + ] + }, + "maxItems": 1, + "minItems": 1, + "type": "array" + } + ], + "description": "Compute the sum of the given column." + } + }, + "required": [ + "stddev" + ], + "type": "object" + }, + "StddevPop": { + "additionalProperties": false, + "properties": { + "distinct": { + "type": "boolean" + }, + "orderby": { + "anyOf": [ + { + "$ref": "#/definitions/TransformField" + }, + { + "items": { + "$ref": "#/definitions/TransformField" + }, + "type": "array" + } + ] + }, + "partitionby": { + "anyOf": [ + { + "$ref": "#/definitions/TransformField" + }, + { + "items": { + "$ref": "#/definitions/TransformField" + }, + "type": "array" + } + ] + }, + "range": { + "anyOf": [ + { + "items": { + "type": [ + "number", + "null" + ] + }, + "type": "array" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "rows": { + "anyOf": [ + { + "items": { + "type": [ + "number", + "null" + ] + }, + "type": "array" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "stddevPop": { + "anyOf": [ + { + "description": "A transform argument.", + "type": [ + "string", + "number", + "boolean" + ] + }, + { + "items": { + "description": "A transform argument.", + "type": [ + "string", + "number", + "boolean" + ] + }, + "maxItems": 1, + "minItems": 1, + "type": "array" + } + ], + "description": "Compute the sum of the given column." + } + }, + "required": [ + "stddevPop" + ], + "type": "object" + }, + "Sum": { + "additionalProperties": false, + "properties": { + "distinct": { + "type": "boolean" + }, + "orderby": { + "anyOf": [ + { + "$ref": "#/definitions/TransformField" + }, + { + "items": { + "$ref": "#/definitions/TransformField" + }, + "type": "array" + } + ] + }, + "partitionby": { + "anyOf": [ + { + "$ref": "#/definitions/TransformField" + }, + { + "items": { + "$ref": "#/definitions/TransformField" + }, + "type": "array" + } + ] + }, + "range": { + "anyOf": [ + { + "items": { + "type": [ + "number", + "null" + ] + }, + "type": "array" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "rows": { + "anyOf": [ + { + "items": { + "type": [ + "number", + "null" + ] + }, + "type": "array" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "sum": { + "anyOf": [ + { + "description": "A transform argument.", + "type": [ + "string", + "number", + "boolean" + ] + }, + { + "items": { + "description": "A transform argument.", + "type": [ + "string", + "number", + "boolean" + ] + }, + "maxItems": 1, + "minItems": 1, + "type": "array" + } + ], + "description": "Compute the sum of the given column." + } + }, + "required": [ + "sum" + ], + "type": "object" + }, + "SymbolType": { + "description": "The built-in symbol implementations. For fill, one of:\n\n- *circle* - a circle\n- *cross* - a Greek cross with arms of equal length\n- *diamond* - a rhombus\n- *square* - a square\n- *star* - a pentagonal star (pentagram)\n- *triangle* - an up-pointing triangle\n- *wye* - a Y with arms of equal length\n\nFor stroke (based on [Heman Robinson’s research][1]), one of:\n\n- *circle* - a circle\n- *plus* - a plus sign\n- *times* - an X with arms of equal length\n- *triangle2* - an (alternate) up-pointing triangle\n- *asterisk* - an asterisk\n- *square2* - a (alternate) square\n- *diamond2* - a rotated square\n\nThe *hexagon* symbol is also supported.\n\n[1]: https://www.tandfonline.com/doi/abs/10.1080/10618600.2019.1637746", + "enum": [ + "asterisk", + "circle", + "cross", + "diamond", + "diamond2", + "hexagon", + "plus", + "square", + "square2", + "star", + "times", + "triangle", + "triangle2", + "wye" + ], + "type": "string" + }, + "Table": { + "additionalProperties": false, + "description": "A table grid view component.", + "properties": { + "align": { + "additionalProperties": { + "enum": [ + "left", + "right", + "center", + "justify" + ], + "type": "string" + }, + "description": "An object of per-column alignment values. Column names should be object keys, which map to alignment values. Valid alignment values are: `\"left\"`, `\"right\"`, `\"center\"`, and `\"justify\"`. By default, numbers are right-aligned and other values are left-aligned.", + "type": "object" + }, + "as": { + "$ref": "#/definitions/ParamRef", + "description": "The output selection. A selection clause is added for each currently selected table row." + }, + "columns": { + "description": "A list of column names to include in the table grid. If unspecified, all table columns are included.", + "items": { + "type": "string" + }, + "type": "array" + }, + "filterBy": { + "$ref": "#/definitions/ParamRef", + "description": "A selection to filter the database table indicated by the `from` property." + }, + "from": { + "description": "The name of a database table to use as a data source for this widget.", + "type": "string" + }, + "height": { + "description": "The height of the table widget, in pixels.", + "type": "number" + }, + "input": { + "const": "table", + "description": "A table grid widget.", + "type": "string" + }, + "maxWidth": { + "description": "The maximum width of the table widget, in pixels.", + "type": "number" + }, + "rowBatch": { + "description": "The number of rows load in a new batch upon table scroll.", + "type": "number" + }, + "width": { + "anyOf": [ + { + "type": "number" + }, + { + "additionalProperties": { + "type": "number" + }, + "type": "object" + } + ], + "description": "If a number, sets the total width of the table widget, in pixels. If an object, provides per-column pixel width values. Column names should be object keys, mapped to numeric width values." + } + }, + "required": [ + "input", + "from" + ], + "type": "object" + }, + "Text": { + "additionalProperties": false, + "description": "The text mark.", + "properties": { + "ariaDescription": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-description][1]; a constant textual description.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-description" + }, + "ariaHidden": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-hidden][1] state; a constant indicating whether the element is exposed to an accessibility API.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-hidden" + }, + "ariaLabel": { + "$ref": "#/definitions/ChannelValue", + "description": "The [aria-label][1]; a channel specifying short textual labels representing the value in the accessibility tree.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-label" + }, + "clip": { + "anyOf": [ + { + "const": "frame", + "type": "string" + }, + { + "const": "sphere", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to clip the mark; one of:\n\n- *frame* or true - clip to the plot’s frame (inner area)\n- *sphere* - clip to the projected sphere (*e.g.*, front hemisphere)\n- null or false - do not clip\n\nThe *sphere* clip option requires a geographic projection." + }, + "data": { + "$ref": "#/definitions/PlotMarkData", + "description": "The data source for the mark." + }, + "dx": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The horizontal offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "dy": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The vertical offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "facet": { + "anyOf": [ + { + "const": "auto", + "type": "string" + }, + { + "const": "include", + "type": "string" + }, + { + "const": "exclude", + "type": "string" + }, + { + "const": "super", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to enable or disable faceting; one of:\n\n- *auto* (default) - automatically determine if this mark should be faceted\n- *include* (or true) - draw the subset of the mark’s data in the current facet\n- *exclude* - draw the subset of the mark’s data *not* in the current facet\n- *super* - draw this mark in a single frame that covers all facets\n- null (or false) - repeat this mark’s data across all facets (*i.e.*, no faceting)\n\nWhen a mark uses *super* faceting, it is not allowed to use position scales (*x*, *y*, *fx*, or *fy*); *super* faceting is intended for decorations, such as labels and legends.\n\nWhen top-level faceting is used, the default *auto* setting is equivalent to *include* when the mark data is strictly equal to the top-level facet data; otherwise it is equivalent to null. When the *include* or *exclude* facet mode is chosen, the mark data must be parallel to the top-level facet data: the data must have the same length and order. If the data are not parallel, then the wrong data may be shown in each facet. The default\n*auto* therefore requires strict equality (`===`) for safety, and using the facet data as mark data is recommended when using the *exclude* facet mode. (To construct parallel data safely, consider using [*array*.map][1] on the facet data.)\n\nWhen mark-level faceting is used, the default *auto* setting is equivalent to *include*: the mark will be faceted if either the **fx** or **fy** channel option (or both) is specified. The null or false option will disable faceting, while *exclude* draws the subset of the mark’s data *not* in the current facet.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map" + }, + "facetAnchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "right", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "const": "left", + "type": "string" + }, + { + "const": "top-left", + "type": "string" + }, + { + "const": "top-right", + "type": "string" + }, + { + "const": "bottom-left", + "type": "string" + }, + { + "const": "bottom-right", + "type": "string" + }, + { + "const": "top-empty", + "type": "string" + }, + { + "const": "right-empty", + "type": "string" + }, + { + "const": "bottom-empty", + "type": "string" + }, + { + "const": "left-empty", + "type": "string" + }, + { + "const": "empty", + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to place the mark with respect to facets; one of:\n\n- null (default for most marks) - display the mark in each non-empty facet\n- *top*, *right*, *bottom*, or *left* - display the mark only in facets on the given side\n- *top-empty*, *right-empty*, *bottom-empty*, or *left-empty* (default for axis marks) - display the mark only in facets that have empty space on the given side: either the margin, or an empty facet\n- *empty* - display the mark in empty facets only" + }, + "fill": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill" + }, + "fillOpacity": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill-opacity][1]; a constant number between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill-opacity" + }, + "filter": { + "$ref": "#/definitions/ChannelValue", + "description": "Applies a transform to filter the mark’s index according to the given channel values; only truthy values are retained.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "fontFamily": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font-family][1]; a constant; defaults to the plot’s font family, which is typically [*system-ui*][2].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-family [2]: https://drafts.csswg.org/css-fonts-4/#valdef-font-family-system-ui" + }, + "fontSize": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font size][1] in pixels; either a constant or a channel; defaults to the plot’s font size, which is typically 10. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-size" + }, + "fontStyle": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font style][1]; a constant; defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-style" + }, + "fontVariant": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font variant][1]; a constant; if the **text** channel contains numbers or dates, defaults to *tabular-nums* to facilitate comparing numbers; otherwise defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant" + }, + "fontWeight": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font weight][1]; a constant; defaults to the plot’s font weight, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight" + }, + "frameAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The frame anchor specifies defaults for **x** and **y**, along with\n**textAnchor** and **lineAnchor**, based on the plot’s frame; it may be one of the four sides (*top*, *right*, *bottom*, *left*), one of the four corners (*top-left*, *top-right*, *bottom-right*, *bottom-left*), or the\n*middle* of the frame." + }, + "fx": { + "$ref": "#/definitions/ChannelValue", + "description": "The horizontal facet position channel, for mark-level faceting, bound to the *fx* scale." + }, + "fy": { + "$ref": "#/definitions/ChannelValue", + "description": "The vertical facet position channel, for mark-level faceting, bound to the\n*fy* scale." + }, + "href": { + "$ref": "#/definitions/ChannelValue", + "description": "The [href][1]; a channel specifying URLs for clickable links. May be used in conjunction with the **target** option to open links in another window.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/href" + }, + "imageFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A CSS [filter][1]; a constant string used to adjust the rendering of images, such as *blur(5px)*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/filter" + }, + "lineAnchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "middle", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line anchor controls how text is aligned (typically vertically) relative to its anchor point; it is one of *top*, *bottom*, or *middle*. If the frame anchor is *top*, *top-left*, or *top-right*, the default line anchor is *top*; if the frame anchor is *bottom*, *bottom-right*, or\n*bottom-left*, the default is *bottom*; otherwise it is *middle*." + }, + "lineHeight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line height in ems; defaults to 1. The line height affects the (typically vertical) separation between adjacent baselines of text, as well as the separation between the text and its anchor point." + }, + "lineWidth": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line width in ems (e.g., 10 for about 20 characters); defaults to infinity, disabling wrapping and clipping.\n\nIf **textOverflow** is null, lines will be wrapped at the specified length. If a line is split at a soft hyphen (\\xad), a hyphen (-) will be displayed at the end of the line. If **textOverflow** is not null, lines will be clipped according to the given strategy." + }, + "margin": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four mark margins: **marginTop**,\n**marginRight**, **marginBottom**, and **marginLeft**; typically defaults to 0, except for axis marks." + }, + "marginBottom": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s bottom margin; the minimum distance in pixels between the bottom edges of the inner and outer plot area." + }, + "marginLeft": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s left margin; the minimum distance in pixels between the left edges of the inner and outer plot area." + }, + "marginRight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s right margin; the minimum distance in pixels between the right edges of the mark’s inner and outer plot area." + }, + "marginTop": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s top margin; the minimum distance in pixels between the top edges of the inner and outer plot area." + }, + "mark": { + "const": "text", + "description": "A text mark. The **text** channel specifies the textual contents of the mark, which may be preformatted with line breaks (\\n, \\r\\n, or \\r), or wrapped or clipped using the **lineWidth** and **textOverflow** options.\n\nIf **text** contains numbers or dates, a default formatter will be applied, and the **fontVariant** will default to *tabular-nums* instead of *normal*. If **text** is not specified, it defaults to the identity function for primitive data (such as numbers, dates, and strings), and to the zero-based index [0, 1, 2, …] for objects (so that something identifying is visible by default).\n\nIf either **x** or **y** is not specified, the default is determined by the **frameAnchor** option.", + "type": "string" + }, + "mixBlendMode": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [mix-blend-mode][1]; a constant string specifying how to blend content such as *multiply*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode" + }, + "monospace": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, changes the default **fontFamily** to *monospace*, and uses simplified monospaced text metrics calculations." + }, + "opacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally. For faster rendering, prefer the **strokeOpacity** or **fillOpacity** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/opacity" + }, + "paintOrder": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [paint-order][1]; a constant string specifying the order in which the\n**fill**, **stroke**, and any markers are drawn; defaults to *normal*, which draws the fill, then stroke, then markers; defaults to *stroke* for the text mark to create a “halo” around text to improve legibility.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/paint-order" + }, + "pointerEvents": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [pointer-events][1] property; a constant string such as *none*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/pointer-events" + }, + "reverse": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Applies a transform to reverse the order of the mark’s index, say for reverse input order." + }, + "rotate": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The rotation angle in degrees clockwise; a constant or a channel; defaults to 0°. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel." + }, + "select": { + "$ref": "#/definitions/SelectFilter", + "description": "Applies a filter transform after data is loaded to highlight selected values only. For example, `first` and `last` select the first or last values of series only (using the *z* channel to separate series). Meanwhile, `nearestX` and `nearestY` select the point nearest to the pointer along the *x* or *y* channel dimension. Unlike Mosaic selections, a mark level *select* is internal to the mark only, and does not populate a param or selection value to be shared across clients.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "shapeRendering": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [shape-rendering][1]; a constant string such as *crispEdges*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/shape-rendering" + }, + "sort": { + "anyOf": [ + { + "$ref": "#/definitions/SortOrder" + }, + { + "$ref": "#/definitions/ChannelDomainSort" + } + ], + "description": "Either applies a transform to sort the mark’s index by the specified channel values, or imputes ordinal scale domains from this mark’s channels.\n\nWhen imputing ordinal scale domains from channel values, the **sort** option is an object whose keys are ordinal scale names such as *x* or *fx*, and whose values are channel names such as *y*, *y1*, or *y2*. For example, to impute the *y* scale’s domain from the associated *x* channel values in ascending order:\n\n```js sort: {y: \"x\"} ```\n\nFor different sort options for different scales, replace the channel name with a *value* object and per-scale options:\n\n```js sort: {y: {value: \"-x\"}} ```\n\nWhen sorting the mark’s index, the **sort** option is instead one of:\n\n- a channel value definition for sorting given values in ascending order\n- a {value, order} object for sorting given values\n- a {channel, order} object for sorting the named channel’s values" + }, + "stroke": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke" + }, + "strokeDasharray": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dasharray][1]; a constant number indicating the length in pixels of alternating dashes and gaps, or a constant string of numbers separated by spaces or commas (_e.g._, *10 2* for dashes of 10 pixels separated by gaps of 2 pixels), or *none* (the default) for no dashing\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dasharray" + }, + "strokeDashoffset": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dashoffset][1]; a constant indicating the offset in pixels of the first dash along the stroke; defaults to zero.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dashoffset" + }, + "strokeLinecap": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linecap][1]; a constant specifying how to cap stroked paths, such as *butt*, *round*, or *square*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linecap" + }, + "strokeLinejoin": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linejoin][1]; a constant specifying how to join stroked paths, such as *bevel*, *miter*, *miter-clip*, or *round*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linejoin" + }, + "strokeMiterlimit": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-miterlimit][1]; a constant number specifying how to limit the length of *miter* joins on stroked paths.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-miterlimit" + }, + "strokeOpacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-opacity" + }, + "strokeWidth": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-width][1]; a constant number in pixels, or a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-width" + }, + "target": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [target][1]; a constant string specifying the target window (_e.g._,\n*_blank*) for clickable links; used in conjunction with the **href** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/target" + }, + "text": { + "$ref": "#/definitions/ChannelValue", + "description": "The text contents channel, possibly with line breaks (\\n, \\r\\n, or \\r). If not specified, defaults to the zero-based index [0, 1, 2, …]." + }, + "textAnchor": { + "anyOf": [ + { + "const": "start", + "type": "string" + }, + { + "const": "middle", + "type": "string" + }, + { + "const": "end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [text anchor][1] controls how text is aligned (typically horizontally) relative to its anchor point; it is one of *start*, *end*, or *middle*. If the frame anchor is *left*, *top-left*, or *bottom-left*, the default text anchor is *start*; if the frame anchor is *right*, *top-right*, or\n*bottom-right*, the default is *end*; otherwise it is *middle*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/text-anchor" + }, + "textOverflow": { + "anyOf": [ + { + "type": "null" + }, + { + "const": "clip", + "type": "string" + }, + { + "const": "ellipsis", + "type": "string" + }, + { + "const": "clip-start", + "type": "string" + }, + { + "const": "clip-end", + "type": "string" + }, + { + "const": "ellipsis-start", + "type": "string" + }, + { + "const": "ellipsis-middle", + "type": "string" + }, + { + "const": "ellipsis-end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How truncate (or wrap) lines of text longer than the given **lineWidth**; one of:\n\n- null (default) - preserve overflowing characters (and wrap if needed)\n- *clip* or *clip-end* - remove characters from the end\n- *clip-start* - remove characters from the start\n- *ellipsis* or *ellipsis-end* - replace characters from the end with an ellipsis (…)\n- *ellipsis-start* - replace characters from the start with an ellipsis (…)\n- *ellipsis-middle* - replace characters from the middle with an ellipsis (…)\n\nIf no **title** was specified, if text requires truncation, a title containing the non-truncated text will be implicitly added." + }, + "tip": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/TipPointer" + }, + { + "properties": { + "anchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The tip anchor specifies how to orient the tip box relative to its anchor position; it refers to the part of the tip box that is attached to the anchor point. For example, the *top-left* anchor places the top-left corner of tip box near the anchor position, hence placing the tip box below and to the right of the anchor position." + }, + "fontFamily": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font-family][1]; a constant; defaults to the plot’s font family, which is typically [*system-ui*][2].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-family [2]: https://drafts.csswg.org/css-fonts-4/#valdef-font-family-system-ui" + }, + "fontSize": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font size][1] in pixels; either a constant or a channel; defaults to the plot’s font size, which is typically 10. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-size" + }, + "fontStyle": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font style][1]; a constant; defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-style" + }, + "fontVariant": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font variant][1]; a constant; if the **text** channel contains numbers or dates, defaults to *tabular-nums* to facilitate comparing numbers; otherwise defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant" + }, + "fontWeight": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font weight][1]; a constant; defaults to the plot’s font weight, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight" + }, + "format": { + "additionalProperties": false, + "description": "How channel values are formatted for display. If a format is a string, it is interpreted as a (UTC) time format for temporal channels, and otherwise a number format.", + "properties": { + "ariaLabel": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fill": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fillOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fontSize": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fx": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fy": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "geometry": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "height": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "href": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "length": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "opacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "path": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "r": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "rotate": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "src": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "stroke": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeWidth": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "symbol": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "text": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "title": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "weight": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "width": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "z": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + } + }, + "type": "object" + }, + "frameAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The frame anchor specifies defaults for **x** and **y** based on the plot’s frame; it may be one of the four sides (*top*, *right*, *bottom*, *left*), one of the four corners (*top-left*, *top-right*, *bottom-right*,\n*bottom-left*), or the *middle* of the frame. For example, for tips distributed horizontally at the top of the frame:\n\n```js Plot.tip(data, {x: \"date\", frameAnchor: \"top\"}) ```" + }, + "lineHeight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line height in ems; defaults to 1. The line height affects the (typically vertical) separation between adjacent baselines of text, as well as the separation between the text and its anchor point." + }, + "lineWidth": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line width in ems (e.g., 10 for about 20 characters); defaults to infinity, disabling wrapping and clipping.\n\nIf **textOverflow** is null, lines will be wrapped at the specified length. If a line is split at a soft hyphen (\\xad), a hyphen (-) will be displayed at the end of the line. If **textOverflow** is not null, lines will be clipped according to the given strategy." + }, + "monospace": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, changes the default **fontFamily** to *monospace*, and uses simplified monospaced text metrics calculations." + }, + "pathFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The image filter for the tip’s box; defaults to a drop shadow." + }, + "pointer": { + "$ref": "#/definitions/TipPointer" + }, + "pointerSize": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The size of the tip’s pointer in pixels; defaults to 12." + }, + "preferredAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If an explicit tip anchor is not specified, an anchor is chosen automatically such that the tip fits within the plot’s frame; if the preferred anchor fits, it is chosen." + }, + "textAnchor": { + "anyOf": [ + { + "const": "start", + "type": "string" + }, + { + "const": "middle", + "type": "string" + }, + { + "const": "end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [text anchor][1] controls how text is aligned (typically horizontally) relative to its anchor point; it is one of *start*, *end*, or *middle*. If the frame anchor is *left*, *top-left*, or *bottom-left*, the default text anchor is *start*; if the frame anchor is *right*, *top-right*, or\n*bottom-right*, the default is *end*; otherwise it is *middle*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/text-anchor" + }, + "textOverflow": { + "anyOf": [ + { + "type": "null" + }, + { + "const": "clip", + "type": "string" + }, + { + "const": "ellipsis", + "type": "string" + }, + { + "const": "clip-start", + "type": "string" + }, + { + "const": "clip-end", + "type": "string" + }, + { + "const": "ellipsis-start", + "type": "string" + }, + { + "const": "ellipsis-middle", + "type": "string" + }, + { + "const": "ellipsis-end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How truncate (or wrap) lines of text longer than the given **lineWidth**; one of:\n\n- null (default) - preserve overflowing characters (and wrap if needed)\n- *clip* or *clip-end* - remove characters from the end\n- *clip-start* - remove characters from the start\n- *ellipsis* or *ellipsis-end* - replace characters from the end with an ellipsis (…)\n- *ellipsis-start* - replace characters from the start with an ellipsis (…)\n- *ellipsis-middle* - replace characters from the middle with an ellipsis (…)\n\nIf no **title** was specified, if text requires truncation, a title containing the non-truncated text will be implicitly added." + }, + "textPadding": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The padding around the text in pixels; defaults to 8." + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + } + }, + "type": "object" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to generate a tooltip for this mark, and any tip options." + }, + "title": { + "$ref": "#/definitions/ChannelValue", + "description": "The title; a channel specifying accessible, short textual descriptions as strings (possibly with newlines). If the tip option is specified, the title will be displayed with an interactive tooltip instead of using the SVG [title element][1].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/title" + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel specifying the text’s anchor point, typically bound to the *x* scale." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel specifying the text’s anchor point, typically bound to the *y* scale." + }, + "z": { + "$ref": "#/definitions/ChannelValue", + "description": "An optional ordinal channel for grouping data into series." + } + }, + "required": [ + "mark" + ], + "type": "object" + }, + "TextX": { + "additionalProperties": false, + "description": "The textX mark.", + "properties": { + "ariaDescription": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-description][1]; a constant textual description.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-description" + }, + "ariaHidden": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-hidden][1] state; a constant indicating whether the element is exposed to an accessibility API.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-hidden" + }, + "ariaLabel": { + "$ref": "#/definitions/ChannelValue", + "description": "The [aria-label][1]; a channel specifying short textual labels representing the value in the accessibility tree.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-label" + }, + "clip": { + "anyOf": [ + { + "const": "frame", + "type": "string" + }, + { + "const": "sphere", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to clip the mark; one of:\n\n- *frame* or true - clip to the plot’s frame (inner area)\n- *sphere* - clip to the projected sphere (*e.g.*, front hemisphere)\n- null or false - do not clip\n\nThe *sphere* clip option requires a geographic projection." + }, + "data": { + "$ref": "#/definitions/PlotMarkData", + "description": "The data source for the mark." + }, + "dx": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The horizontal offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "dy": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The vertical offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "facet": { + "anyOf": [ + { + "const": "auto", + "type": "string" + }, + { + "const": "include", + "type": "string" + }, + { + "const": "exclude", + "type": "string" + }, + { + "const": "super", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to enable or disable faceting; one of:\n\n- *auto* (default) - automatically determine if this mark should be faceted\n- *include* (or true) - draw the subset of the mark’s data in the current facet\n- *exclude* - draw the subset of the mark’s data *not* in the current facet\n- *super* - draw this mark in a single frame that covers all facets\n- null (or false) - repeat this mark’s data across all facets (*i.e.*, no faceting)\n\nWhen a mark uses *super* faceting, it is not allowed to use position scales (*x*, *y*, *fx*, or *fy*); *super* faceting is intended for decorations, such as labels and legends.\n\nWhen top-level faceting is used, the default *auto* setting is equivalent to *include* when the mark data is strictly equal to the top-level facet data; otherwise it is equivalent to null. When the *include* or *exclude* facet mode is chosen, the mark data must be parallel to the top-level facet data: the data must have the same length and order. If the data are not parallel, then the wrong data may be shown in each facet. The default\n*auto* therefore requires strict equality (`===`) for safety, and using the facet data as mark data is recommended when using the *exclude* facet mode. (To construct parallel data safely, consider using [*array*.map][1] on the facet data.)\n\nWhen mark-level faceting is used, the default *auto* setting is equivalent to *include*: the mark will be faceted if either the **fx** or **fy** channel option (or both) is specified. The null or false option will disable faceting, while *exclude* draws the subset of the mark’s data *not* in the current facet.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map" + }, + "facetAnchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "right", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "const": "left", + "type": "string" + }, + { + "const": "top-left", + "type": "string" + }, + { + "const": "top-right", + "type": "string" + }, + { + "const": "bottom-left", + "type": "string" + }, + { + "const": "bottom-right", + "type": "string" + }, + { + "const": "top-empty", + "type": "string" + }, + { + "const": "right-empty", + "type": "string" + }, + { + "const": "bottom-empty", + "type": "string" + }, + { + "const": "left-empty", + "type": "string" + }, + { + "const": "empty", + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to place the mark with respect to facets; one of:\n\n- null (default for most marks) - display the mark in each non-empty facet\n- *top*, *right*, *bottom*, or *left* - display the mark only in facets on the given side\n- *top-empty*, *right-empty*, *bottom-empty*, or *left-empty* (default for axis marks) - display the mark only in facets that have empty space on the given side: either the margin, or an empty facet\n- *empty* - display the mark in empty facets only" + }, + "fill": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill" + }, + "fillOpacity": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill-opacity][1]; a constant number between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill-opacity" + }, + "filter": { + "$ref": "#/definitions/ChannelValue", + "description": "Applies a transform to filter the mark’s index according to the given channel values; only truthy values are retained.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "fontFamily": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font-family][1]; a constant; defaults to the plot’s font family, which is typically [*system-ui*][2].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-family [2]: https://drafts.csswg.org/css-fonts-4/#valdef-font-family-system-ui" + }, + "fontSize": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font size][1] in pixels; either a constant or a channel; defaults to the plot’s font size, which is typically 10. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-size" + }, + "fontStyle": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font style][1]; a constant; defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-style" + }, + "fontVariant": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font variant][1]; a constant; if the **text** channel contains numbers or dates, defaults to *tabular-nums* to facilitate comparing numbers; otherwise defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant" + }, + "fontWeight": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font weight][1]; a constant; defaults to the plot’s font weight, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight" + }, + "frameAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The frame anchor specifies defaults for **x** and **y**, along with\n**textAnchor** and **lineAnchor**, based on the plot’s frame; it may be one of the four sides (*top*, *right*, *bottom*, *left*), one of the four corners (*top-left*, *top-right*, *bottom-right*, *bottom-left*), or the\n*middle* of the frame." + }, + "fx": { + "$ref": "#/definitions/ChannelValue", + "description": "The horizontal facet position channel, for mark-level faceting, bound to the *fx* scale." + }, + "fy": { + "$ref": "#/definitions/ChannelValue", + "description": "The vertical facet position channel, for mark-level faceting, bound to the\n*fy* scale." + }, + "href": { + "$ref": "#/definitions/ChannelValue", + "description": "The [href][1]; a channel specifying URLs for clickable links. May be used in conjunction with the **target** option to open links in another window.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/href" + }, + "imageFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A CSS [filter][1]; a constant string used to adjust the rendering of images, such as *blur(5px)*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/filter" + }, + "interval": { + "anyOf": [ + { + "$ref": "#/definitions/Interval" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "An interval (such as *day* or a number), to transform **y** values to the middle of the interval." + }, + "lineAnchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "middle", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line anchor controls how text is aligned (typically vertically) relative to its anchor point; it is one of *top*, *bottom*, or *middle*. If the frame anchor is *top*, *top-left*, or *top-right*, the default line anchor is *top*; if the frame anchor is *bottom*, *bottom-right*, or\n*bottom-left*, the default is *bottom*; otherwise it is *middle*." + }, + "lineHeight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line height in ems; defaults to 1. The line height affects the (typically vertical) separation between adjacent baselines of text, as well as the separation between the text and its anchor point." + }, + "lineWidth": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line width in ems (e.g., 10 for about 20 characters); defaults to infinity, disabling wrapping and clipping.\n\nIf **textOverflow** is null, lines will be wrapped at the specified length. If a line is split at a soft hyphen (\\xad), a hyphen (-) will be displayed at the end of the line. If **textOverflow** is not null, lines will be clipped according to the given strategy." + }, + "margin": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four mark margins: **marginTop**,\n**marginRight**, **marginBottom**, and **marginLeft**; typically defaults to 0, except for axis marks." + }, + "marginBottom": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s bottom margin; the minimum distance in pixels between the bottom edges of the inner and outer plot area." + }, + "marginLeft": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s left margin; the minimum distance in pixels between the left edges of the inner and outer plot area." + }, + "marginRight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s right margin; the minimum distance in pixels between the right edges of the mark’s inner and outer plot area." + }, + "marginTop": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s top margin; the minimum distance in pixels between the top edges of the inner and outer plot area." + }, + "mark": { + "const": "textX", + "description": "Like text, but **x** defaults to the identity function, assuming that\n*data* = [*x₀*, *x₁*, *x₂*, …]. If an **interval** is specified, such as\n*day*, **y** is transformed to the middle of the interval.", + "type": "string" + }, + "mixBlendMode": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [mix-blend-mode][1]; a constant string specifying how to blend content such as *multiply*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode" + }, + "monospace": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, changes the default **fontFamily** to *monospace*, and uses simplified monospaced text metrics calculations." + }, + "opacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally. For faster rendering, prefer the **strokeOpacity** or **fillOpacity** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/opacity" + }, + "paintOrder": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [paint-order][1]; a constant string specifying the order in which the\n**fill**, **stroke**, and any markers are drawn; defaults to *normal*, which draws the fill, then stroke, then markers; defaults to *stroke* for the text mark to create a “halo” around text to improve legibility.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/paint-order" + }, + "pointerEvents": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [pointer-events][1] property; a constant string such as *none*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/pointer-events" + }, + "reverse": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Applies a transform to reverse the order of the mark’s index, say for reverse input order." + }, + "rotate": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The rotation angle in degrees clockwise; a constant or a channel; defaults to 0°. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel." + }, + "select": { + "$ref": "#/definitions/SelectFilter", + "description": "Applies a filter transform after data is loaded to highlight selected values only. For example, `first` and `last` select the first or last values of series only (using the *z* channel to separate series). Meanwhile, `nearestX` and `nearestY` select the point nearest to the pointer along the *x* or *y* channel dimension. Unlike Mosaic selections, a mark level *select* is internal to the mark only, and does not populate a param or selection value to be shared across clients.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "shapeRendering": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [shape-rendering][1]; a constant string such as *crispEdges*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/shape-rendering" + }, + "sort": { + "anyOf": [ + { + "$ref": "#/definitions/SortOrder" + }, + { + "$ref": "#/definitions/ChannelDomainSort" + } + ], + "description": "Either applies a transform to sort the mark’s index by the specified channel values, or imputes ordinal scale domains from this mark’s channels.\n\nWhen imputing ordinal scale domains from channel values, the **sort** option is an object whose keys are ordinal scale names such as *x* or *fx*, and whose values are channel names such as *y*, *y1*, or *y2*. For example, to impute the *y* scale’s domain from the associated *x* channel values in ascending order:\n\n```js sort: {y: \"x\"} ```\n\nFor different sort options for different scales, replace the channel name with a *value* object and per-scale options:\n\n```js sort: {y: {value: \"-x\"}} ```\n\nWhen sorting the mark’s index, the **sort** option is instead one of:\n\n- a channel value definition for sorting given values in ascending order\n- a {value, order} object for sorting given values\n- a {channel, order} object for sorting the named channel’s values" + }, + "stroke": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke" + }, + "strokeDasharray": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dasharray][1]; a constant number indicating the length in pixels of alternating dashes and gaps, or a constant string of numbers separated by spaces or commas (_e.g._, *10 2* for dashes of 10 pixels separated by gaps of 2 pixels), or *none* (the default) for no dashing\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dasharray" + }, + "strokeDashoffset": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dashoffset][1]; a constant indicating the offset in pixels of the first dash along the stroke; defaults to zero.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dashoffset" + }, + "strokeLinecap": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linecap][1]; a constant specifying how to cap stroked paths, such as *butt*, *round*, or *square*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linecap" + }, + "strokeLinejoin": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linejoin][1]; a constant specifying how to join stroked paths, such as *bevel*, *miter*, *miter-clip*, or *round*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linejoin" + }, + "strokeMiterlimit": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-miterlimit][1]; a constant number specifying how to limit the length of *miter* joins on stroked paths.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-miterlimit" + }, + "strokeOpacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-opacity" + }, + "strokeWidth": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-width][1]; a constant number in pixels, or a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-width" + }, + "target": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [target][1]; a constant string specifying the target window (_e.g._,\n*_blank*) for clickable links; used in conjunction with the **href** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/target" + }, + "text": { + "$ref": "#/definitions/ChannelValue", + "description": "The text contents channel, possibly with line breaks (\\n, \\r\\n, or \\r). If not specified, defaults to the zero-based index [0, 1, 2, …]." + }, + "textAnchor": { + "anyOf": [ + { + "const": "start", + "type": "string" + }, + { + "const": "middle", + "type": "string" + }, + { + "const": "end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [text anchor][1] controls how text is aligned (typically horizontally) relative to its anchor point; it is one of *start*, *end*, or *middle*. If the frame anchor is *left*, *top-left*, or *bottom-left*, the default text anchor is *start*; if the frame anchor is *right*, *top-right*, or\n*bottom-right*, the default is *end*; otherwise it is *middle*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/text-anchor" + }, + "textOverflow": { + "anyOf": [ + { + "type": "null" + }, + { + "const": "clip", + "type": "string" + }, + { + "const": "ellipsis", + "type": "string" + }, + { + "const": "clip-start", + "type": "string" + }, + { + "const": "clip-end", + "type": "string" + }, + { + "const": "ellipsis-start", + "type": "string" + }, + { + "const": "ellipsis-middle", + "type": "string" + }, + { + "const": "ellipsis-end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How truncate (or wrap) lines of text longer than the given **lineWidth**; one of:\n\n- null (default) - preserve overflowing characters (and wrap if needed)\n- *clip* or *clip-end* - remove characters from the end\n- *clip-start* - remove characters from the start\n- *ellipsis* or *ellipsis-end* - replace characters from the end with an ellipsis (…)\n- *ellipsis-start* - replace characters from the start with an ellipsis (…)\n- *ellipsis-middle* - replace characters from the middle with an ellipsis (…)\n\nIf no **title** was specified, if text requires truncation, a title containing the non-truncated text will be implicitly added." + }, + "tip": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/TipPointer" + }, + { + "properties": { + "anchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The tip anchor specifies how to orient the tip box relative to its anchor position; it refers to the part of the tip box that is attached to the anchor point. For example, the *top-left* anchor places the top-left corner of tip box near the anchor position, hence placing the tip box below and to the right of the anchor position." + }, + "fontFamily": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font-family][1]; a constant; defaults to the plot’s font family, which is typically [*system-ui*][2].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-family [2]: https://drafts.csswg.org/css-fonts-4/#valdef-font-family-system-ui" + }, + "fontSize": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font size][1] in pixels; either a constant or a channel; defaults to the plot’s font size, which is typically 10. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-size" + }, + "fontStyle": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font style][1]; a constant; defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-style" + }, + "fontVariant": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font variant][1]; a constant; if the **text** channel contains numbers or dates, defaults to *tabular-nums* to facilitate comparing numbers; otherwise defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant" + }, + "fontWeight": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font weight][1]; a constant; defaults to the plot’s font weight, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight" + }, + "format": { + "additionalProperties": false, + "description": "How channel values are formatted for display. If a format is a string, it is interpreted as a (UTC) time format for temporal channels, and otherwise a number format.", + "properties": { + "ariaLabel": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fill": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fillOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fontSize": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fx": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fy": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "geometry": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "height": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "href": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "length": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "opacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "path": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "r": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "rotate": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "src": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "stroke": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeWidth": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "symbol": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "text": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "title": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "weight": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "width": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "z": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + } + }, + "type": "object" + }, + "frameAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The frame anchor specifies defaults for **x** and **y** based on the plot’s frame; it may be one of the four sides (*top*, *right*, *bottom*, *left*), one of the four corners (*top-left*, *top-right*, *bottom-right*,\n*bottom-left*), or the *middle* of the frame. For example, for tips distributed horizontally at the top of the frame:\n\n```js Plot.tip(data, {x: \"date\", frameAnchor: \"top\"}) ```" + }, + "lineHeight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line height in ems; defaults to 1. The line height affects the (typically vertical) separation between adjacent baselines of text, as well as the separation between the text and its anchor point." + }, + "lineWidth": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line width in ems (e.g., 10 for about 20 characters); defaults to infinity, disabling wrapping and clipping.\n\nIf **textOverflow** is null, lines will be wrapped at the specified length. If a line is split at a soft hyphen (\\xad), a hyphen (-) will be displayed at the end of the line. If **textOverflow** is not null, lines will be clipped according to the given strategy." + }, + "monospace": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, changes the default **fontFamily** to *monospace*, and uses simplified monospaced text metrics calculations." + }, + "pathFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The image filter for the tip’s box; defaults to a drop shadow." + }, + "pointer": { + "$ref": "#/definitions/TipPointer" + }, + "pointerSize": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The size of the tip’s pointer in pixels; defaults to 12." + }, + "preferredAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If an explicit tip anchor is not specified, an anchor is chosen automatically such that the tip fits within the plot’s frame; if the preferred anchor fits, it is chosen." + }, + "textAnchor": { + "anyOf": [ + { + "const": "start", + "type": "string" + }, + { + "const": "middle", + "type": "string" + }, + { + "const": "end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [text anchor][1] controls how text is aligned (typically horizontally) relative to its anchor point; it is one of *start*, *end*, or *middle*. If the frame anchor is *left*, *top-left*, or *bottom-left*, the default text anchor is *start*; if the frame anchor is *right*, *top-right*, or\n*bottom-right*, the default is *end*; otherwise it is *middle*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/text-anchor" + }, + "textOverflow": { + "anyOf": [ + { + "type": "null" + }, + { + "const": "clip", + "type": "string" + }, + { + "const": "ellipsis", + "type": "string" + }, + { + "const": "clip-start", + "type": "string" + }, + { + "const": "clip-end", + "type": "string" + }, + { + "const": "ellipsis-start", + "type": "string" + }, + { + "const": "ellipsis-middle", + "type": "string" + }, + { + "const": "ellipsis-end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How truncate (or wrap) lines of text longer than the given **lineWidth**; one of:\n\n- null (default) - preserve overflowing characters (and wrap if needed)\n- *clip* or *clip-end* - remove characters from the end\n- *clip-start* - remove characters from the start\n- *ellipsis* or *ellipsis-end* - replace characters from the end with an ellipsis (…)\n- *ellipsis-start* - replace characters from the start with an ellipsis (…)\n- *ellipsis-middle* - replace characters from the middle with an ellipsis (…)\n\nIf no **title** was specified, if text requires truncation, a title containing the non-truncated text will be implicitly added." + }, + "textPadding": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The padding around the text in pixels; defaults to 8." + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + } + }, + "type": "object" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to generate a tooltip for this mark, and any tip options." + }, + "title": { + "$ref": "#/definitions/ChannelValue", + "description": "The title; a channel specifying accessible, short textual descriptions as strings (possibly with newlines). If the tip option is specified, the title will be displayed with an interactive tooltip instead of using the SVG [title element][1].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/title" + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel specifying the text’s anchor point, typically bound to the *x* scale." + }, + "y": { + "$ref": "#/definitions/ChannelValueIntervalSpec", + "description": "The vertical position of the text’s anchor point, typically bound to the\n*y* scale." + }, + "z": { + "$ref": "#/definitions/ChannelValue", + "description": "An optional ordinal channel for grouping data into series." + } + }, + "required": [ + "mark" + ], + "type": "object" + }, + "TextY": { + "additionalProperties": false, + "description": "The textY mark.", + "properties": { + "ariaDescription": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-description][1]; a constant textual description.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-description" + }, + "ariaHidden": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-hidden][1] state; a constant indicating whether the element is exposed to an accessibility API.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-hidden" + }, + "ariaLabel": { + "$ref": "#/definitions/ChannelValue", + "description": "The [aria-label][1]; a channel specifying short textual labels representing the value in the accessibility tree.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-label" + }, + "clip": { + "anyOf": [ + { + "const": "frame", + "type": "string" + }, + { + "const": "sphere", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to clip the mark; one of:\n\n- *frame* or true - clip to the plot’s frame (inner area)\n- *sphere* - clip to the projected sphere (*e.g.*, front hemisphere)\n- null or false - do not clip\n\nThe *sphere* clip option requires a geographic projection." + }, + "data": { + "$ref": "#/definitions/PlotMarkData", + "description": "The data source for the mark." + }, + "dx": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The horizontal offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "dy": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The vertical offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "facet": { + "anyOf": [ + { + "const": "auto", + "type": "string" + }, + { + "const": "include", + "type": "string" + }, + { + "const": "exclude", + "type": "string" + }, + { + "const": "super", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to enable or disable faceting; one of:\n\n- *auto* (default) - automatically determine if this mark should be faceted\n- *include* (or true) - draw the subset of the mark’s data in the current facet\n- *exclude* - draw the subset of the mark’s data *not* in the current facet\n- *super* - draw this mark in a single frame that covers all facets\n- null (or false) - repeat this mark’s data across all facets (*i.e.*, no faceting)\n\nWhen a mark uses *super* faceting, it is not allowed to use position scales (*x*, *y*, *fx*, or *fy*); *super* faceting is intended for decorations, such as labels and legends.\n\nWhen top-level faceting is used, the default *auto* setting is equivalent to *include* when the mark data is strictly equal to the top-level facet data; otherwise it is equivalent to null. When the *include* or *exclude* facet mode is chosen, the mark data must be parallel to the top-level facet data: the data must have the same length and order. If the data are not parallel, then the wrong data may be shown in each facet. The default\n*auto* therefore requires strict equality (`===`) for safety, and using the facet data as mark data is recommended when using the *exclude* facet mode. (To construct parallel data safely, consider using [*array*.map][1] on the facet data.)\n\nWhen mark-level faceting is used, the default *auto* setting is equivalent to *include*: the mark will be faceted if either the **fx** or **fy** channel option (or both) is specified. The null or false option will disable faceting, while *exclude* draws the subset of the mark’s data *not* in the current facet.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map" + }, + "facetAnchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "right", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "const": "left", + "type": "string" + }, + { + "const": "top-left", + "type": "string" + }, + { + "const": "top-right", + "type": "string" + }, + { + "const": "bottom-left", + "type": "string" + }, + { + "const": "bottom-right", + "type": "string" + }, + { + "const": "top-empty", + "type": "string" + }, + { + "const": "right-empty", + "type": "string" + }, + { + "const": "bottom-empty", + "type": "string" + }, + { + "const": "left-empty", + "type": "string" + }, + { + "const": "empty", + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to place the mark with respect to facets; one of:\n\n- null (default for most marks) - display the mark in each non-empty facet\n- *top*, *right*, *bottom*, or *left* - display the mark only in facets on the given side\n- *top-empty*, *right-empty*, *bottom-empty*, or *left-empty* (default for axis marks) - display the mark only in facets that have empty space on the given side: either the margin, or an empty facet\n- *empty* - display the mark in empty facets only" + }, + "fill": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill" + }, + "fillOpacity": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill-opacity][1]; a constant number between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill-opacity" + }, + "filter": { + "$ref": "#/definitions/ChannelValue", + "description": "Applies a transform to filter the mark’s index according to the given channel values; only truthy values are retained.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "fontFamily": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font-family][1]; a constant; defaults to the plot’s font family, which is typically [*system-ui*][2].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-family [2]: https://drafts.csswg.org/css-fonts-4/#valdef-font-family-system-ui" + }, + "fontSize": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font size][1] in pixels; either a constant or a channel; defaults to the plot’s font size, which is typically 10. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-size" + }, + "fontStyle": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font style][1]; a constant; defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-style" + }, + "fontVariant": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font variant][1]; a constant; if the **text** channel contains numbers or dates, defaults to *tabular-nums* to facilitate comparing numbers; otherwise defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant" + }, + "fontWeight": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font weight][1]; a constant; defaults to the plot’s font weight, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight" + }, + "frameAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The frame anchor specifies defaults for **x** and **y**, along with\n**textAnchor** and **lineAnchor**, based on the plot’s frame; it may be one of the four sides (*top*, *right*, *bottom*, *left*), one of the four corners (*top-left*, *top-right*, *bottom-right*, *bottom-left*), or the\n*middle* of the frame." + }, + "fx": { + "$ref": "#/definitions/ChannelValue", + "description": "The horizontal facet position channel, for mark-level faceting, bound to the *fx* scale." + }, + "fy": { + "$ref": "#/definitions/ChannelValue", + "description": "The vertical facet position channel, for mark-level faceting, bound to the\n*fy* scale." + }, + "href": { + "$ref": "#/definitions/ChannelValue", + "description": "The [href][1]; a channel specifying URLs for clickable links. May be used in conjunction with the **target** option to open links in another window.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/href" + }, + "imageFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A CSS [filter][1]; a constant string used to adjust the rendering of images, such as *blur(5px)*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/filter" + }, + "interval": { + "$ref": "#/definitions/Interval", + "description": "An interval (such as *day* or a number), to transform **x** values to the middle of the interval." + }, + "lineAnchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "middle", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line anchor controls how text is aligned (typically vertically) relative to its anchor point; it is one of *top*, *bottom*, or *middle*. If the frame anchor is *top*, *top-left*, or *top-right*, the default line anchor is *top*; if the frame anchor is *bottom*, *bottom-right*, or\n*bottom-left*, the default is *bottom*; otherwise it is *middle*." + }, + "lineHeight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line height in ems; defaults to 1. The line height affects the (typically vertical) separation between adjacent baselines of text, as well as the separation between the text and its anchor point." + }, + "lineWidth": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line width in ems (e.g., 10 for about 20 characters); defaults to infinity, disabling wrapping and clipping.\n\nIf **textOverflow** is null, lines will be wrapped at the specified length. If a line is split at a soft hyphen (\\xad), a hyphen (-) will be displayed at the end of the line. If **textOverflow** is not null, lines will be clipped according to the given strategy." + }, + "margin": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four mark margins: **marginTop**,\n**marginRight**, **marginBottom**, and **marginLeft**; typically defaults to 0, except for axis marks." + }, + "marginBottom": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s bottom margin; the minimum distance in pixels between the bottom edges of the inner and outer plot area." + }, + "marginLeft": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s left margin; the minimum distance in pixels between the left edges of the inner and outer plot area." + }, + "marginRight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s right margin; the minimum distance in pixels between the right edges of the mark’s inner and outer plot area." + }, + "marginTop": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s top margin; the minimum distance in pixels between the top edges of the inner and outer plot area." + }, + "mark": { + "const": "textY", + "description": "Like text, but **y** defaults to the identity function, assuming that\n*data* = [*y₀*, *y₁*, *y₂*, …]. If an **interval** is specified, such as\n*day*, **x** is transformed to the middle of the interval.", + "type": "string" + }, + "mixBlendMode": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [mix-blend-mode][1]; a constant string specifying how to blend content such as *multiply*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode" + }, + "monospace": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, changes the default **fontFamily** to *monospace*, and uses simplified monospaced text metrics calculations." + }, + "opacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally. For faster rendering, prefer the **strokeOpacity** or **fillOpacity** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/opacity" + }, + "paintOrder": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [paint-order][1]; a constant string specifying the order in which the\n**fill**, **stroke**, and any markers are drawn; defaults to *normal*, which draws the fill, then stroke, then markers; defaults to *stroke* for the text mark to create a “halo” around text to improve legibility.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/paint-order" + }, + "pointerEvents": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [pointer-events][1] property; a constant string such as *none*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/pointer-events" + }, + "reverse": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Applies a transform to reverse the order of the mark’s index, say for reverse input order." + }, + "rotate": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The rotation angle in degrees clockwise; a constant or a channel; defaults to 0°. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel." + }, + "select": { + "$ref": "#/definitions/SelectFilter", + "description": "Applies a filter transform after data is loaded to highlight selected values only. For example, `first` and `last` select the first or last values of series only (using the *z* channel to separate series). Meanwhile, `nearestX` and `nearestY` select the point nearest to the pointer along the *x* or *y* channel dimension. Unlike Mosaic selections, a mark level *select* is internal to the mark only, and does not populate a param or selection value to be shared across clients.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "shapeRendering": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [shape-rendering][1]; a constant string such as *crispEdges*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/shape-rendering" + }, + "sort": { + "anyOf": [ + { + "$ref": "#/definitions/SortOrder" + }, + { + "$ref": "#/definitions/ChannelDomainSort" + } + ], + "description": "Either applies a transform to sort the mark’s index by the specified channel values, or imputes ordinal scale domains from this mark’s channels.\n\nWhen imputing ordinal scale domains from channel values, the **sort** option is an object whose keys are ordinal scale names such as *x* or *fx*, and whose values are channel names such as *y*, *y1*, or *y2*. For example, to impute the *y* scale’s domain from the associated *x* channel values in ascending order:\n\n```js sort: {y: \"x\"} ```\n\nFor different sort options for different scales, replace the channel name with a *value* object and per-scale options:\n\n```js sort: {y: {value: \"-x\"}} ```\n\nWhen sorting the mark’s index, the **sort** option is instead one of:\n\n- a channel value definition for sorting given values in ascending order\n- a {value, order} object for sorting given values\n- a {channel, order} object for sorting the named channel’s values" + }, + "stroke": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke" + }, + "strokeDasharray": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dasharray][1]; a constant number indicating the length in pixels of alternating dashes and gaps, or a constant string of numbers separated by spaces or commas (_e.g._, *10 2* for dashes of 10 pixels separated by gaps of 2 pixels), or *none* (the default) for no dashing\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dasharray" + }, + "strokeDashoffset": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dashoffset][1]; a constant indicating the offset in pixels of the first dash along the stroke; defaults to zero.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dashoffset" + }, + "strokeLinecap": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linecap][1]; a constant specifying how to cap stroked paths, such as *butt*, *round*, or *square*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linecap" + }, + "strokeLinejoin": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linejoin][1]; a constant specifying how to join stroked paths, such as *bevel*, *miter*, *miter-clip*, or *round*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linejoin" + }, + "strokeMiterlimit": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-miterlimit][1]; a constant number specifying how to limit the length of *miter* joins on stroked paths.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-miterlimit" + }, + "strokeOpacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-opacity" + }, + "strokeWidth": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-width][1]; a constant number in pixels, or a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-width" + }, + "target": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [target][1]; a constant string specifying the target window (_e.g._,\n*_blank*) for clickable links; used in conjunction with the **href** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/target" + }, + "text": { + "$ref": "#/definitions/ChannelValue", + "description": "The text contents channel, possibly with line breaks (\\n, \\r\\n, or \\r). If not specified, defaults to the zero-based index [0, 1, 2, …]." + }, + "textAnchor": { + "anyOf": [ + { + "const": "start", + "type": "string" + }, + { + "const": "middle", + "type": "string" + }, + { + "const": "end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [text anchor][1] controls how text is aligned (typically horizontally) relative to its anchor point; it is one of *start*, *end*, or *middle*. If the frame anchor is *left*, *top-left*, or *bottom-left*, the default text anchor is *start*; if the frame anchor is *right*, *top-right*, or\n*bottom-right*, the default is *end*; otherwise it is *middle*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/text-anchor" + }, + "textOverflow": { + "anyOf": [ + { + "type": "null" + }, + { + "const": "clip", + "type": "string" + }, + { + "const": "ellipsis", + "type": "string" + }, + { + "const": "clip-start", + "type": "string" + }, + { + "const": "clip-end", + "type": "string" + }, + { + "const": "ellipsis-start", + "type": "string" + }, + { + "const": "ellipsis-middle", + "type": "string" + }, + { + "const": "ellipsis-end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How truncate (or wrap) lines of text longer than the given **lineWidth**; one of:\n\n- null (default) - preserve overflowing characters (and wrap if needed)\n- *clip* or *clip-end* - remove characters from the end\n- *clip-start* - remove characters from the start\n- *ellipsis* or *ellipsis-end* - replace characters from the end with an ellipsis (…)\n- *ellipsis-start* - replace characters from the start with an ellipsis (…)\n- *ellipsis-middle* - replace characters from the middle with an ellipsis (…)\n\nIf no **title** was specified, if text requires truncation, a title containing the non-truncated text will be implicitly added." + }, + "tip": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/TipPointer" + }, + { + "properties": { + "anchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The tip anchor specifies how to orient the tip box relative to its anchor position; it refers to the part of the tip box that is attached to the anchor point. For example, the *top-left* anchor places the top-left corner of tip box near the anchor position, hence placing the tip box below and to the right of the anchor position." + }, + "fontFamily": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font-family][1]; a constant; defaults to the plot’s font family, which is typically [*system-ui*][2].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-family [2]: https://drafts.csswg.org/css-fonts-4/#valdef-font-family-system-ui" + }, + "fontSize": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font size][1] in pixels; either a constant or a channel; defaults to the plot’s font size, which is typically 10. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-size" + }, + "fontStyle": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font style][1]; a constant; defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-style" + }, + "fontVariant": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font variant][1]; a constant; if the **text** channel contains numbers or dates, defaults to *tabular-nums* to facilitate comparing numbers; otherwise defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant" + }, + "fontWeight": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font weight][1]; a constant; defaults to the plot’s font weight, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight" + }, + "format": { + "additionalProperties": false, + "description": "How channel values are formatted for display. If a format is a string, it is interpreted as a (UTC) time format for temporal channels, and otherwise a number format.", + "properties": { + "ariaLabel": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fill": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fillOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fontSize": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fx": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fy": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "geometry": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "height": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "href": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "length": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "opacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "path": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "r": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "rotate": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "src": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "stroke": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeWidth": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "symbol": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "text": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "title": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "weight": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "width": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "z": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + } + }, + "type": "object" + }, + "frameAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The frame anchor specifies defaults for **x** and **y** based on the plot’s frame; it may be one of the four sides (*top*, *right*, *bottom*, *left*), one of the four corners (*top-left*, *top-right*, *bottom-right*,\n*bottom-left*), or the *middle* of the frame. For example, for tips distributed horizontally at the top of the frame:\n\n```js Plot.tip(data, {x: \"date\", frameAnchor: \"top\"}) ```" + }, + "lineHeight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line height in ems; defaults to 1. The line height affects the (typically vertical) separation between adjacent baselines of text, as well as the separation between the text and its anchor point." + }, + "lineWidth": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line width in ems (e.g., 10 for about 20 characters); defaults to infinity, disabling wrapping and clipping.\n\nIf **textOverflow** is null, lines will be wrapped at the specified length. If a line is split at a soft hyphen (\\xad), a hyphen (-) will be displayed at the end of the line. If **textOverflow** is not null, lines will be clipped according to the given strategy." + }, + "monospace": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, changes the default **fontFamily** to *monospace*, and uses simplified monospaced text metrics calculations." + }, + "pathFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The image filter for the tip’s box; defaults to a drop shadow." + }, + "pointer": { + "$ref": "#/definitions/TipPointer" + }, + "pointerSize": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The size of the tip’s pointer in pixels; defaults to 12." + }, + "preferredAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If an explicit tip anchor is not specified, an anchor is chosen automatically such that the tip fits within the plot’s frame; if the preferred anchor fits, it is chosen." + }, + "textAnchor": { + "anyOf": [ + { + "const": "start", + "type": "string" + }, + { + "const": "middle", + "type": "string" + }, + { + "const": "end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [text anchor][1] controls how text is aligned (typically horizontally) relative to its anchor point; it is one of *start*, *end*, or *middle*. If the frame anchor is *left*, *top-left*, or *bottom-left*, the default text anchor is *start*; if the frame anchor is *right*, *top-right*, or\n*bottom-right*, the default is *end*; otherwise it is *middle*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/text-anchor" + }, + "textOverflow": { + "anyOf": [ + { + "type": "null" + }, + { + "const": "clip", + "type": "string" + }, + { + "const": "ellipsis", + "type": "string" + }, + { + "const": "clip-start", + "type": "string" + }, + { + "const": "clip-end", + "type": "string" + }, + { + "const": "ellipsis-start", + "type": "string" + }, + { + "const": "ellipsis-middle", + "type": "string" + }, + { + "const": "ellipsis-end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How truncate (or wrap) lines of text longer than the given **lineWidth**; one of:\n\n- null (default) - preserve overflowing characters (and wrap if needed)\n- *clip* or *clip-end* - remove characters from the end\n- *clip-start* - remove characters from the start\n- *ellipsis* or *ellipsis-end* - replace characters from the end with an ellipsis (…)\n- *ellipsis-start* - replace characters from the start with an ellipsis (…)\n- *ellipsis-middle* - replace characters from the middle with an ellipsis (…)\n\nIf no **title** was specified, if text requires truncation, a title containing the non-truncated text will be implicitly added." + }, + "textPadding": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The padding around the text in pixels; defaults to 8." + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + } + }, + "type": "object" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to generate a tooltip for this mark, and any tip options." + }, + "title": { + "$ref": "#/definitions/ChannelValue", + "description": "The title; a channel specifying accessible, short textual descriptions as strings (possibly with newlines). If the tip option is specified, the title will be displayed with an interactive tooltip instead of using the SVG [title element][1].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/title" + }, + "x": { + "$ref": "#/definitions/ChannelValueIntervalSpec", + "description": "The horizontal position of the text’s anchor point, typically bound to the\n*x* scale." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel specifying the text’s anchor point, typically bound to the *y* scale." + }, + "z": { + "$ref": "#/definitions/ChannelValue", + "description": "An optional ordinal channel for grouping data into series." + } + }, + "required": [ + "mark" + ], + "type": "object" + }, + "TickX": { + "additionalProperties": false, + "description": "The tickX mark.", + "properties": { + "ariaDescription": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-description][1]; a constant textual description.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-description" + }, + "ariaHidden": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-hidden][1] state; a constant indicating whether the element is exposed to an accessibility API.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-hidden" + }, + "ariaLabel": { + "$ref": "#/definitions/ChannelValue", + "description": "The [aria-label][1]; a channel specifying short textual labels representing the value in the accessibility tree.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-label" + }, + "clip": { + "anyOf": [ + { + "const": "frame", + "type": "string" + }, + { + "const": "sphere", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to clip the mark; one of:\n\n- *frame* or true - clip to the plot’s frame (inner area)\n- *sphere* - clip to the projected sphere (*e.g.*, front hemisphere)\n- null or false - do not clip\n\nThe *sphere* clip option requires a geographic projection." + }, + "data": { + "$ref": "#/definitions/PlotMarkData", + "description": "The data source for the mark." + }, + "dx": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The horizontal offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "dy": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The vertical offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "facet": { + "anyOf": [ + { + "const": "auto", + "type": "string" + }, + { + "const": "include", + "type": "string" + }, + { + "const": "exclude", + "type": "string" + }, + { + "const": "super", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to enable or disable faceting; one of:\n\n- *auto* (default) - automatically determine if this mark should be faceted\n- *include* (or true) - draw the subset of the mark’s data in the current facet\n- *exclude* - draw the subset of the mark’s data *not* in the current facet\n- *super* - draw this mark in a single frame that covers all facets\n- null (or false) - repeat this mark’s data across all facets (*i.e.*, no faceting)\n\nWhen a mark uses *super* faceting, it is not allowed to use position scales (*x*, *y*, *fx*, or *fy*); *super* faceting is intended for decorations, such as labels and legends.\n\nWhen top-level faceting is used, the default *auto* setting is equivalent to *include* when the mark data is strictly equal to the top-level facet data; otherwise it is equivalent to null. When the *include* or *exclude* facet mode is chosen, the mark data must be parallel to the top-level facet data: the data must have the same length and order. If the data are not parallel, then the wrong data may be shown in each facet. The default\n*auto* therefore requires strict equality (`===`) for safety, and using the facet data as mark data is recommended when using the *exclude* facet mode. (To construct parallel data safely, consider using [*array*.map][1] on the facet data.)\n\nWhen mark-level faceting is used, the default *auto* setting is equivalent to *include*: the mark will be faceted if either the **fx** or **fy** channel option (or both) is specified. The null or false option will disable faceting, while *exclude* draws the subset of the mark’s data *not* in the current facet.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map" + }, + "facetAnchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "right", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "const": "left", + "type": "string" + }, + { + "const": "top-left", + "type": "string" + }, + { + "const": "top-right", + "type": "string" + }, + { + "const": "bottom-left", + "type": "string" + }, + { + "const": "bottom-right", + "type": "string" + }, + { + "const": "top-empty", + "type": "string" + }, + { + "const": "right-empty", + "type": "string" + }, + { + "const": "bottom-empty", + "type": "string" + }, + { + "const": "left-empty", + "type": "string" + }, + { + "const": "empty", + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to place the mark with respect to facets; one of:\n\n- null (default for most marks) - display the mark in each non-empty facet\n- *top*, *right*, *bottom*, or *left* - display the mark only in facets on the given side\n- *top-empty*, *right-empty*, *bottom-empty*, or *left-empty* (default for axis marks) - display the mark only in facets that have empty space on the given side: either the margin, or an empty facet\n- *empty* - display the mark in empty facets only" + }, + "fill": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill" + }, + "fillOpacity": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill-opacity][1]; a constant number between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill-opacity" + }, + "filter": { + "$ref": "#/definitions/ChannelValue", + "description": "Applies a transform to filter the mark’s index according to the given channel values; only truthy values are retained.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "fx": { + "$ref": "#/definitions/ChannelValue", + "description": "The horizontal facet position channel, for mark-level faceting, bound to the *fx* scale." + }, + "fy": { + "$ref": "#/definitions/ChannelValue", + "description": "The vertical facet position channel, for mark-level faceting, bound to the\n*fy* scale." + }, + "href": { + "$ref": "#/definitions/ChannelValue", + "description": "The [href][1]; a channel specifying URLs for clickable links. May be used in conjunction with the **target** option to open links in another window.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/href" + }, + "imageFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A CSS [filter][1]; a constant string used to adjust the rendering of images, such as *blur(5px)*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/filter" + }, + "inset": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four insets: **insetTop**,\n**insetRight**, **insetBottom**, and **insetLeft**. All insets typically default to zero, though not always (say when using bin transform). A positive inset reduces effective area, while a negative inset increases it." + }, + "insetBottom": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Insets the bottom edge by the specified number of pixels. A positive value insets towards the top edge (reducing effective area), while a negative value insets away from the top edge (increasing it)." + }, + "insetTop": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Insets the top edge by the specified number of pixels. A positive value insets towards the bottom edge (reducing effective area), while a negative value insets away from the bottom edge (increasing it)." + }, + "margin": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four mark margins: **marginTop**,\n**marginRight**, **marginBottom**, and **marginLeft**; typically defaults to 0, except for axis marks." + }, + "marginBottom": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s bottom margin; the minimum distance in pixels between the bottom edges of the inner and outer plot area." + }, + "marginLeft": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s left margin; the minimum distance in pixels between the left edges of the inner and outer plot area." + }, + "marginRight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s right margin; the minimum distance in pixels between the right edges of the mark’s inner and outer plot area." + }, + "marginTop": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s top margin; the minimum distance in pixels between the top edges of the inner and outer plot area." + }, + "mark": { + "const": "tickX", + "description": "A horizontally-positioned tickX mark (a vertical line, |). The **x** channel specifies the tick’s horizontal position and defaults to identity, assuming that *data* = [*x₀*, *x₁*, *x₂*, …]; the optional **y** ordinal channel specifies its vertical position.\n\nIf *y* represents quantitative or temporal values, use a ruleX mark instead.", + "type": "string" + }, + "marker": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for markerStart, markerMid, and markerEnd; one of:\n\n- a marker name such as *arrow* or *circle*\n- *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*" + }, + "markerEnd": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The marker for the ending point of a line segment; one of:\n\n- a marker name such as *arrow* or *circle*\n* *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*" + }, + "markerMid": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The marker for any middle (interior) points of a line segment. If the line segment only has a start and end point, this option has no effect. One of:\n\n- a marker name such as *arrow* or *circle*\n* *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*\n* a function - a custom marker function; see below" + }, + "markerStart": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The marker for the starting point of a line segment; one of:\n\n- a marker name such as *arrow* or *circle*\n* *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*" + }, + "mixBlendMode": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [mix-blend-mode][1]; a constant string specifying how to blend content such as *multiply*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode" + }, + "opacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally. For faster rendering, prefer the **strokeOpacity** or **fillOpacity** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/opacity" + }, + "paintOrder": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [paint-order][1]; a constant string specifying the order in which the\n**fill**, **stroke**, and any markers are drawn; defaults to *normal*, which draws the fill, then stroke, then markers; defaults to *stroke* for the text mark to create a “halo” around text to improve legibility.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/paint-order" + }, + "pointerEvents": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [pointer-events][1] property; a constant string such as *none*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/pointer-events" + }, + "reverse": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Applies a transform to reverse the order of the mark’s index, say for reverse input order." + }, + "select": { + "$ref": "#/definitions/SelectFilter", + "description": "Applies a filter transform after data is loaded to highlight selected values only. For example, `first` and `last` select the first or last values of series only (using the *z* channel to separate series). Meanwhile, `nearestX` and `nearestY` select the point nearest to the pointer along the *x* or *y* channel dimension. Unlike Mosaic selections, a mark level *select* is internal to the mark only, and does not populate a param or selection value to be shared across clients.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "shapeRendering": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [shape-rendering][1]; a constant string such as *crispEdges*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/shape-rendering" + }, + "sort": { + "anyOf": [ + { + "$ref": "#/definitions/SortOrder" + }, + { + "$ref": "#/definitions/ChannelDomainSort" + } + ], + "description": "Either applies a transform to sort the mark’s index by the specified channel values, or imputes ordinal scale domains from this mark’s channels.\n\nWhen imputing ordinal scale domains from channel values, the **sort** option is an object whose keys are ordinal scale names such as *x* or *fx*, and whose values are channel names such as *y*, *y1*, or *y2*. For example, to impute the *y* scale’s domain from the associated *x* channel values in ascending order:\n\n```js sort: {y: \"x\"} ```\n\nFor different sort options for different scales, replace the channel name with a *value* object and per-scale options:\n\n```js sort: {y: {value: \"-x\"}} ```\n\nWhen sorting the mark’s index, the **sort** option is instead one of:\n\n- a channel value definition for sorting given values in ascending order\n- a {value, order} object for sorting given values\n- a {channel, order} object for sorting the named channel’s values" + }, + "stroke": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke" + }, + "strokeDasharray": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dasharray][1]; a constant number indicating the length in pixels of alternating dashes and gaps, or a constant string of numbers separated by spaces or commas (_e.g._, *10 2* for dashes of 10 pixels separated by gaps of 2 pixels), or *none* (the default) for no dashing\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dasharray" + }, + "strokeDashoffset": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dashoffset][1]; a constant indicating the offset in pixels of the first dash along the stroke; defaults to zero.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dashoffset" + }, + "strokeLinecap": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linecap][1]; a constant specifying how to cap stroked paths, such as *butt*, *round*, or *square*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linecap" + }, + "strokeLinejoin": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linejoin][1]; a constant specifying how to join stroked paths, such as *bevel*, *miter*, *miter-clip*, or *round*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linejoin" + }, + "strokeMiterlimit": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-miterlimit][1]; a constant number specifying how to limit the length of *miter* joins on stroked paths.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-miterlimit" + }, + "strokeOpacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-opacity" + }, + "strokeWidth": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-width][1]; a constant number in pixels, or a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-width" + }, + "target": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [target][1]; a constant string specifying the target window (_e.g._,\n*_blank*) for clickable links; used in conjunction with the **href** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/target" + }, + "tip": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/TipPointer" + }, + { + "properties": { + "anchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The tip anchor specifies how to orient the tip box relative to its anchor position; it refers to the part of the tip box that is attached to the anchor point. For example, the *top-left* anchor places the top-left corner of tip box near the anchor position, hence placing the tip box below and to the right of the anchor position." + }, + "fontFamily": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font-family][1]; a constant; defaults to the plot’s font family, which is typically [*system-ui*][2].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-family [2]: https://drafts.csswg.org/css-fonts-4/#valdef-font-family-system-ui" + }, + "fontSize": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font size][1] in pixels; either a constant or a channel; defaults to the plot’s font size, which is typically 10. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-size" + }, + "fontStyle": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font style][1]; a constant; defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-style" + }, + "fontVariant": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font variant][1]; a constant; if the **text** channel contains numbers or dates, defaults to *tabular-nums* to facilitate comparing numbers; otherwise defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant" + }, + "fontWeight": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font weight][1]; a constant; defaults to the plot’s font weight, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight" + }, + "format": { + "additionalProperties": false, + "description": "How channel values are formatted for display. If a format is a string, it is interpreted as a (UTC) time format for temporal channels, and otherwise a number format.", + "properties": { + "ariaLabel": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fill": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fillOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fontSize": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fx": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fy": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "geometry": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "height": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "href": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "length": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "opacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "path": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "r": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "rotate": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "src": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "stroke": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeWidth": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "symbol": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "text": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "title": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "weight": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "width": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "z": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + } + }, + "type": "object" + }, + "frameAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The frame anchor specifies defaults for **x** and **y** based on the plot’s frame; it may be one of the four sides (*top*, *right*, *bottom*, *left*), one of the four corners (*top-left*, *top-right*, *bottom-right*,\n*bottom-left*), or the *middle* of the frame. For example, for tips distributed horizontally at the top of the frame:\n\n```js Plot.tip(data, {x: \"date\", frameAnchor: \"top\"}) ```" + }, + "lineHeight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line height in ems; defaults to 1. The line height affects the (typically vertical) separation between adjacent baselines of text, as well as the separation between the text and its anchor point." + }, + "lineWidth": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line width in ems (e.g., 10 for about 20 characters); defaults to infinity, disabling wrapping and clipping.\n\nIf **textOverflow** is null, lines will be wrapped at the specified length. If a line is split at a soft hyphen (\\xad), a hyphen (-) will be displayed at the end of the line. If **textOverflow** is not null, lines will be clipped according to the given strategy." + }, + "monospace": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, changes the default **fontFamily** to *monospace*, and uses simplified monospaced text metrics calculations." + }, + "pathFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The image filter for the tip’s box; defaults to a drop shadow." + }, + "pointer": { + "$ref": "#/definitions/TipPointer" + }, + "pointerSize": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The size of the tip’s pointer in pixels; defaults to 12." + }, + "preferredAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If an explicit tip anchor is not specified, an anchor is chosen automatically such that the tip fits within the plot’s frame; if the preferred anchor fits, it is chosen." + }, + "textAnchor": { + "anyOf": [ + { + "const": "start", + "type": "string" + }, + { + "const": "middle", + "type": "string" + }, + { + "const": "end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [text anchor][1] controls how text is aligned (typically horizontally) relative to its anchor point; it is one of *start*, *end*, or *middle*. If the frame anchor is *left*, *top-left*, or *bottom-left*, the default text anchor is *start*; if the frame anchor is *right*, *top-right*, or\n*bottom-right*, the default is *end*; otherwise it is *middle*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/text-anchor" + }, + "textOverflow": { + "anyOf": [ + { + "type": "null" + }, + { + "const": "clip", + "type": "string" + }, + { + "const": "ellipsis", + "type": "string" + }, + { + "const": "clip-start", + "type": "string" + }, + { + "const": "clip-end", + "type": "string" + }, + { + "const": "ellipsis-start", + "type": "string" + }, + { + "const": "ellipsis-middle", + "type": "string" + }, + { + "const": "ellipsis-end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How truncate (or wrap) lines of text longer than the given **lineWidth**; one of:\n\n- null (default) - preserve overflowing characters (and wrap if needed)\n- *clip* or *clip-end* - remove characters from the end\n- *clip-start* - remove characters from the start\n- *ellipsis* or *ellipsis-end* - replace characters from the end with an ellipsis (…)\n- *ellipsis-start* - replace characters from the start with an ellipsis (…)\n- *ellipsis-middle* - replace characters from the middle with an ellipsis (…)\n\nIf no **title** was specified, if text requires truncation, a title containing the non-truncated text will be implicitly added." + }, + "textPadding": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The padding around the text in pixels; defaults to 8." + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + } + }, + "type": "object" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to generate a tooltip for this mark, and any tip options." + }, + "title": { + "$ref": "#/definitions/ChannelValue", + "description": "The title; a channel specifying accessible, short textual descriptions as strings (possibly with newlines). If the tip option is specified, the title will be displayed with an interactive tooltip instead of using the SVG [title element][1].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/title" + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The required horizontal position of the tick; a channel typically bound to the *x* scale." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The optional vertical position of the tick; an ordinal channel typically bound to the *y* scale. If not specified, the tick spans the vertical extent of the frame; otherwise the *y* scale must be a *band* scale.\n\nIf *y* represents quantitative or temporal values, use a ruleX mark instead." + } + }, + "required": [ + "data", + "mark" + ], + "type": "object" + }, + "TickY": { + "additionalProperties": false, + "description": "The tickY mark.", + "properties": { + "ariaDescription": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-description][1]; a constant textual description.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-description" + }, + "ariaHidden": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-hidden][1] state; a constant indicating whether the element is exposed to an accessibility API.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-hidden" + }, + "ariaLabel": { + "$ref": "#/definitions/ChannelValue", + "description": "The [aria-label][1]; a channel specifying short textual labels representing the value in the accessibility tree.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-label" + }, + "clip": { + "anyOf": [ + { + "const": "frame", + "type": "string" + }, + { + "const": "sphere", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to clip the mark; one of:\n\n- *frame* or true - clip to the plot’s frame (inner area)\n- *sphere* - clip to the projected sphere (*e.g.*, front hemisphere)\n- null or false - do not clip\n\nThe *sphere* clip option requires a geographic projection." + }, + "data": { + "$ref": "#/definitions/PlotMarkData", + "description": "The data source for the mark." + }, + "dx": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The horizontal offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "dy": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The vertical offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "facet": { + "anyOf": [ + { + "const": "auto", + "type": "string" + }, + { + "const": "include", + "type": "string" + }, + { + "const": "exclude", + "type": "string" + }, + { + "const": "super", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to enable or disable faceting; one of:\n\n- *auto* (default) - automatically determine if this mark should be faceted\n- *include* (or true) - draw the subset of the mark’s data in the current facet\n- *exclude* - draw the subset of the mark’s data *not* in the current facet\n- *super* - draw this mark in a single frame that covers all facets\n- null (or false) - repeat this mark’s data across all facets (*i.e.*, no faceting)\n\nWhen a mark uses *super* faceting, it is not allowed to use position scales (*x*, *y*, *fx*, or *fy*); *super* faceting is intended for decorations, such as labels and legends.\n\nWhen top-level faceting is used, the default *auto* setting is equivalent to *include* when the mark data is strictly equal to the top-level facet data; otherwise it is equivalent to null. When the *include* or *exclude* facet mode is chosen, the mark data must be parallel to the top-level facet data: the data must have the same length and order. If the data are not parallel, then the wrong data may be shown in each facet. The default\n*auto* therefore requires strict equality (`===`) for safety, and using the facet data as mark data is recommended when using the *exclude* facet mode. (To construct parallel data safely, consider using [*array*.map][1] on the facet data.)\n\nWhen mark-level faceting is used, the default *auto* setting is equivalent to *include*: the mark will be faceted if either the **fx** or **fy** channel option (or both) is specified. The null or false option will disable faceting, while *exclude* draws the subset of the mark’s data *not* in the current facet.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map" + }, + "facetAnchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "right", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "const": "left", + "type": "string" + }, + { + "const": "top-left", + "type": "string" + }, + { + "const": "top-right", + "type": "string" + }, + { + "const": "bottom-left", + "type": "string" + }, + { + "const": "bottom-right", + "type": "string" + }, + { + "const": "top-empty", + "type": "string" + }, + { + "const": "right-empty", + "type": "string" + }, + { + "const": "bottom-empty", + "type": "string" + }, + { + "const": "left-empty", + "type": "string" + }, + { + "const": "empty", + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to place the mark with respect to facets; one of:\n\n- null (default for most marks) - display the mark in each non-empty facet\n- *top*, *right*, *bottom*, or *left* - display the mark only in facets on the given side\n- *top-empty*, *right-empty*, *bottom-empty*, or *left-empty* (default for axis marks) - display the mark only in facets that have empty space on the given side: either the margin, or an empty facet\n- *empty* - display the mark in empty facets only" + }, + "fill": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill" + }, + "fillOpacity": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill-opacity][1]; a constant number between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill-opacity" + }, + "filter": { + "$ref": "#/definitions/ChannelValue", + "description": "Applies a transform to filter the mark’s index according to the given channel values; only truthy values are retained.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "fx": { + "$ref": "#/definitions/ChannelValue", + "description": "The horizontal facet position channel, for mark-level faceting, bound to the *fx* scale." + }, + "fy": { + "$ref": "#/definitions/ChannelValue", + "description": "The vertical facet position channel, for mark-level faceting, bound to the\n*fy* scale." + }, + "href": { + "$ref": "#/definitions/ChannelValue", + "description": "The [href][1]; a channel specifying URLs for clickable links. May be used in conjunction with the **target** option to open links in another window.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/href" + }, + "imageFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A CSS [filter][1]; a constant string used to adjust the rendering of images, such as *blur(5px)*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/filter" + }, + "inset": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four insets: **insetTop**,\n**insetRight**, **insetBottom**, and **insetLeft**. All insets typically default to zero, though not always (say when using bin transform). A positive inset reduces effective area, while a negative inset increases it." + }, + "insetLeft": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Insets the left edge by the specified number of pixels. A positive value insets towards the right edge (reducing effective area), while a negative value insets away from the right edge (increasing it)." + }, + "insetRight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Insets the right edge by the specified number of pixels. A positive value insets towards the left edge (reducing effective area), while a negative value insets away from the left edge (increasing it)." + }, + "margin": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four mark margins: **marginTop**,\n**marginRight**, **marginBottom**, and **marginLeft**; typically defaults to 0, except for axis marks." + }, + "marginBottom": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s bottom margin; the minimum distance in pixels between the bottom edges of the inner and outer plot area." + }, + "marginLeft": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s left margin; the minimum distance in pixels between the left edges of the inner and outer plot area." + }, + "marginRight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s right margin; the minimum distance in pixels between the right edges of the mark’s inner and outer plot area." + }, + "marginTop": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s top margin; the minimum distance in pixels between the top edges of the inner and outer plot area." + }, + "mark": { + "const": "tickY", + "description": "A vertically-positioned tickY mark (a horizontal line, —). The **y** channel specifies the tick's vertical position and defaults to identity, assuming that *data* = [*y₀*, *y₁*, *y₂*, …]; the optional **x** ordinal channel specifies its horizontal position.\n\nIf *x* represents quantitative or temporal values, use a ruleY mark instead.", + "type": "string" + }, + "marker": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for markerStart, markerMid, and markerEnd; one of:\n\n- a marker name such as *arrow* or *circle*\n- *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*" + }, + "markerEnd": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The marker for the ending point of a line segment; one of:\n\n- a marker name such as *arrow* or *circle*\n* *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*" + }, + "markerMid": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The marker for any middle (interior) points of a line segment. If the line segment only has a start and end point, this option has no effect. One of:\n\n- a marker name such as *arrow* or *circle*\n* *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*\n* a function - a custom marker function; see below" + }, + "markerStart": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The marker for the starting point of a line segment; one of:\n\n- a marker name such as *arrow* or *circle*\n* *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*" + }, + "mixBlendMode": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [mix-blend-mode][1]; a constant string specifying how to blend content such as *multiply*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode" + }, + "opacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally. For faster rendering, prefer the **strokeOpacity** or **fillOpacity** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/opacity" + }, + "paintOrder": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [paint-order][1]; a constant string specifying the order in which the\n**fill**, **stroke**, and any markers are drawn; defaults to *normal*, which draws the fill, then stroke, then markers; defaults to *stroke* for the text mark to create a “halo” around text to improve legibility.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/paint-order" + }, + "pointerEvents": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [pointer-events][1] property; a constant string such as *none*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/pointer-events" + }, + "reverse": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Applies a transform to reverse the order of the mark’s index, say for reverse input order." + }, + "select": { + "$ref": "#/definitions/SelectFilter", + "description": "Applies a filter transform after data is loaded to highlight selected values only. For example, `first` and `last` select the first or last values of series only (using the *z* channel to separate series). Meanwhile, `nearestX` and `nearestY` select the point nearest to the pointer along the *x* or *y* channel dimension. Unlike Mosaic selections, a mark level *select* is internal to the mark only, and does not populate a param or selection value to be shared across clients.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "shapeRendering": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [shape-rendering][1]; a constant string such as *crispEdges*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/shape-rendering" + }, + "sort": { + "anyOf": [ + { + "$ref": "#/definitions/SortOrder" + }, + { + "$ref": "#/definitions/ChannelDomainSort" + } + ], + "description": "Either applies a transform to sort the mark’s index by the specified channel values, or imputes ordinal scale domains from this mark’s channels.\n\nWhen imputing ordinal scale domains from channel values, the **sort** option is an object whose keys are ordinal scale names such as *x* or *fx*, and whose values are channel names such as *y*, *y1*, or *y2*. For example, to impute the *y* scale’s domain from the associated *x* channel values in ascending order:\n\n```js sort: {y: \"x\"} ```\n\nFor different sort options for different scales, replace the channel name with a *value* object and per-scale options:\n\n```js sort: {y: {value: \"-x\"}} ```\n\nWhen sorting the mark’s index, the **sort** option is instead one of:\n\n- a channel value definition for sorting given values in ascending order\n- a {value, order} object for sorting given values\n- a {channel, order} object for sorting the named channel’s values" + }, + "stroke": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke" + }, + "strokeDasharray": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dasharray][1]; a constant number indicating the length in pixels of alternating dashes and gaps, or a constant string of numbers separated by spaces or commas (_e.g._, *10 2* for dashes of 10 pixels separated by gaps of 2 pixels), or *none* (the default) for no dashing\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dasharray" + }, + "strokeDashoffset": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dashoffset][1]; a constant indicating the offset in pixels of the first dash along the stroke; defaults to zero.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dashoffset" + }, + "strokeLinecap": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linecap][1]; a constant specifying how to cap stroked paths, such as *butt*, *round*, or *square*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linecap" + }, + "strokeLinejoin": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linejoin][1]; a constant specifying how to join stroked paths, such as *bevel*, *miter*, *miter-clip*, or *round*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linejoin" + }, + "strokeMiterlimit": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-miterlimit][1]; a constant number specifying how to limit the length of *miter* joins on stroked paths.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-miterlimit" + }, + "strokeOpacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-opacity" + }, + "strokeWidth": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-width][1]; a constant number in pixels, or a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-width" + }, + "target": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [target][1]; a constant string specifying the target window (_e.g._,\n*_blank*) for clickable links; used in conjunction with the **href** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/target" + }, + "tip": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/TipPointer" + }, + { + "properties": { + "anchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The tip anchor specifies how to orient the tip box relative to its anchor position; it refers to the part of the tip box that is attached to the anchor point. For example, the *top-left* anchor places the top-left corner of tip box near the anchor position, hence placing the tip box below and to the right of the anchor position." + }, + "fontFamily": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font-family][1]; a constant; defaults to the plot’s font family, which is typically [*system-ui*][2].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-family [2]: https://drafts.csswg.org/css-fonts-4/#valdef-font-family-system-ui" + }, + "fontSize": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font size][1] in pixels; either a constant or a channel; defaults to the plot’s font size, which is typically 10. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-size" + }, + "fontStyle": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font style][1]; a constant; defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-style" + }, + "fontVariant": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font variant][1]; a constant; if the **text** channel contains numbers or dates, defaults to *tabular-nums* to facilitate comparing numbers; otherwise defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant" + }, + "fontWeight": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font weight][1]; a constant; defaults to the plot’s font weight, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight" + }, + "format": { + "additionalProperties": false, + "description": "How channel values are formatted for display. If a format is a string, it is interpreted as a (UTC) time format for temporal channels, and otherwise a number format.", + "properties": { + "ariaLabel": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fill": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fillOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fontSize": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fx": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fy": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "geometry": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "height": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "href": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "length": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "opacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "path": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "r": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "rotate": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "src": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "stroke": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeWidth": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "symbol": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "text": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "title": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "weight": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "width": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "z": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + } + }, + "type": "object" + }, + "frameAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The frame anchor specifies defaults for **x** and **y** based on the plot’s frame; it may be one of the four sides (*top*, *right*, *bottom*, *left*), one of the four corners (*top-left*, *top-right*, *bottom-right*,\n*bottom-left*), or the *middle* of the frame. For example, for tips distributed horizontally at the top of the frame:\n\n```js Plot.tip(data, {x: \"date\", frameAnchor: \"top\"}) ```" + }, + "lineHeight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line height in ems; defaults to 1. The line height affects the (typically vertical) separation between adjacent baselines of text, as well as the separation between the text and its anchor point." + }, + "lineWidth": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line width in ems (e.g., 10 for about 20 characters); defaults to infinity, disabling wrapping and clipping.\n\nIf **textOverflow** is null, lines will be wrapped at the specified length. If a line is split at a soft hyphen (\\xad), a hyphen (-) will be displayed at the end of the line. If **textOverflow** is not null, lines will be clipped according to the given strategy." + }, + "monospace": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, changes the default **fontFamily** to *monospace*, and uses simplified monospaced text metrics calculations." + }, + "pathFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The image filter for the tip’s box; defaults to a drop shadow." + }, + "pointer": { + "$ref": "#/definitions/TipPointer" + }, + "pointerSize": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The size of the tip’s pointer in pixels; defaults to 12." + }, + "preferredAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If an explicit tip anchor is not specified, an anchor is chosen automatically such that the tip fits within the plot’s frame; if the preferred anchor fits, it is chosen." + }, + "textAnchor": { + "anyOf": [ + { + "const": "start", + "type": "string" + }, + { + "const": "middle", + "type": "string" + }, + { + "const": "end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [text anchor][1] controls how text is aligned (typically horizontally) relative to its anchor point; it is one of *start*, *end*, or *middle*. If the frame anchor is *left*, *top-left*, or *bottom-left*, the default text anchor is *start*; if the frame anchor is *right*, *top-right*, or\n*bottom-right*, the default is *end*; otherwise it is *middle*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/text-anchor" + }, + "textOverflow": { + "anyOf": [ + { + "type": "null" + }, + { + "const": "clip", + "type": "string" + }, + { + "const": "ellipsis", + "type": "string" + }, + { + "const": "clip-start", + "type": "string" + }, + { + "const": "clip-end", + "type": "string" + }, + { + "const": "ellipsis-start", + "type": "string" + }, + { + "const": "ellipsis-middle", + "type": "string" + }, + { + "const": "ellipsis-end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How truncate (or wrap) lines of text longer than the given **lineWidth**; one of:\n\n- null (default) - preserve overflowing characters (and wrap if needed)\n- *clip* or *clip-end* - remove characters from the end\n- *clip-start* - remove characters from the start\n- *ellipsis* or *ellipsis-end* - replace characters from the end with an ellipsis (…)\n- *ellipsis-start* - replace characters from the start with an ellipsis (…)\n- *ellipsis-middle* - replace characters from the middle with an ellipsis (…)\n\nIf no **title** was specified, if text requires truncation, a title containing the non-truncated text will be implicitly added." + }, + "textPadding": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The padding around the text in pixels; defaults to 8." + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + } + }, + "type": "object" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to generate a tooltip for this mark, and any tip options." + }, + "title": { + "$ref": "#/definitions/ChannelValue", + "description": "The title; a channel specifying accessible, short textual descriptions as strings (possibly with newlines). If the tip option is specified, the title will be displayed with an interactive tooltip instead of using the SVG [title element][1].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/title" + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The optional horizontal position of the tick; an ordinal channel typically bound to the *x* scale. If not specified, the tick spans the horizontal extent of the frame; otherwise the *x* scale must be a *band* scale.\n\nIf *x* represents quantitative or temporal values, use a ruleY mark instead." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The required vertical position of the tick; a channel typically bound to the *y* scale." + } + }, + "required": [ + "data", + "mark" + ], + "type": "object" + }, + "TimeIntervalName": { + "description": "The built-in time intervals; UTC or local time, depending on context. The\n*week* interval is an alias for *sunday*. The *quarter* interval is every three months, and the *half* interval is every six months, aligned at the start of the year.", + "enum": [ + "second", + "minute", + "hour", + "day", + "week", + "month", + "quarter", + "half", + "year", + "monday", + "tuesday", + "wednesday", + "thursday", + "friday", + "saturday", + "sunday" + ], + "type": "string" + }, + "TipPointer": { + "description": "The pointer mode for the tip; corresponds to pointerX, pointerY, and pointer.", + "enum": [ + "x", + "y", + "xy" + ], + "type": "string" + }, + "Toggle": { + "additionalProperties": false, + "description": "A toggle interactor.", + "properties": { + "as": { + "$ref": "#/definitions/ParamRef", + "description": "The output selection. A clause of the form `(field = value1) OR (field = value2) ...` is added for the currently selected values." + }, + "channels": { + "description": "The encoding channels over which to select values. For a selected mark, selection clauses will cover the backing data fields for each channel.", + "items": { + "type": "string" + }, + "type": "array" + }, + "peers": { + "description": "A flag indicating if peer (sibling) marks are when cross-filtering (default `true`). If set, peer marks will not be filtered by this interactor's selection in cross-filtering setups.", + "type": "boolean" + }, + "select": { + "const": "toggle", + "description": "Select individal values.", + "type": "string" + } + }, + "required": [ + "as", + "channels", + "select" + ], + "type": "object" + }, + "ToggleColor": { + "additionalProperties": false, + "description": "A toggleColor interactor.", + "properties": { + "as": { + "$ref": "#/definitions/ParamRef", + "description": "The output selection. A clause of the form `(field = value1) OR (field = value2) ...` is added for the currently selected values." + }, + "peers": { + "description": "A flag indicating if peer (sibling) marks are when cross-filtering (default `true`). If set, peer marks will not be filtered by this interactor's selection in cross-filtering setups.", + "type": "boolean" + }, + "select": { + "const": "toggleColor", + "description": "Select individal values in the `color` scale domain. Clicking or touching a mark toggles its selection status.", + "type": "string" + } + }, + "required": [ + "as", + "select" + ], + "type": "object" + }, + "ToggleX": { + "additionalProperties": false, + "description": "A toggleX interactor.", + "properties": { + "as": { + "$ref": "#/definitions/ParamRef", + "description": "The output selection. A clause of the form `(field = value1) OR (field = value2) ...` is added for the currently selected values." + }, + "peers": { + "description": "A flag indicating if peer (sibling) marks are when cross-filtering (default `true`). If set, peer marks will not be filtered by this interactor's selection in cross-filtering setups.", + "type": "boolean" + }, + "select": { + "const": "toggleX", + "description": "Select individal values in the `x` scale domain. Clicking or touching a mark toggles its selection status.", + "type": "string" + } + }, + "required": [ + "as", + "select" + ], + "type": "object" + }, + "ToggleY": { + "additionalProperties": false, + "description": "A toggleY interactor.", + "properties": { + "as": { + "$ref": "#/definitions/ParamRef", + "description": "The output selection. A clause of the form `(field = value1) OR (field = value2) ...` is added for the currently selected values." + }, + "peers": { + "description": "A flag indicating if peer (sibling) marks are when cross-filtering (default `true`). If set, peer marks will not be filtered by this interactor's selection in cross-filtering setups.", + "type": "boolean" + }, + "select": { + "const": "toggleY", + "description": "Select individal values in the `y` scale domain. Clicking or touching a mark toggles its selection status.", + "type": "string" + } + }, + "required": [ + "as", + "select" + ], + "type": "object" + }, + "Transform": { + "anyOf": [ + { + "$ref": "#/definitions/ColumnTransform" + }, + { + "$ref": "#/definitions/AggregateTransform" + }, + { + "$ref": "#/definitions/WindowTransform" + } + ], + "description": "A data transform." + }, + "TransformField": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A field argument to a data transform." + }, + "VConcat": { + "additionalProperties": false, + "description": "A vconcat component.", + "properties": { + "vconcat": { + "description": "Vertically concatenate components in a column layout.", + "items": { + "$ref": "#/definitions/Component" + }, + "type": "array" + } + }, + "required": [ + "vconcat" + ], + "type": "object" + }, + "VSpace": { + "additionalProperties": false, + "description": "A vspace component.", + "properties": { + "vspace": { + "description": "Vertical space to place between components. Number values indicate screen pixels. String values may use CSS units (em, pt, px, etc).", + "type": [ + "number", + "string" + ] + } + }, + "required": [ + "vspace" + ], + "type": "object" + }, + "VarPop": { + "additionalProperties": false, + "properties": { + "distinct": { + "type": "boolean" + }, + "orderby": { + "anyOf": [ + { + "$ref": "#/definitions/TransformField" + }, + { + "items": { + "$ref": "#/definitions/TransformField" + }, + "type": "array" + } + ] + }, + "partitionby": { + "anyOf": [ + { + "$ref": "#/definitions/TransformField" + }, + { + "items": { + "$ref": "#/definitions/TransformField" + }, + "type": "array" + } + ] + }, + "range": { + "anyOf": [ + { + "items": { + "type": [ + "number", + "null" + ] + }, + "type": "array" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "rows": { + "anyOf": [ + { + "items": { + "type": [ + "number", + "null" + ] + }, + "type": "array" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "varPop": { + "anyOf": [ + { + "description": "A transform argument.", + "type": [ + "string", + "number", + "boolean" + ] + }, + { + "items": { + "description": "A transform argument.", + "type": [ + "string", + "number", + "boolean" + ] + }, + "maxItems": 1, + "minItems": 1, + "type": "array" + } + ], + "description": "Compute the population variance of the given column." + } + }, + "required": [ + "varPop" + ], + "type": "object" + }, + "Variance": { + "additionalProperties": false, + "properties": { + "distinct": { + "type": "boolean" + }, + "orderby": { + "anyOf": [ + { + "$ref": "#/definitions/TransformField" + }, + { + "items": { + "$ref": "#/definitions/TransformField" + }, + "type": "array" + } + ] + }, + "partitionby": { + "anyOf": [ + { + "$ref": "#/definitions/TransformField" + }, + { + "items": { + "$ref": "#/definitions/TransformField" + }, + "type": "array" + } + ] + }, + "range": { + "anyOf": [ + { + "items": { + "type": [ + "number", + "null" + ] + }, + "type": "array" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "rows": { + "anyOf": [ + { + "items": { + "type": [ + "number", + "null" + ] + }, + "type": "array" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "variance": { + "anyOf": [ + { + "description": "A transform argument.", + "type": [ + "string", + "number", + "boolean" + ] + }, + { + "items": { + "description": "A transform argument.", + "type": [ + "string", + "number", + "boolean" + ] + }, + "maxItems": 1, + "minItems": 1, + "type": "array" + } + ], + "description": "Compute the sample variance of the given column." + } + }, + "required": [ + "variance" + ], + "type": "object" + }, + "Vector": { + "additionalProperties": false, + "description": "The vector mark.", + "properties": { + "anchor": { + "anyOf": [ + { + "const": "start", + "type": "string" + }, + { + "const": "middle", + "type": "string" + }, + { + "const": "end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The vector’s position along its orientation relative to its anchor point; a constant. Assuming a default **rotate** angle of 0°, one of:\n\n- *start* - from [*x*, *y*] to [*x*, *y* - *l*]\n- *middle* (default) - from [*x*, *y* + *l* / 2] to [*x*, *y* - *l* / 2]\n- *end* - from [*x*, *y* + *l*] to [*x*, *y*]\n\nwhere [*x*, *y*] is the vector’s anchor point and *l* is the vector’s (possibly scaled) length in pixels." + }, + "ariaDescription": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-description][1]; a constant textual description.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-description" + }, + "ariaHidden": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-hidden][1] state; a constant indicating whether the element is exposed to an accessibility API.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-hidden" + }, + "ariaLabel": { + "$ref": "#/definitions/ChannelValue", + "description": "The [aria-label][1]; a channel specifying short textual labels representing the value in the accessibility tree.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-label" + }, + "clip": { + "anyOf": [ + { + "const": "frame", + "type": "string" + }, + { + "const": "sphere", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to clip the mark; one of:\n\n- *frame* or true - clip to the plot’s frame (inner area)\n- *sphere* - clip to the projected sphere (*e.g.*, front hemisphere)\n- null or false - do not clip\n\nThe *sphere* clip option requires a geographic projection." + }, + "data": { + "$ref": "#/definitions/PlotMarkData", + "description": "The data source for the mark." + }, + "dx": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The horizontal offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "dy": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The vertical offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "facet": { + "anyOf": [ + { + "const": "auto", + "type": "string" + }, + { + "const": "include", + "type": "string" + }, + { + "const": "exclude", + "type": "string" + }, + { + "const": "super", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to enable or disable faceting; one of:\n\n- *auto* (default) - automatically determine if this mark should be faceted\n- *include* (or true) - draw the subset of the mark’s data in the current facet\n- *exclude* - draw the subset of the mark’s data *not* in the current facet\n- *super* - draw this mark in a single frame that covers all facets\n- null (or false) - repeat this mark’s data across all facets (*i.e.*, no faceting)\n\nWhen a mark uses *super* faceting, it is not allowed to use position scales (*x*, *y*, *fx*, or *fy*); *super* faceting is intended for decorations, such as labels and legends.\n\nWhen top-level faceting is used, the default *auto* setting is equivalent to *include* when the mark data is strictly equal to the top-level facet data; otherwise it is equivalent to null. When the *include* or *exclude* facet mode is chosen, the mark data must be parallel to the top-level facet data: the data must have the same length and order. If the data are not parallel, then the wrong data may be shown in each facet. The default\n*auto* therefore requires strict equality (`===`) for safety, and using the facet data as mark data is recommended when using the *exclude* facet mode. (To construct parallel data safely, consider using [*array*.map][1] on the facet data.)\n\nWhen mark-level faceting is used, the default *auto* setting is equivalent to *include*: the mark will be faceted if either the **fx** or **fy** channel option (or both) is specified. The null or false option will disable faceting, while *exclude* draws the subset of the mark’s data *not* in the current facet.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map" + }, + "facetAnchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "right", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "const": "left", + "type": "string" + }, + { + "const": "top-left", + "type": "string" + }, + { + "const": "top-right", + "type": "string" + }, + { + "const": "bottom-left", + "type": "string" + }, + { + "const": "bottom-right", + "type": "string" + }, + { + "const": "top-empty", + "type": "string" + }, + { + "const": "right-empty", + "type": "string" + }, + { + "const": "bottom-empty", + "type": "string" + }, + { + "const": "left-empty", + "type": "string" + }, + { + "const": "empty", + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to place the mark with respect to facets; one of:\n\n- null (default for most marks) - display the mark in each non-empty facet\n- *top*, *right*, *bottom*, or *left* - display the mark only in facets on the given side\n- *top-empty*, *right-empty*, *bottom-empty*, or *left-empty* (default for axis marks) - display the mark only in facets that have empty space on the given side: either the margin, or an empty facet\n- *empty* - display the mark in empty facets only" + }, + "fill": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill" + }, + "fillOpacity": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill-opacity][1]; a constant number between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill-opacity" + }, + "filter": { + "$ref": "#/definitions/ChannelValue", + "description": "Applies a transform to filter the mark’s index according to the given channel values; only truthy values are retained.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "frameAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The vector’s frame anchor, to default **x** and **y** relative to the frame; a constant representing one of the frame corners (*top-left*,\n*top-right*, *bottom-right*, *bottom-left*), sides (*top*, *right*,\n*bottom*, *left*), or *middle* (default). Has no effect if both **x** and **y** are specified." + }, + "fx": { + "$ref": "#/definitions/ChannelValue", + "description": "The horizontal facet position channel, for mark-level faceting, bound to the *fx* scale." + }, + "fy": { + "$ref": "#/definitions/ChannelValue", + "description": "The vertical facet position channel, for mark-level faceting, bound to the\n*fy* scale." + }, + "href": { + "$ref": "#/definitions/ChannelValue", + "description": "The [href][1]; a channel specifying URLs for clickable links. May be used in conjunction with the **target** option to open links in another window.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/href" + }, + "imageFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A CSS [filter][1]; a constant string used to adjust the rendering of images, such as *blur(5px)*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/filter" + }, + "length": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vector’s length; either an optional channel bound to the *length* scale or a constant number in pixels. Defaults to 12 pixels." + }, + "margin": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four mark margins: **marginTop**,\n**marginRight**, **marginBottom**, and **marginLeft**; typically defaults to 0, except for axis marks." + }, + "marginBottom": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s bottom margin; the minimum distance in pixels between the bottom edges of the inner and outer plot area." + }, + "marginLeft": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s left margin; the minimum distance in pixels between the left edges of the inner and outer plot area." + }, + "marginRight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s right margin; the minimum distance in pixels between the right edges of the mark’s inner and outer plot area." + }, + "marginTop": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s top margin; the minimum distance in pixels between the top edges of the inner and outer plot area." + }, + "mark": { + "const": "vector", + "description": "A vector mark.\n\nIf none of **frameAnchor**, **x**, and **y** are specified, then **x** and\n**y** default to accessors assuming that *data* contains tuples [[*x₀*,\n*y₀*], [*x₁*, *y₁*], [*x₂*, *y₂*], …]", + "type": "string" + }, + "mixBlendMode": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [mix-blend-mode][1]; a constant string specifying how to blend content such as *multiply*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode" + }, + "opacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally. For faster rendering, prefer the **strokeOpacity** or **fillOpacity** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/opacity" + }, + "paintOrder": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [paint-order][1]; a constant string specifying the order in which the\n**fill**, **stroke**, and any markers are drawn; defaults to *normal*, which draws the fill, then stroke, then markers; defaults to *stroke* for the text mark to create a “halo” around text to improve legibility.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/paint-order" + }, + "pointerEvents": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [pointer-events][1] property; a constant string such as *none*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/pointer-events" + }, + "r": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The vector shape’s radius, such as half the width of the *arrow*’s head or the *spike*’s base; a constant number in pixels. Defaults to 3.5 pixels." + }, + "reverse": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Applies a transform to reverse the order of the mark’s index, say for reverse input order." + }, + "rotate": { + "$ref": "#/definitions/ChannelValue", + "description": "The vector’s orientation (rotation angle); either a constant number in degrees clockwise, or an optional channel (with no associated scale). Defaults to 0 degrees with the vector pointing up." + }, + "select": { + "$ref": "#/definitions/SelectFilter", + "description": "Applies a filter transform after data is loaded to highlight selected values only. For example, `first` and `last` select the first or last values of series only (using the *z* channel to separate series). Meanwhile, `nearestX` and `nearestY` select the point nearest to the pointer along the *x* or *y* channel dimension. Unlike Mosaic selections, a mark level *select* is internal to the mark only, and does not populate a param or selection value to be shared across clients.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "shape": { + "anyOf": [ + { + "$ref": "#/definitions/VectorShape" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The shape of the vector; a constant. Defaults to *arrow*." + }, + "shapeRendering": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [shape-rendering][1]; a constant string such as *crispEdges*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/shape-rendering" + }, + "sort": { + "anyOf": [ + { + "$ref": "#/definitions/SortOrder" + }, + { + "$ref": "#/definitions/ChannelDomainSort" + } + ], + "description": "Either applies a transform to sort the mark’s index by the specified channel values, or imputes ordinal scale domains from this mark’s channels.\n\nWhen imputing ordinal scale domains from channel values, the **sort** option is an object whose keys are ordinal scale names such as *x* or *fx*, and whose values are channel names such as *y*, *y1*, or *y2*. For example, to impute the *y* scale’s domain from the associated *x* channel values in ascending order:\n\n```js sort: {y: \"x\"} ```\n\nFor different sort options for different scales, replace the channel name with a *value* object and per-scale options:\n\n```js sort: {y: {value: \"-x\"}} ```\n\nWhen sorting the mark’s index, the **sort** option is instead one of:\n\n- a channel value definition for sorting given values in ascending order\n- a {value, order} object for sorting given values\n- a {channel, order} object for sorting the named channel’s values" + }, + "stroke": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke" + }, + "strokeDasharray": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dasharray][1]; a constant number indicating the length in pixels of alternating dashes and gaps, or a constant string of numbers separated by spaces or commas (_e.g._, *10 2* for dashes of 10 pixels separated by gaps of 2 pixels), or *none* (the default) for no dashing\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dasharray" + }, + "strokeDashoffset": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dashoffset][1]; a constant indicating the offset in pixels of the first dash along the stroke; defaults to zero.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dashoffset" + }, + "strokeLinecap": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linecap][1]; a constant specifying how to cap stroked paths, such as *butt*, *round*, or *square*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linecap" + }, + "strokeLinejoin": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linejoin][1]; a constant specifying how to join stroked paths, such as *bevel*, *miter*, *miter-clip*, or *round*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linejoin" + }, + "strokeMiterlimit": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-miterlimit][1]; a constant number specifying how to limit the length of *miter* joins on stroked paths.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-miterlimit" + }, + "strokeOpacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-opacity" + }, + "strokeWidth": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-width][1]; a constant number in pixels, or a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-width" + }, + "target": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [target][1]; a constant string specifying the target window (_e.g._,\n*_blank*) for clickable links; used in conjunction with the **href** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/target" + }, + "tip": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/TipPointer" + }, + { + "properties": { + "anchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The tip anchor specifies how to orient the tip box relative to its anchor position; it refers to the part of the tip box that is attached to the anchor point. For example, the *top-left* anchor places the top-left corner of tip box near the anchor position, hence placing the tip box below and to the right of the anchor position." + }, + "fontFamily": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font-family][1]; a constant; defaults to the plot’s font family, which is typically [*system-ui*][2].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-family [2]: https://drafts.csswg.org/css-fonts-4/#valdef-font-family-system-ui" + }, + "fontSize": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font size][1] in pixels; either a constant or a channel; defaults to the plot’s font size, which is typically 10. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-size" + }, + "fontStyle": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font style][1]; a constant; defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-style" + }, + "fontVariant": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font variant][1]; a constant; if the **text** channel contains numbers or dates, defaults to *tabular-nums* to facilitate comparing numbers; otherwise defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant" + }, + "fontWeight": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font weight][1]; a constant; defaults to the plot’s font weight, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight" + }, + "format": { + "additionalProperties": false, + "description": "How channel values are formatted for display. If a format is a string, it is interpreted as a (UTC) time format for temporal channels, and otherwise a number format.", + "properties": { + "ariaLabel": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fill": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fillOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fontSize": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fx": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fy": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "geometry": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "height": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "href": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "length": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "opacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "path": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "r": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "rotate": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "src": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "stroke": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeWidth": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "symbol": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "text": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "title": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "weight": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "width": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "z": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + } + }, + "type": "object" + }, + "frameAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The frame anchor specifies defaults for **x** and **y** based on the plot’s frame; it may be one of the four sides (*top*, *right*, *bottom*, *left*), one of the four corners (*top-left*, *top-right*, *bottom-right*,\n*bottom-left*), or the *middle* of the frame. For example, for tips distributed horizontally at the top of the frame:\n\n```js Plot.tip(data, {x: \"date\", frameAnchor: \"top\"}) ```" + }, + "lineHeight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line height in ems; defaults to 1. The line height affects the (typically vertical) separation between adjacent baselines of text, as well as the separation between the text and its anchor point." + }, + "lineWidth": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line width in ems (e.g., 10 for about 20 characters); defaults to infinity, disabling wrapping and clipping.\n\nIf **textOverflow** is null, lines will be wrapped at the specified length. If a line is split at a soft hyphen (\\xad), a hyphen (-) will be displayed at the end of the line. If **textOverflow** is not null, lines will be clipped according to the given strategy." + }, + "monospace": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, changes the default **fontFamily** to *monospace*, and uses simplified monospaced text metrics calculations." + }, + "pathFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The image filter for the tip’s box; defaults to a drop shadow." + }, + "pointer": { + "$ref": "#/definitions/TipPointer" + }, + "pointerSize": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The size of the tip’s pointer in pixels; defaults to 12." + }, + "preferredAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If an explicit tip anchor is not specified, an anchor is chosen automatically such that the tip fits within the plot’s frame; if the preferred anchor fits, it is chosen." + }, + "textAnchor": { + "anyOf": [ + { + "const": "start", + "type": "string" + }, + { + "const": "middle", + "type": "string" + }, + { + "const": "end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [text anchor][1] controls how text is aligned (typically horizontally) relative to its anchor point; it is one of *start*, *end*, or *middle*. If the frame anchor is *left*, *top-left*, or *bottom-left*, the default text anchor is *start*; if the frame anchor is *right*, *top-right*, or\n*bottom-right*, the default is *end*; otherwise it is *middle*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/text-anchor" + }, + "textOverflow": { + "anyOf": [ + { + "type": "null" + }, + { + "const": "clip", + "type": "string" + }, + { + "const": "ellipsis", + "type": "string" + }, + { + "const": "clip-start", + "type": "string" + }, + { + "const": "clip-end", + "type": "string" + }, + { + "const": "ellipsis-start", + "type": "string" + }, + { + "const": "ellipsis-middle", + "type": "string" + }, + { + "const": "ellipsis-end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How truncate (or wrap) lines of text longer than the given **lineWidth**; one of:\n\n- null (default) - preserve overflowing characters (and wrap if needed)\n- *clip* or *clip-end* - remove characters from the end\n- *clip-start* - remove characters from the start\n- *ellipsis* or *ellipsis-end* - replace characters from the end with an ellipsis (…)\n- *ellipsis-start* - replace characters from the start with an ellipsis (…)\n- *ellipsis-middle* - replace characters from the middle with an ellipsis (…)\n\nIf no **title** was specified, if text requires truncation, a title containing the non-truncated text will be implicitly added." + }, + "textPadding": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The padding around the text in pixels; defaults to 8." + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + } + }, + "type": "object" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to generate a tooltip for this mark, and any tip options." + }, + "title": { + "$ref": "#/definitions/ChannelValue", + "description": "The title; a channel specifying accessible, short textual descriptions as strings (possibly with newlines). If the tip option is specified, the title will be displayed with an interactive tooltip instead of using the SVG [title element][1].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/title" + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position of the vector’s anchor point; an optional channel bound to the *x* scale. Default depends on the **frameAnchor**." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position of the vector’s anchor point; an optional channel bound to the *y* scale. Default depends on the **frameAnchor**." + } + }, + "required": [ + "data", + "mark" + ], + "type": "object" + }, + "VectorShape": { + "$ref": "#/definitions/VectorShapeName", + "description": "How to draw a vector: either a named shape or a custom implementation." + }, + "VectorShapeName": { + "description": "The built-in vector shape implementations; one of:\n\n- *arrow* - a straight line with an open arrowhead at the end (↑)\n- *spike* - an isosceles triangle with a flat base (▲)", + "enum": [ + "arrow", + "spike" + ], + "type": "string" + }, + "VectorX": { + "additionalProperties": false, + "description": "The vectorX mark.", + "properties": { + "anchor": { + "anyOf": [ + { + "const": "start", + "type": "string" + }, + { + "const": "middle", + "type": "string" + }, + { + "const": "end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The vector’s position along its orientation relative to its anchor point; a constant. Assuming a default **rotate** angle of 0°, one of:\n\n- *start* - from [*x*, *y*] to [*x*, *y* - *l*]\n- *middle* (default) - from [*x*, *y* + *l* / 2] to [*x*, *y* - *l* / 2]\n- *end* - from [*x*, *y* + *l*] to [*x*, *y*]\n\nwhere [*x*, *y*] is the vector’s anchor point and *l* is the vector’s (possibly scaled) length in pixels." + }, + "ariaDescription": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-description][1]; a constant textual description.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-description" + }, + "ariaHidden": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-hidden][1] state; a constant indicating whether the element is exposed to an accessibility API.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-hidden" + }, + "ariaLabel": { + "$ref": "#/definitions/ChannelValue", + "description": "The [aria-label][1]; a channel specifying short textual labels representing the value in the accessibility tree.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-label" + }, + "clip": { + "anyOf": [ + { + "const": "frame", + "type": "string" + }, + { + "const": "sphere", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to clip the mark; one of:\n\n- *frame* or true - clip to the plot’s frame (inner area)\n- *sphere* - clip to the projected sphere (*e.g.*, front hemisphere)\n- null or false - do not clip\n\nThe *sphere* clip option requires a geographic projection." + }, + "data": { + "$ref": "#/definitions/PlotMarkData", + "description": "The data source for the mark." + }, + "dx": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The horizontal offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "dy": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The vertical offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "facet": { + "anyOf": [ + { + "const": "auto", + "type": "string" + }, + { + "const": "include", + "type": "string" + }, + { + "const": "exclude", + "type": "string" + }, + { + "const": "super", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to enable or disable faceting; one of:\n\n- *auto* (default) - automatically determine if this mark should be faceted\n- *include* (or true) - draw the subset of the mark’s data in the current facet\n- *exclude* - draw the subset of the mark’s data *not* in the current facet\n- *super* - draw this mark in a single frame that covers all facets\n- null (or false) - repeat this mark’s data across all facets (*i.e.*, no faceting)\n\nWhen a mark uses *super* faceting, it is not allowed to use position scales (*x*, *y*, *fx*, or *fy*); *super* faceting is intended for decorations, such as labels and legends.\n\nWhen top-level faceting is used, the default *auto* setting is equivalent to *include* when the mark data is strictly equal to the top-level facet data; otherwise it is equivalent to null. When the *include* or *exclude* facet mode is chosen, the mark data must be parallel to the top-level facet data: the data must have the same length and order. If the data are not parallel, then the wrong data may be shown in each facet. The default\n*auto* therefore requires strict equality (`===`) for safety, and using the facet data as mark data is recommended when using the *exclude* facet mode. (To construct parallel data safely, consider using [*array*.map][1] on the facet data.)\n\nWhen mark-level faceting is used, the default *auto* setting is equivalent to *include*: the mark will be faceted if either the **fx** or **fy** channel option (or both) is specified. The null or false option will disable faceting, while *exclude* draws the subset of the mark’s data *not* in the current facet.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map" + }, + "facetAnchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "right", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "const": "left", + "type": "string" + }, + { + "const": "top-left", + "type": "string" + }, + { + "const": "top-right", + "type": "string" + }, + { + "const": "bottom-left", + "type": "string" + }, + { + "const": "bottom-right", + "type": "string" + }, + { + "const": "top-empty", + "type": "string" + }, + { + "const": "right-empty", + "type": "string" + }, + { + "const": "bottom-empty", + "type": "string" + }, + { + "const": "left-empty", + "type": "string" + }, + { + "const": "empty", + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to place the mark with respect to facets; one of:\n\n- null (default for most marks) - display the mark in each non-empty facet\n- *top*, *right*, *bottom*, or *left* - display the mark only in facets on the given side\n- *top-empty*, *right-empty*, *bottom-empty*, or *left-empty* (default for axis marks) - display the mark only in facets that have empty space on the given side: either the margin, or an empty facet\n- *empty* - display the mark in empty facets only" + }, + "fill": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill" + }, + "fillOpacity": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill-opacity][1]; a constant number between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill-opacity" + }, + "filter": { + "$ref": "#/definitions/ChannelValue", + "description": "Applies a transform to filter the mark’s index according to the given channel values; only truthy values are retained.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "frameAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The vector’s frame anchor, to default **x** and **y** relative to the frame; a constant representing one of the frame corners (*top-left*,\n*top-right*, *bottom-right*, *bottom-left*), sides (*top*, *right*,\n*bottom*, *left*), or *middle* (default). Has no effect if both **x** and **y** are specified." + }, + "fx": { + "$ref": "#/definitions/ChannelValue", + "description": "The horizontal facet position channel, for mark-level faceting, bound to the *fx* scale." + }, + "fy": { + "$ref": "#/definitions/ChannelValue", + "description": "The vertical facet position channel, for mark-level faceting, bound to the\n*fy* scale." + }, + "href": { + "$ref": "#/definitions/ChannelValue", + "description": "The [href][1]; a channel specifying URLs for clickable links. May be used in conjunction with the **target** option to open links in another window.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/href" + }, + "imageFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A CSS [filter][1]; a constant string used to adjust the rendering of images, such as *blur(5px)*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/filter" + }, + "length": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vector’s length; either an optional channel bound to the *length* scale or a constant number in pixels. Defaults to 12 pixels." + }, + "margin": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four mark margins: **marginTop**,\n**marginRight**, **marginBottom**, and **marginLeft**; typically defaults to 0, except for axis marks." + }, + "marginBottom": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s bottom margin; the minimum distance in pixels between the bottom edges of the inner and outer plot area." + }, + "marginLeft": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s left margin; the minimum distance in pixels between the left edges of the inner and outer plot area." + }, + "marginRight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s right margin; the minimum distance in pixels between the right edges of the mark’s inner and outer plot area." + }, + "marginTop": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s top margin; the minimum distance in pixels between the top edges of the inner and outer plot area." + }, + "mark": { + "const": "vectorX", + "description": "Like vector, but **x** instead defaults to the identity function and **y** defaults to null, assuming that *data* is an array of numbers [*x₀*, *x₁*,\n*x₂*, …].", + "type": "string" + }, + "mixBlendMode": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [mix-blend-mode][1]; a constant string specifying how to blend content such as *multiply*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode" + }, + "opacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally. For faster rendering, prefer the **strokeOpacity** or **fillOpacity** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/opacity" + }, + "paintOrder": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [paint-order][1]; a constant string specifying the order in which the\n**fill**, **stroke**, and any markers are drawn; defaults to *normal*, which draws the fill, then stroke, then markers; defaults to *stroke* for the text mark to create a “halo” around text to improve legibility.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/paint-order" + }, + "pointerEvents": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [pointer-events][1] property; a constant string such as *none*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/pointer-events" + }, + "r": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The vector shape’s radius, such as half the width of the *arrow*’s head or the *spike*’s base; a constant number in pixels. Defaults to 3.5 pixels." + }, + "reverse": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Applies a transform to reverse the order of the mark’s index, say for reverse input order." + }, + "rotate": { + "$ref": "#/definitions/ChannelValue", + "description": "The vector’s orientation (rotation angle); either a constant number in degrees clockwise, or an optional channel (with no associated scale). Defaults to 0 degrees with the vector pointing up." + }, + "select": { + "$ref": "#/definitions/SelectFilter", + "description": "Applies a filter transform after data is loaded to highlight selected values only. For example, `first` and `last` select the first or last values of series only (using the *z* channel to separate series). Meanwhile, `nearestX` and `nearestY` select the point nearest to the pointer along the *x* or *y* channel dimension. Unlike Mosaic selections, a mark level *select* is internal to the mark only, and does not populate a param or selection value to be shared across clients.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "shape": { + "anyOf": [ + { + "$ref": "#/definitions/VectorShape" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The shape of the vector; a constant. Defaults to *arrow*." + }, + "shapeRendering": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [shape-rendering][1]; a constant string such as *crispEdges*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/shape-rendering" + }, + "sort": { + "anyOf": [ + { + "$ref": "#/definitions/SortOrder" + }, + { + "$ref": "#/definitions/ChannelDomainSort" + } + ], + "description": "Either applies a transform to sort the mark’s index by the specified channel values, or imputes ordinal scale domains from this mark’s channels.\n\nWhen imputing ordinal scale domains from channel values, the **sort** option is an object whose keys are ordinal scale names such as *x* or *fx*, and whose values are channel names such as *y*, *y1*, or *y2*. For example, to impute the *y* scale’s domain from the associated *x* channel values in ascending order:\n\n```js sort: {y: \"x\"} ```\n\nFor different sort options for different scales, replace the channel name with a *value* object and per-scale options:\n\n```js sort: {y: {value: \"-x\"}} ```\n\nWhen sorting the mark’s index, the **sort** option is instead one of:\n\n- a channel value definition for sorting given values in ascending order\n- a {value, order} object for sorting given values\n- a {channel, order} object for sorting the named channel’s values" + }, + "stroke": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke" + }, + "strokeDasharray": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dasharray][1]; a constant number indicating the length in pixels of alternating dashes and gaps, or a constant string of numbers separated by spaces or commas (_e.g._, *10 2* for dashes of 10 pixels separated by gaps of 2 pixels), or *none* (the default) for no dashing\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dasharray" + }, + "strokeDashoffset": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dashoffset][1]; a constant indicating the offset in pixels of the first dash along the stroke; defaults to zero.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dashoffset" + }, + "strokeLinecap": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linecap][1]; a constant specifying how to cap stroked paths, such as *butt*, *round*, or *square*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linecap" + }, + "strokeLinejoin": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linejoin][1]; a constant specifying how to join stroked paths, such as *bevel*, *miter*, *miter-clip*, or *round*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linejoin" + }, + "strokeMiterlimit": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-miterlimit][1]; a constant number specifying how to limit the length of *miter* joins on stroked paths.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-miterlimit" + }, + "strokeOpacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-opacity" + }, + "strokeWidth": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-width][1]; a constant number in pixels, or a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-width" + }, + "target": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [target][1]; a constant string specifying the target window (_e.g._,\n*_blank*) for clickable links; used in conjunction with the **href** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/target" + }, + "tip": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/TipPointer" + }, + { + "properties": { + "anchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The tip anchor specifies how to orient the tip box relative to its anchor position; it refers to the part of the tip box that is attached to the anchor point. For example, the *top-left* anchor places the top-left corner of tip box near the anchor position, hence placing the tip box below and to the right of the anchor position." + }, + "fontFamily": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font-family][1]; a constant; defaults to the plot’s font family, which is typically [*system-ui*][2].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-family [2]: https://drafts.csswg.org/css-fonts-4/#valdef-font-family-system-ui" + }, + "fontSize": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font size][1] in pixels; either a constant or a channel; defaults to the plot’s font size, which is typically 10. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-size" + }, + "fontStyle": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font style][1]; a constant; defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-style" + }, + "fontVariant": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font variant][1]; a constant; if the **text** channel contains numbers or dates, defaults to *tabular-nums* to facilitate comparing numbers; otherwise defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant" + }, + "fontWeight": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font weight][1]; a constant; defaults to the plot’s font weight, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight" + }, + "format": { + "additionalProperties": false, + "description": "How channel values are formatted for display. If a format is a string, it is interpreted as a (UTC) time format for temporal channels, and otherwise a number format.", + "properties": { + "ariaLabel": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fill": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fillOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fontSize": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fx": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fy": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "geometry": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "height": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "href": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "length": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "opacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "path": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "r": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "rotate": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "src": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "stroke": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeWidth": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "symbol": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "text": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "title": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "weight": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "width": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "z": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + } + }, + "type": "object" + }, + "frameAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The frame anchor specifies defaults for **x** and **y** based on the plot’s frame; it may be one of the four sides (*top*, *right*, *bottom*, *left*), one of the four corners (*top-left*, *top-right*, *bottom-right*,\n*bottom-left*), or the *middle* of the frame. For example, for tips distributed horizontally at the top of the frame:\n\n```js Plot.tip(data, {x: \"date\", frameAnchor: \"top\"}) ```" + }, + "lineHeight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line height in ems; defaults to 1. The line height affects the (typically vertical) separation between adjacent baselines of text, as well as the separation between the text and its anchor point." + }, + "lineWidth": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line width in ems (e.g., 10 for about 20 characters); defaults to infinity, disabling wrapping and clipping.\n\nIf **textOverflow** is null, lines will be wrapped at the specified length. If a line is split at a soft hyphen (\\xad), a hyphen (-) will be displayed at the end of the line. If **textOverflow** is not null, lines will be clipped according to the given strategy." + }, + "monospace": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, changes the default **fontFamily** to *monospace*, and uses simplified monospaced text metrics calculations." + }, + "pathFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The image filter for the tip’s box; defaults to a drop shadow." + }, + "pointer": { + "$ref": "#/definitions/TipPointer" + }, + "pointerSize": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The size of the tip’s pointer in pixels; defaults to 12." + }, + "preferredAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If an explicit tip anchor is not specified, an anchor is chosen automatically such that the tip fits within the plot’s frame; if the preferred anchor fits, it is chosen." + }, + "textAnchor": { + "anyOf": [ + { + "const": "start", + "type": "string" + }, + { + "const": "middle", + "type": "string" + }, + { + "const": "end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [text anchor][1] controls how text is aligned (typically horizontally) relative to its anchor point; it is one of *start*, *end*, or *middle*. If the frame anchor is *left*, *top-left*, or *bottom-left*, the default text anchor is *start*; if the frame anchor is *right*, *top-right*, or\n*bottom-right*, the default is *end*; otherwise it is *middle*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/text-anchor" + }, + "textOverflow": { + "anyOf": [ + { + "type": "null" + }, + { + "const": "clip", + "type": "string" + }, + { + "const": "ellipsis", + "type": "string" + }, + { + "const": "clip-start", + "type": "string" + }, + { + "const": "clip-end", + "type": "string" + }, + { + "const": "ellipsis-start", + "type": "string" + }, + { + "const": "ellipsis-middle", + "type": "string" + }, + { + "const": "ellipsis-end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How truncate (or wrap) lines of text longer than the given **lineWidth**; one of:\n\n- null (default) - preserve overflowing characters (and wrap if needed)\n- *clip* or *clip-end* - remove characters from the end\n- *clip-start* - remove characters from the start\n- *ellipsis* or *ellipsis-end* - replace characters from the end with an ellipsis (…)\n- *ellipsis-start* - replace characters from the start with an ellipsis (…)\n- *ellipsis-middle* - replace characters from the middle with an ellipsis (…)\n\nIf no **title** was specified, if text requires truncation, a title containing the non-truncated text will be implicitly added." + }, + "textPadding": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The padding around the text in pixels; defaults to 8." + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + } + }, + "type": "object" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to generate a tooltip for this mark, and any tip options." + }, + "title": { + "$ref": "#/definitions/ChannelValue", + "description": "The title; a channel specifying accessible, short textual descriptions as strings (possibly with newlines). If the tip option is specified, the title will be displayed with an interactive tooltip instead of using the SVG [title element][1].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/title" + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position of the vector’s anchor point; an optional channel bound to the *x* scale. Default depends on the **frameAnchor**." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position of the vector’s anchor point; an optional channel bound to the *y* scale. Default depends on the **frameAnchor**." + } + }, + "required": [ + "data", + "mark" + ], + "type": "object" + }, + "VectorY": { + "additionalProperties": false, + "description": "The vectorY mark.", + "properties": { + "anchor": { + "anyOf": [ + { + "const": "start", + "type": "string" + }, + { + "const": "middle", + "type": "string" + }, + { + "const": "end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The vector’s position along its orientation relative to its anchor point; a constant. Assuming a default **rotate** angle of 0°, one of:\n\n- *start* - from [*x*, *y*] to [*x*, *y* - *l*]\n- *middle* (default) - from [*x*, *y* + *l* / 2] to [*x*, *y* - *l* / 2]\n- *end* - from [*x*, *y* + *l*] to [*x*, *y*]\n\nwhere [*x*, *y*] is the vector’s anchor point and *l* is the vector’s (possibly scaled) length in pixels." + }, + "ariaDescription": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-description][1]; a constant textual description.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-description" + }, + "ariaHidden": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-hidden][1] state; a constant indicating whether the element is exposed to an accessibility API.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-hidden" + }, + "ariaLabel": { + "$ref": "#/definitions/ChannelValue", + "description": "The [aria-label][1]; a channel specifying short textual labels representing the value in the accessibility tree.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-label" + }, + "clip": { + "anyOf": [ + { + "const": "frame", + "type": "string" + }, + { + "const": "sphere", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to clip the mark; one of:\n\n- *frame* or true - clip to the plot’s frame (inner area)\n- *sphere* - clip to the projected sphere (*e.g.*, front hemisphere)\n- null or false - do not clip\n\nThe *sphere* clip option requires a geographic projection." + }, + "data": { + "$ref": "#/definitions/PlotMarkData", + "description": "The data source for the mark." + }, + "dx": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The horizontal offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "dy": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The vertical offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "facet": { + "anyOf": [ + { + "const": "auto", + "type": "string" + }, + { + "const": "include", + "type": "string" + }, + { + "const": "exclude", + "type": "string" + }, + { + "const": "super", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to enable or disable faceting; one of:\n\n- *auto* (default) - automatically determine if this mark should be faceted\n- *include* (or true) - draw the subset of the mark’s data in the current facet\n- *exclude* - draw the subset of the mark’s data *not* in the current facet\n- *super* - draw this mark in a single frame that covers all facets\n- null (or false) - repeat this mark’s data across all facets (*i.e.*, no faceting)\n\nWhen a mark uses *super* faceting, it is not allowed to use position scales (*x*, *y*, *fx*, or *fy*); *super* faceting is intended for decorations, such as labels and legends.\n\nWhen top-level faceting is used, the default *auto* setting is equivalent to *include* when the mark data is strictly equal to the top-level facet data; otherwise it is equivalent to null. When the *include* or *exclude* facet mode is chosen, the mark data must be parallel to the top-level facet data: the data must have the same length and order. If the data are not parallel, then the wrong data may be shown in each facet. The default\n*auto* therefore requires strict equality (`===`) for safety, and using the facet data as mark data is recommended when using the *exclude* facet mode. (To construct parallel data safely, consider using [*array*.map][1] on the facet data.)\n\nWhen mark-level faceting is used, the default *auto* setting is equivalent to *include*: the mark will be faceted if either the **fx** or **fy** channel option (or both) is specified. The null or false option will disable faceting, while *exclude* draws the subset of the mark’s data *not* in the current facet.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map" + }, + "facetAnchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "right", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "const": "left", + "type": "string" + }, + { + "const": "top-left", + "type": "string" + }, + { + "const": "top-right", + "type": "string" + }, + { + "const": "bottom-left", + "type": "string" + }, + { + "const": "bottom-right", + "type": "string" + }, + { + "const": "top-empty", + "type": "string" + }, + { + "const": "right-empty", + "type": "string" + }, + { + "const": "bottom-empty", + "type": "string" + }, + { + "const": "left-empty", + "type": "string" + }, + { + "const": "empty", + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to place the mark with respect to facets; one of:\n\n- null (default for most marks) - display the mark in each non-empty facet\n- *top*, *right*, *bottom*, or *left* - display the mark only in facets on the given side\n- *top-empty*, *right-empty*, *bottom-empty*, or *left-empty* (default for axis marks) - display the mark only in facets that have empty space on the given side: either the margin, or an empty facet\n- *empty* - display the mark in empty facets only" + }, + "fill": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill" + }, + "fillOpacity": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill-opacity][1]; a constant number between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill-opacity" + }, + "filter": { + "$ref": "#/definitions/ChannelValue", + "description": "Applies a transform to filter the mark’s index according to the given channel values; only truthy values are retained.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "frameAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The vector’s frame anchor, to default **x** and **y** relative to the frame; a constant representing one of the frame corners (*top-left*,\n*top-right*, *bottom-right*, *bottom-left*), sides (*top*, *right*,\n*bottom*, *left*), or *middle* (default). Has no effect if both **x** and **y** are specified." + }, + "fx": { + "$ref": "#/definitions/ChannelValue", + "description": "The horizontal facet position channel, for mark-level faceting, bound to the *fx* scale." + }, + "fy": { + "$ref": "#/definitions/ChannelValue", + "description": "The vertical facet position channel, for mark-level faceting, bound to the\n*fy* scale." + }, + "href": { + "$ref": "#/definitions/ChannelValue", + "description": "The [href][1]; a channel specifying URLs for clickable links. May be used in conjunction with the **target** option to open links in another window.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/href" + }, + "imageFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A CSS [filter][1]; a constant string used to adjust the rendering of images, such as *blur(5px)*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/filter" + }, + "length": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vector’s length; either an optional channel bound to the *length* scale or a constant number in pixels. Defaults to 12 pixels." + }, + "margin": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four mark margins: **marginTop**,\n**marginRight**, **marginBottom**, and **marginLeft**; typically defaults to 0, except for axis marks." + }, + "marginBottom": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s bottom margin; the minimum distance in pixels between the bottom edges of the inner and outer plot area." + }, + "marginLeft": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s left margin; the minimum distance in pixels between the left edges of the inner and outer plot area." + }, + "marginRight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s right margin; the minimum distance in pixels between the right edges of the mark’s inner and outer plot area." + }, + "marginTop": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s top margin; the minimum distance in pixels between the top edges of the inner and outer plot area." + }, + "mark": { + "const": "vectorY", + "description": "Like vector, but **y** instead defaults to the identity function and **x** defaults to null, assuming that *data* is an array of numbers [*y₀*, *y₁*,\n*y₂*, …].", + "type": "string" + }, + "mixBlendMode": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [mix-blend-mode][1]; a constant string specifying how to blend content such as *multiply*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode" + }, + "opacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally. For faster rendering, prefer the **strokeOpacity** or **fillOpacity** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/opacity" + }, + "paintOrder": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [paint-order][1]; a constant string specifying the order in which the\n**fill**, **stroke**, and any markers are drawn; defaults to *normal*, which draws the fill, then stroke, then markers; defaults to *stroke* for the text mark to create a “halo” around text to improve legibility.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/paint-order" + }, + "pointerEvents": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [pointer-events][1] property; a constant string such as *none*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/pointer-events" + }, + "r": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The vector shape’s radius, such as half the width of the *arrow*’s head or the *spike*’s base; a constant number in pixels. Defaults to 3.5 pixels." + }, + "reverse": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Applies a transform to reverse the order of the mark’s index, say for reverse input order." + }, + "rotate": { + "$ref": "#/definitions/ChannelValue", + "description": "The vector’s orientation (rotation angle); either a constant number in degrees clockwise, or an optional channel (with no associated scale). Defaults to 0 degrees with the vector pointing up." + }, + "select": { + "$ref": "#/definitions/SelectFilter", + "description": "Applies a filter transform after data is loaded to highlight selected values only. For example, `first` and `last` select the first or last values of series only (using the *z* channel to separate series). Meanwhile, `nearestX` and `nearestY` select the point nearest to the pointer along the *x* or *y* channel dimension. Unlike Mosaic selections, a mark level *select* is internal to the mark only, and does not populate a param or selection value to be shared across clients.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "shape": { + "anyOf": [ + { + "$ref": "#/definitions/VectorShape" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The shape of the vector; a constant. Defaults to *arrow*." + }, + "shapeRendering": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [shape-rendering][1]; a constant string such as *crispEdges*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/shape-rendering" + }, + "sort": { + "anyOf": [ + { + "$ref": "#/definitions/SortOrder" + }, + { + "$ref": "#/definitions/ChannelDomainSort" + } + ], + "description": "Either applies a transform to sort the mark’s index by the specified channel values, or imputes ordinal scale domains from this mark’s channels.\n\nWhen imputing ordinal scale domains from channel values, the **sort** option is an object whose keys are ordinal scale names such as *x* or *fx*, and whose values are channel names such as *y*, *y1*, or *y2*. For example, to impute the *y* scale’s domain from the associated *x* channel values in ascending order:\n\n```js sort: {y: \"x\"} ```\n\nFor different sort options for different scales, replace the channel name with a *value* object and per-scale options:\n\n```js sort: {y: {value: \"-x\"}} ```\n\nWhen sorting the mark’s index, the **sort** option is instead one of:\n\n- a channel value definition for sorting given values in ascending order\n- a {value, order} object for sorting given values\n- a {channel, order} object for sorting the named channel’s values" + }, + "stroke": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke" + }, + "strokeDasharray": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dasharray][1]; a constant number indicating the length in pixels of alternating dashes and gaps, or a constant string of numbers separated by spaces or commas (_e.g._, *10 2* for dashes of 10 pixels separated by gaps of 2 pixels), or *none* (the default) for no dashing\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dasharray" + }, + "strokeDashoffset": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dashoffset][1]; a constant indicating the offset in pixels of the first dash along the stroke; defaults to zero.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dashoffset" + }, + "strokeLinecap": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linecap][1]; a constant specifying how to cap stroked paths, such as *butt*, *round*, or *square*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linecap" + }, + "strokeLinejoin": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linejoin][1]; a constant specifying how to join stroked paths, such as *bevel*, *miter*, *miter-clip*, or *round*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linejoin" + }, + "strokeMiterlimit": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-miterlimit][1]; a constant number specifying how to limit the length of *miter* joins on stroked paths.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-miterlimit" + }, + "strokeOpacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-opacity" + }, + "strokeWidth": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-width][1]; a constant number in pixels, or a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-width" + }, + "target": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [target][1]; a constant string specifying the target window (_e.g._,\n*_blank*) for clickable links; used in conjunction with the **href** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/target" + }, + "tip": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/TipPointer" + }, + { + "properties": { + "anchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The tip anchor specifies how to orient the tip box relative to its anchor position; it refers to the part of the tip box that is attached to the anchor point. For example, the *top-left* anchor places the top-left corner of tip box near the anchor position, hence placing the tip box below and to the right of the anchor position." + }, + "fontFamily": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font-family][1]; a constant; defaults to the plot’s font family, which is typically [*system-ui*][2].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-family [2]: https://drafts.csswg.org/css-fonts-4/#valdef-font-family-system-ui" + }, + "fontSize": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font size][1] in pixels; either a constant or a channel; defaults to the plot’s font size, which is typically 10. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-size" + }, + "fontStyle": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font style][1]; a constant; defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-style" + }, + "fontVariant": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font variant][1]; a constant; if the **text** channel contains numbers or dates, defaults to *tabular-nums* to facilitate comparing numbers; otherwise defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant" + }, + "fontWeight": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font weight][1]; a constant; defaults to the plot’s font weight, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight" + }, + "format": { + "additionalProperties": false, + "description": "How channel values are formatted for display. If a format is a string, it is interpreted as a (UTC) time format for temporal channels, and otherwise a number format.", + "properties": { + "ariaLabel": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fill": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fillOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fontSize": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fx": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fy": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "geometry": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "height": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "href": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "length": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "opacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "path": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "r": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "rotate": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "src": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "stroke": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeWidth": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "symbol": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "text": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "title": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "weight": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "width": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "z": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + } + }, + "type": "object" + }, + "frameAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The frame anchor specifies defaults for **x** and **y** based on the plot’s frame; it may be one of the four sides (*top*, *right*, *bottom*, *left*), one of the four corners (*top-left*, *top-right*, *bottom-right*,\n*bottom-left*), or the *middle* of the frame. For example, for tips distributed horizontally at the top of the frame:\n\n```js Plot.tip(data, {x: \"date\", frameAnchor: \"top\"}) ```" + }, + "lineHeight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line height in ems; defaults to 1. The line height affects the (typically vertical) separation between adjacent baselines of text, as well as the separation between the text and its anchor point." + }, + "lineWidth": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line width in ems (e.g., 10 for about 20 characters); defaults to infinity, disabling wrapping and clipping.\n\nIf **textOverflow** is null, lines will be wrapped at the specified length. If a line is split at a soft hyphen (\\xad), a hyphen (-) will be displayed at the end of the line. If **textOverflow** is not null, lines will be clipped according to the given strategy." + }, + "monospace": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, changes the default **fontFamily** to *monospace*, and uses simplified monospaced text metrics calculations." + }, + "pathFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The image filter for the tip’s box; defaults to a drop shadow." + }, + "pointer": { + "$ref": "#/definitions/TipPointer" + }, + "pointerSize": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The size of the tip’s pointer in pixels; defaults to 12." + }, + "preferredAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If an explicit tip anchor is not specified, an anchor is chosen automatically such that the tip fits within the plot’s frame; if the preferred anchor fits, it is chosen." + }, + "textAnchor": { + "anyOf": [ + { + "const": "start", + "type": "string" + }, + { + "const": "middle", + "type": "string" + }, + { + "const": "end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [text anchor][1] controls how text is aligned (typically horizontally) relative to its anchor point; it is one of *start*, *end*, or *middle*. If the frame anchor is *left*, *top-left*, or *bottom-left*, the default text anchor is *start*; if the frame anchor is *right*, *top-right*, or\n*bottom-right*, the default is *end*; otherwise it is *middle*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/text-anchor" + }, + "textOverflow": { + "anyOf": [ + { + "type": "null" + }, + { + "const": "clip", + "type": "string" + }, + { + "const": "ellipsis", + "type": "string" + }, + { + "const": "clip-start", + "type": "string" + }, + { + "const": "clip-end", + "type": "string" + }, + { + "const": "ellipsis-start", + "type": "string" + }, + { + "const": "ellipsis-middle", + "type": "string" + }, + { + "const": "ellipsis-end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How truncate (or wrap) lines of text longer than the given **lineWidth**; one of:\n\n- null (default) - preserve overflowing characters (and wrap if needed)\n- *clip* or *clip-end* - remove characters from the end\n- *clip-start* - remove characters from the start\n- *ellipsis* or *ellipsis-end* - replace characters from the end with an ellipsis (…)\n- *ellipsis-start* - replace characters from the start with an ellipsis (…)\n- *ellipsis-middle* - replace characters from the middle with an ellipsis (…)\n\nIf no **title** was specified, if text requires truncation, a title containing the non-truncated text will be implicitly added." + }, + "textPadding": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The padding around the text in pixels; defaults to 8." + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + } + }, + "type": "object" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to generate a tooltip for this mark, and any tip options." + }, + "title": { + "$ref": "#/definitions/ChannelValue", + "description": "The title; a channel specifying accessible, short textual descriptions as strings (possibly with newlines). If the tip option is specified, the title will be displayed with an interactive tooltip instead of using the SVG [title element][1].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/title" + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position of the vector’s anchor point; an optional channel bound to the *x* scale. Default depends on the **frameAnchor**." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position of the vector’s anchor point; an optional channel bound to the *y* scale. Default depends on the **frameAnchor**." + } + }, + "required": [ + "data", + "mark" + ], + "type": "object" + }, + "Voronoi": { + "additionalProperties": false, + "description": "The voronoi mark.", + "properties": { + "ariaDescription": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-description][1]; a constant textual description.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-description" + }, + "ariaHidden": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-hidden][1] state; a constant indicating whether the element is exposed to an accessibility API.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-hidden" + }, + "ariaLabel": { + "$ref": "#/definitions/ChannelValue", + "description": "The [aria-label][1]; a channel specifying short textual labels representing the value in the accessibility tree.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-label" + }, + "clip": { + "anyOf": [ + { + "const": "frame", + "type": "string" + }, + { + "const": "sphere", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to clip the mark; one of:\n\n- *frame* or true - clip to the plot’s frame (inner area)\n- *sphere* - clip to the projected sphere (*e.g.*, front hemisphere)\n- null or false - do not clip\n\nThe *sphere* clip option requires a geographic projection." + }, + "curve": { + "anyOf": [ + { + "$ref": "#/definitions/Curve" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The curve (interpolation) method for connecting adjacent points. One of:\n\n- *basis* - a cubic basis spline (repeating the end points)\n- *basis-open* - an open cubic basis spline\n- *basis-closed* - a closed cubic basis spline\n- *bump-x* - a Bézier curve with horizontal tangents\n- *bump-y* - a Bézier curve with vertical tangents\n- *bundle* - a straightened cubic basis spline (suitable for lines only, not areas)\n- *cardinal* - a cubic cardinal spline (with one-sided differences at the ends)\n- *cardinal-open* - an open cubic cardinal spline\n- *cardinal-closed* - an closed cubic cardinal spline\n- *catmull-rom* - a cubic Catmull–Rom spline (with one-sided differences at the ends)\n- *catmull-rom-open* - an open cubic Catmull–Rom spline\n- *catmull-rom-closed* - a closed cubic Catmull–Rom spline\n- *linear* - a piecewise linear curve (*i.e.*, straight line segments)\n- *linear-closed* - a closed piecewise linear curve (*i.e.*, straight line segments)\n- *monotone-x* - a cubic spline that preserves monotonicity in *x*\n- *monotone-y* - a cubic spline that preserves monotonicity in *y*\n- *natural* - a natural cubic spline\n- *step* - a piecewise constant function where *y* changes at the midpoint of *x*\n- *step-after* - a piecewise constant function where *y* changes after *x*\n- *step-before* - a piecewise constant function where *x* changes after *y*" + }, + "data": { + "$ref": "#/definitions/PlotMarkData", + "description": "The data source for the mark." + }, + "dx": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The horizontal offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "dy": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The vertical offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "facet": { + "anyOf": [ + { + "const": "auto", + "type": "string" + }, + { + "const": "include", + "type": "string" + }, + { + "const": "exclude", + "type": "string" + }, + { + "const": "super", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to enable or disable faceting; one of:\n\n- *auto* (default) - automatically determine if this mark should be faceted\n- *include* (or true) - draw the subset of the mark’s data in the current facet\n- *exclude* - draw the subset of the mark’s data *not* in the current facet\n- *super* - draw this mark in a single frame that covers all facets\n- null (or false) - repeat this mark’s data across all facets (*i.e.*, no faceting)\n\nWhen a mark uses *super* faceting, it is not allowed to use position scales (*x*, *y*, *fx*, or *fy*); *super* faceting is intended for decorations, such as labels and legends.\n\nWhen top-level faceting is used, the default *auto* setting is equivalent to *include* when the mark data is strictly equal to the top-level facet data; otherwise it is equivalent to null. When the *include* or *exclude* facet mode is chosen, the mark data must be parallel to the top-level facet data: the data must have the same length and order. If the data are not parallel, then the wrong data may be shown in each facet. The default\n*auto* therefore requires strict equality (`===`) for safety, and using the facet data as mark data is recommended when using the *exclude* facet mode. (To construct parallel data safely, consider using [*array*.map][1] on the facet data.)\n\nWhen mark-level faceting is used, the default *auto* setting is equivalent to *include*: the mark will be faceted if either the **fx** or **fy** channel option (or both) is specified. The null or false option will disable faceting, while *exclude* draws the subset of the mark’s data *not* in the current facet.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map" + }, + "facetAnchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "right", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "const": "left", + "type": "string" + }, + { + "const": "top-left", + "type": "string" + }, + { + "const": "top-right", + "type": "string" + }, + { + "const": "bottom-left", + "type": "string" + }, + { + "const": "bottom-right", + "type": "string" + }, + { + "const": "top-empty", + "type": "string" + }, + { + "const": "right-empty", + "type": "string" + }, + { + "const": "bottom-empty", + "type": "string" + }, + { + "const": "left-empty", + "type": "string" + }, + { + "const": "empty", + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to place the mark with respect to facets; one of:\n\n- null (default for most marks) - display the mark in each non-empty facet\n- *top*, *right*, *bottom*, or *left* - display the mark only in facets on the given side\n- *top-empty*, *right-empty*, *bottom-empty*, or *left-empty* (default for axis marks) - display the mark only in facets that have empty space on the given side: either the margin, or an empty facet\n- *empty* - display the mark in empty facets only" + }, + "fill": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill" + }, + "fillOpacity": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill-opacity][1]; a constant number between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill-opacity" + }, + "filter": { + "$ref": "#/definitions/ChannelValue", + "description": "Applies a transform to filter the mark’s index according to the given channel values; only truthy values are retained.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "fx": { + "$ref": "#/definitions/ChannelValue", + "description": "The horizontal facet position channel, for mark-level faceting, bound to the *fx* scale." + }, + "fy": { + "$ref": "#/definitions/ChannelValue", + "description": "The vertical facet position channel, for mark-level faceting, bound to the\n*fy* scale." + }, + "href": { + "$ref": "#/definitions/ChannelValue", + "description": "The [href][1]; a channel specifying URLs for clickable links. May be used in conjunction with the **target** option to open links in another window.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/href" + }, + "imageFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A CSS [filter][1]; a constant string used to adjust the rendering of images, such as *blur(5px)*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/filter" + }, + "margin": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four mark margins: **marginTop**,\n**marginRight**, **marginBottom**, and **marginLeft**; typically defaults to 0, except for axis marks." + }, + "marginBottom": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s bottom margin; the minimum distance in pixels between the bottom edges of the inner and outer plot area." + }, + "marginLeft": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s left margin; the minimum distance in pixels between the left edges of the inner and outer plot area." + }, + "marginRight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s right margin; the minimum distance in pixels between the right edges of the mark’s inner and outer plot area." + }, + "marginTop": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s top margin; the minimum distance in pixels between the top edges of the inner and outer plot area." + }, + "mark": { + "const": "voronoi", + "description": "A mark that draws polygons for each cell of the Voronoi tesselation of the points given by the **x** and **y** channels.\n\nIf **z** is specified, the input points are grouped by *z*, producing a separate Voronoi tesselation for each group.", + "type": "string" + }, + "marker": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for markerStart, markerMid, and markerEnd; one of:\n\n- a marker name such as *arrow* or *circle*\n- *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*" + }, + "markerEnd": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The marker for the ending point of a line segment; one of:\n\n- a marker name such as *arrow* or *circle*\n* *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*" + }, + "markerMid": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The marker for any middle (interior) points of a line segment. If the line segment only has a start and end point, this option has no effect. One of:\n\n- a marker name such as *arrow* or *circle*\n* *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*\n* a function - a custom marker function; see below" + }, + "markerStart": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The marker for the starting point of a line segment; one of:\n\n- a marker name such as *arrow* or *circle*\n* *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*" + }, + "mixBlendMode": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [mix-blend-mode][1]; a constant string specifying how to blend content such as *multiply*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode" + }, + "opacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally. For faster rendering, prefer the **strokeOpacity** or **fillOpacity** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/opacity" + }, + "paintOrder": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [paint-order][1]; a constant string specifying the order in which the\n**fill**, **stroke**, and any markers are drawn; defaults to *normal*, which draws the fill, then stroke, then markers; defaults to *stroke* for the text mark to create a “halo” around text to improve legibility.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/paint-order" + }, + "pointerEvents": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [pointer-events][1] property; a constant string such as *none*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/pointer-events" + }, + "reverse": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Applies a transform to reverse the order of the mark’s index, say for reverse input order." + }, + "select": { + "$ref": "#/definitions/SelectFilter", + "description": "Applies a filter transform after data is loaded to highlight selected values only. For example, `first` and `last` select the first or last values of series only (using the *z* channel to separate series). Meanwhile, `nearestX` and `nearestY` select the point nearest to the pointer along the *x* or *y* channel dimension. Unlike Mosaic selections, a mark level *select* is internal to the mark only, and does not populate a param or selection value to be shared across clients.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "shapeRendering": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [shape-rendering][1]; a constant string such as *crispEdges*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/shape-rendering" + }, + "sort": { + "anyOf": [ + { + "$ref": "#/definitions/SortOrder" + }, + { + "$ref": "#/definitions/ChannelDomainSort" + } + ], + "description": "Either applies a transform to sort the mark’s index by the specified channel values, or imputes ordinal scale domains from this mark’s channels.\n\nWhen imputing ordinal scale domains from channel values, the **sort** option is an object whose keys are ordinal scale names such as *x* or *fx*, and whose values are channel names such as *y*, *y1*, or *y2*. For example, to impute the *y* scale’s domain from the associated *x* channel values in ascending order:\n\n```js sort: {y: \"x\"} ```\n\nFor different sort options for different scales, replace the channel name with a *value* object and per-scale options:\n\n```js sort: {y: {value: \"-x\"}} ```\n\nWhen sorting the mark’s index, the **sort** option is instead one of:\n\n- a channel value definition for sorting given values in ascending order\n- a {value, order} object for sorting given values\n- a {channel, order} object for sorting the named channel’s values" + }, + "stroke": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke" + }, + "strokeDasharray": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dasharray][1]; a constant number indicating the length in pixels of alternating dashes and gaps, or a constant string of numbers separated by spaces or commas (_e.g._, *10 2* for dashes of 10 pixels separated by gaps of 2 pixels), or *none* (the default) for no dashing\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dasharray" + }, + "strokeDashoffset": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dashoffset][1]; a constant indicating the offset in pixels of the first dash along the stroke; defaults to zero.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dashoffset" + }, + "strokeLinecap": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linecap][1]; a constant specifying how to cap stroked paths, such as *butt*, *round*, or *square*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linecap" + }, + "strokeLinejoin": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linejoin][1]; a constant specifying how to join stroked paths, such as *bevel*, *miter*, *miter-clip*, or *round*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linejoin" + }, + "strokeMiterlimit": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-miterlimit][1]; a constant number specifying how to limit the length of *miter* joins on stroked paths.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-miterlimit" + }, + "strokeOpacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-opacity" + }, + "strokeWidth": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-width][1]; a constant number in pixels, or a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-width" + }, + "target": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [target][1]; a constant string specifying the target window (_e.g._,\n*_blank*) for clickable links; used in conjunction with the **href** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/target" + }, + "tension": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The tension option only has an effect on bundle, cardinal and Catmull–Rom splines (*bundle*, *cardinal*, *cardinal-open*, *cardinal-closed*,\n*catmull-rom*, *catmull-rom-open*, and *catmull-rom-closed*). For bundle splines, it corresponds to [beta][1]; for cardinal splines, [tension][2]; for Catmull–Rom splines, [alpha][3].\n\n[1]: https://d3js.org/d3-shape/curve#curveBundle_beta [2]: https://d3js.org/d3-shape/curve#curveCardinal_tension [3]: https://d3js.org/d3-shape/curve#curveCatmullRom_alpha" + }, + "tip": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/TipPointer" + }, + { + "properties": { + "anchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The tip anchor specifies how to orient the tip box relative to its anchor position; it refers to the part of the tip box that is attached to the anchor point. For example, the *top-left* anchor places the top-left corner of tip box near the anchor position, hence placing the tip box below and to the right of the anchor position." + }, + "fontFamily": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font-family][1]; a constant; defaults to the plot’s font family, which is typically [*system-ui*][2].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-family [2]: https://drafts.csswg.org/css-fonts-4/#valdef-font-family-system-ui" + }, + "fontSize": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font size][1] in pixels; either a constant or a channel; defaults to the plot’s font size, which is typically 10. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-size" + }, + "fontStyle": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font style][1]; a constant; defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-style" + }, + "fontVariant": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font variant][1]; a constant; if the **text** channel contains numbers or dates, defaults to *tabular-nums* to facilitate comparing numbers; otherwise defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant" + }, + "fontWeight": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font weight][1]; a constant; defaults to the plot’s font weight, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight" + }, + "format": { + "additionalProperties": false, + "description": "How channel values are formatted for display. If a format is a string, it is interpreted as a (UTC) time format for temporal channels, and otherwise a number format.", + "properties": { + "ariaLabel": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fill": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fillOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fontSize": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fx": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fy": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "geometry": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "height": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "href": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "length": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "opacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "path": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "r": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "rotate": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "src": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "stroke": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeWidth": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "symbol": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "text": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "title": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "weight": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "width": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "z": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + } + }, + "type": "object" + }, + "frameAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The frame anchor specifies defaults for **x** and **y** based on the plot’s frame; it may be one of the four sides (*top*, *right*, *bottom*, *left*), one of the four corners (*top-left*, *top-right*, *bottom-right*,\n*bottom-left*), or the *middle* of the frame. For example, for tips distributed horizontally at the top of the frame:\n\n```js Plot.tip(data, {x: \"date\", frameAnchor: \"top\"}) ```" + }, + "lineHeight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line height in ems; defaults to 1. The line height affects the (typically vertical) separation between adjacent baselines of text, as well as the separation between the text and its anchor point." + }, + "lineWidth": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line width in ems (e.g., 10 for about 20 characters); defaults to infinity, disabling wrapping and clipping.\n\nIf **textOverflow** is null, lines will be wrapped at the specified length. If a line is split at a soft hyphen (\\xad), a hyphen (-) will be displayed at the end of the line. If **textOverflow** is not null, lines will be clipped according to the given strategy." + }, + "monospace": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, changes the default **fontFamily** to *monospace*, and uses simplified monospaced text metrics calculations." + }, + "pathFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The image filter for the tip’s box; defaults to a drop shadow." + }, + "pointer": { + "$ref": "#/definitions/TipPointer" + }, + "pointerSize": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The size of the tip’s pointer in pixels; defaults to 12." + }, + "preferredAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If an explicit tip anchor is not specified, an anchor is chosen automatically such that the tip fits within the plot’s frame; if the preferred anchor fits, it is chosen." + }, + "textAnchor": { + "anyOf": [ + { + "const": "start", + "type": "string" + }, + { + "const": "middle", + "type": "string" + }, + { + "const": "end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [text anchor][1] controls how text is aligned (typically horizontally) relative to its anchor point; it is one of *start*, *end*, or *middle*. If the frame anchor is *left*, *top-left*, or *bottom-left*, the default text anchor is *start*; if the frame anchor is *right*, *top-right*, or\n*bottom-right*, the default is *end*; otherwise it is *middle*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/text-anchor" + }, + "textOverflow": { + "anyOf": [ + { + "type": "null" + }, + { + "const": "clip", + "type": "string" + }, + { + "const": "ellipsis", + "type": "string" + }, + { + "const": "clip-start", + "type": "string" + }, + { + "const": "clip-end", + "type": "string" + }, + { + "const": "ellipsis-start", + "type": "string" + }, + { + "const": "ellipsis-middle", + "type": "string" + }, + { + "const": "ellipsis-end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How truncate (or wrap) lines of text longer than the given **lineWidth**; one of:\n\n- null (default) - preserve overflowing characters (and wrap if needed)\n- *clip* or *clip-end* - remove characters from the end\n- *clip-start* - remove characters from the start\n- *ellipsis* or *ellipsis-end* - replace characters from the end with an ellipsis (…)\n- *ellipsis-start* - replace characters from the start with an ellipsis (…)\n- *ellipsis-middle* - replace characters from the middle with an ellipsis (…)\n\nIf no **title** was specified, if text requires truncation, a title containing the non-truncated text will be implicitly added." + }, + "textPadding": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The padding around the text in pixels; defaults to 8." + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + } + }, + "type": "object" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to generate a tooltip for this mark, and any tip options." + }, + "title": { + "$ref": "#/definitions/ChannelValue", + "description": "The title; a channel specifying accessible, short textual descriptions as strings (possibly with newlines). If the tip option is specified, the title will be displayed with an interactive tooltip instead of using the SVG [title element][1].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/title" + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel, typically bound to the *x* scale." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel, typically bound to the *y* scale." + }, + "z": { + "$ref": "#/definitions/ChannelValue", + "description": "An optional ordinal channel for grouping to produce multiple (possibly overlapping) triangulations." + } + }, + "required": [ + "data", + "mark" + ], + "type": "object" + }, + "VoronoiMesh": { + "additionalProperties": false, + "description": "The voronoiMesh mark.", + "properties": { + "ariaDescription": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-description][1]; a constant textual description.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-description" + }, + "ariaHidden": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [aria-hidden][1] state; a constant indicating whether the element is exposed to an accessibility API.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-hidden" + }, + "ariaLabel": { + "$ref": "#/definitions/ChannelValue", + "description": "The [aria-label][1]; a channel specifying short textual labels representing the value in the accessibility tree.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-label" + }, + "clip": { + "anyOf": [ + { + "const": "frame", + "type": "string" + }, + { + "const": "sphere", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to clip the mark; one of:\n\n- *frame* or true - clip to the plot’s frame (inner area)\n- *sphere* - clip to the projected sphere (*e.g.*, front hemisphere)\n- null or false - do not clip\n\nThe *sphere* clip option requires a geographic projection." + }, + "curve": { + "anyOf": [ + { + "$ref": "#/definitions/Curve" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The curve (interpolation) method for connecting adjacent points. One of:\n\n- *basis* - a cubic basis spline (repeating the end points)\n- *basis-open* - an open cubic basis spline\n- *basis-closed* - a closed cubic basis spline\n- *bump-x* - a Bézier curve with horizontal tangents\n- *bump-y* - a Bézier curve with vertical tangents\n- *bundle* - a straightened cubic basis spline (suitable for lines only, not areas)\n- *cardinal* - a cubic cardinal spline (with one-sided differences at the ends)\n- *cardinal-open* - an open cubic cardinal spline\n- *cardinal-closed* - an closed cubic cardinal spline\n- *catmull-rom* - a cubic Catmull–Rom spline (with one-sided differences at the ends)\n- *catmull-rom-open* - an open cubic Catmull–Rom spline\n- *catmull-rom-closed* - a closed cubic Catmull–Rom spline\n- *linear* - a piecewise linear curve (*i.e.*, straight line segments)\n- *linear-closed* - a closed piecewise linear curve (*i.e.*, straight line segments)\n- *monotone-x* - a cubic spline that preserves monotonicity in *x*\n- *monotone-y* - a cubic spline that preserves monotonicity in *y*\n- *natural* - a natural cubic spline\n- *step* - a piecewise constant function where *y* changes at the midpoint of *x*\n- *step-after* - a piecewise constant function where *y* changes after *x*\n- *step-before* - a piecewise constant function where *x* changes after *y*" + }, + "data": { + "$ref": "#/definitions/PlotMarkData", + "description": "The data source for the mark." + }, + "dx": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The horizontal offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "dy": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The vertical offset in pixels; a constant option. On low-density screens, an additional 0.5px offset may be applied for crisp edges." + }, + "facet": { + "anyOf": [ + { + "const": "auto", + "type": "string" + }, + { + "const": "include", + "type": "string" + }, + { + "const": "exclude", + "type": "string" + }, + { + "const": "super", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to enable or disable faceting; one of:\n\n- *auto* (default) - automatically determine if this mark should be faceted\n- *include* (or true) - draw the subset of the mark’s data in the current facet\n- *exclude* - draw the subset of the mark’s data *not* in the current facet\n- *super* - draw this mark in a single frame that covers all facets\n- null (or false) - repeat this mark’s data across all facets (*i.e.*, no faceting)\n\nWhen a mark uses *super* faceting, it is not allowed to use position scales (*x*, *y*, *fx*, or *fy*); *super* faceting is intended for decorations, such as labels and legends.\n\nWhen top-level faceting is used, the default *auto* setting is equivalent to *include* when the mark data is strictly equal to the top-level facet data; otherwise it is equivalent to null. When the *include* or *exclude* facet mode is chosen, the mark data must be parallel to the top-level facet data: the data must have the same length and order. If the data are not parallel, then the wrong data may be shown in each facet. The default\n*auto* therefore requires strict equality (`===`) for safety, and using the facet data as mark data is recommended when using the *exclude* facet mode. (To construct parallel data safely, consider using [*array*.map][1] on the facet data.)\n\nWhen mark-level faceting is used, the default *auto* setting is equivalent to *include*: the mark will be faceted if either the **fx** or **fy** channel option (or both) is specified. The null or false option will disable faceting, while *exclude* draws the subset of the mark’s data *not* in the current facet.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map" + }, + "facetAnchor": { + "anyOf": [ + { + "const": "top", + "type": "string" + }, + { + "const": "right", + "type": "string" + }, + { + "const": "bottom", + "type": "string" + }, + { + "const": "left", + "type": "string" + }, + { + "const": "top-left", + "type": "string" + }, + { + "const": "top-right", + "type": "string" + }, + { + "const": "bottom-left", + "type": "string" + }, + { + "const": "bottom-right", + "type": "string" + }, + { + "const": "top-empty", + "type": "string" + }, + { + "const": "right-empty", + "type": "string" + }, + { + "const": "bottom-empty", + "type": "string" + }, + { + "const": "left-empty", + "type": "string" + }, + { + "const": "empty", + "type": "string" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How to place the mark with respect to facets; one of:\n\n- null (default for most marks) - display the mark in each non-empty facet\n- *top*, *right*, *bottom*, or *left* - display the mark only in facets on the given side\n- *top-empty*, *right-empty*, *bottom-empty*, or *left-empty* (default for axis marks) - display the mark only in facets that have empty space on the given side: either the margin, or an empty facet\n- *empty* - display the mark in empty facets only" + }, + "fill": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill" + }, + "fillOpacity": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [fill-opacity][1]; a constant number between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/fill-opacity" + }, + "filter": { + "$ref": "#/definitions/ChannelValue", + "description": "Applies a transform to filter the mark’s index according to the given channel values; only truthy values are retained.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "fx": { + "$ref": "#/definitions/ChannelValue", + "description": "The horizontal facet position channel, for mark-level faceting, bound to the *fx* scale." + }, + "fy": { + "$ref": "#/definitions/ChannelValue", + "description": "The vertical facet position channel, for mark-level faceting, bound to the\n*fy* scale." + }, + "href": { + "$ref": "#/definitions/ChannelValue", + "description": "The [href][1]; a channel specifying URLs for clickable links. May be used in conjunction with the **target** option to open links in another window.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/href" + }, + "imageFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "A CSS [filter][1]; a constant string used to adjust the rendering of images, such as *blur(5px)*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/filter" + }, + "margin": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for all four mark margins: **marginTop**,\n**marginRight**, **marginBottom**, and **marginLeft**; typically defaults to 0, except for axis marks." + }, + "marginBottom": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s bottom margin; the minimum distance in pixels between the bottom edges of the inner and outer plot area." + }, + "marginLeft": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s left margin; the minimum distance in pixels between the left edges of the inner and outer plot area." + }, + "marginRight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s right margin; the minimum distance in pixels between the right edges of the mark’s inner and outer plot area." + }, + "marginTop": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The mark’s top margin; the minimum distance in pixels between the top edges of the inner and outer plot area." + }, + "mark": { + "const": "voronoiMesh", + "description": "A mark that draws a mesh for the cell boundaries of the Voronoi tesselation of the points given by the **x** and **y** channels. The\n**stroke** option defaults to _currentColor_, and the **strokeOpacity** defaults to 0.2. The **fill** option is not supported. When an aesthetic channel is specified (such as **stroke** or **strokeWidth**), the mesh inherits the corresponding channel value from one of its constituent points arbitrarily.\n\nIf **z** is specified, the input points are grouped by *z*, producing a separate Voronoi tesselation for each group.", + "type": "string" + }, + "marker": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Shorthand to set the same default for markerStart, markerMid, and markerEnd; one of:\n\n- a marker name such as *arrow* or *circle*\n- *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*" + }, + "markerEnd": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The marker for the ending point of a line segment; one of:\n\n- a marker name such as *arrow* or *circle*\n* *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*" + }, + "markerMid": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The marker for any middle (interior) points of a line segment. If the line segment only has a start and end point, this option has no effect. One of:\n\n- a marker name such as *arrow* or *circle*\n* *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*\n* a function - a custom marker function; see below" + }, + "markerStart": { + "anyOf": [ + { + "$ref": "#/definitions/MarkerName" + }, + { + "const": "none", + "type": "string" + }, + { + "type": "boolean" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The marker for the starting point of a line segment; one of:\n\n- a marker name such as *arrow* or *circle*\n* *none* (default) - no marker\n* true - alias for *circle-fill*\n* false or null - alias for *none*" + }, + "mixBlendMode": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [mix-blend-mode][1]; a constant string specifying how to blend content such as *multiply*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/mix-blend-mode" + }, + "opacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally. For faster rendering, prefer the **strokeOpacity** or **fillOpacity** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/opacity" + }, + "paintOrder": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [paint-order][1]; a constant string specifying the order in which the\n**fill**, **stroke**, and any markers are drawn; defaults to *normal*, which draws the fill, then stroke, then markers; defaults to *stroke* for the text mark to create a “halo” around text to improve legibility.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/paint-order" + }, + "pointerEvents": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [pointer-events][1] property; a constant string such as *none*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/pointer-events" + }, + "reverse": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Applies a transform to reverse the order of the mark’s index, say for reverse input order." + }, + "select": { + "$ref": "#/definitions/SelectFilter", + "description": "Applies a filter transform after data is loaded to highlight selected values only. For example, `first` and `last` select the first or last values of series only (using the *z* channel to separate series). Meanwhile, `nearestX` and `nearestY` select the point nearest to the pointer along the *x* or *y* channel dimension. Unlike Mosaic selections, a mark level *select* is internal to the mark only, and does not populate a param or selection value to be shared across clients.\n\nNote that filtering only affects the rendered mark index, not the associated channel values, and has no effect on imputed scale domains." + }, + "shapeRendering": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [shape-rendering][1]; a constant string such as *crispEdges*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/shape-rendering" + }, + "sort": { + "anyOf": [ + { + "$ref": "#/definitions/SortOrder" + }, + { + "$ref": "#/definitions/ChannelDomainSort" + } + ], + "description": "Either applies a transform to sort the mark’s index by the specified channel values, or imputes ordinal scale domains from this mark’s channels.\n\nWhen imputing ordinal scale domains from channel values, the **sort** option is an object whose keys are ordinal scale names such as *x* or *fx*, and whose values are channel names such as *y*, *y1*, or *y2*. For example, to impute the *y* scale’s domain from the associated *x* channel values in ascending order:\n\n```js sort: {y: \"x\"} ```\n\nFor different sort options for different scales, replace the channel name with a *value* object and per-scale options:\n\n```js sort: {y: {value: \"-x\"}} ```\n\nWhen sorting the mark’s index, the **sort** option is instead one of:\n\n- a channel value definition for sorting given values in ascending order\n- a {value, order} object for sorting given values\n- a {channel, order} object for sorting the named channel’s values" + }, + "stroke": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValueSpec" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke][1]; a constant CSS color string, or a channel typically bound to the *color* scale. If all channel values are valid CSS colors, by default the channel will not be bound to the *color* scale, interpreting the colors literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke" + }, + "strokeDasharray": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dasharray][1]; a constant number indicating the length in pixels of alternating dashes and gaps, or a constant string of numbers separated by spaces or commas (_e.g._, *10 2* for dashes of 10 pixels separated by gaps of 2 pixels), or *none* (the default) for no dashing\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dasharray" + }, + "strokeDashoffset": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-dashoffset][1]; a constant indicating the offset in pixels of the first dash along the stroke; defaults to zero.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-dashoffset" + }, + "strokeLinecap": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linecap][1]; a constant specifying how to cap stroked paths, such as *butt*, *round*, or *square*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linecap" + }, + "strokeLinejoin": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-linejoin][1]; a constant specifying how to join stroked paths, such as *bevel*, *miter*, *miter-clip*, or *round*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-linejoin" + }, + "strokeMiterlimit": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [stroke-miterlimit][1]; a constant number specifying how to limit the length of *miter* joins on stroked paths.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-miterlimit" + }, + "strokeOpacity": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-opacity][1]; a constant between 0 and 1, or a channel typically bound to the *opacity* scale. If all channel values are numbers in [0, 1], by default the channel will not be bound to the *opacity* scale, interpreting the opacities literally.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-opacity" + }, + "strokeWidth": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The [stroke-width][1]; a constant number in pixels, or a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/stroke-width" + }, + "target": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [target][1]; a constant string specifying the target window (_e.g._,\n*_blank*) for clickable links; used in conjunction with the **href** option.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/target" + }, + "tension": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The tension option only has an effect on bundle, cardinal and Catmull–Rom splines (*bundle*, *cardinal*, *cardinal-open*, *cardinal-closed*,\n*catmull-rom*, *catmull-rom-open*, and *catmull-rom-closed*). For bundle splines, it corresponds to [beta][1]; for cardinal splines, [tension][2]; for Catmull–Rom splines, [alpha][3].\n\n[1]: https://d3js.org/d3-shape/curve#curveBundle_beta [2]: https://d3js.org/d3-shape/curve#curveCardinal_tension [3]: https://d3js.org/d3-shape/curve#curveCatmullRom_alpha" + }, + "tip": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/TipPointer" + }, + { + "properties": { + "anchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The tip anchor specifies how to orient the tip box relative to its anchor position; it refers to the part of the tip box that is attached to the anchor point. For example, the *top-left* anchor places the top-left corner of tip box near the anchor position, hence placing the tip box below and to the right of the anchor position." + }, + "fontFamily": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font-family][1]; a constant; defaults to the plot’s font family, which is typically [*system-ui*][2].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-family [2]: https://drafts.csswg.org/css-fonts-4/#valdef-font-family-system-ui" + }, + "fontSize": { + "anyOf": [ + { + "$ref": "#/definitions/ChannelValue" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font size][1] in pixels; either a constant or a channel; defaults to the plot’s font size, which is typically 10. When a number, it is interpreted as a constant; otherwise it is interpreted as a channel.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-size" + }, + "fontStyle": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font style][1]; a constant; defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-style" + }, + "fontVariant": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font variant][1]; a constant; if the **text** channel contains numbers or dates, defaults to *tabular-nums* to facilitate comparing numbers; otherwise defaults to the plot’s font style, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-variant" + }, + "fontWeight": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [font weight][1]; a constant; defaults to the plot’s font weight, which is typically *normal*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/CSS/font-weight" + }, + "format": { + "additionalProperties": false, + "description": "How channel values are formatted for display. If a format is a string, it is interpreted as a (UTC) time format for temporal channels, and otherwise a number format.", + "properties": { + "ariaLabel": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fill": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fillOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fontSize": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fx": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "fy": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "geometry": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "height": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "href": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "length": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "opacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "path": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "r": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "rotate": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "src": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "stroke": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeOpacity": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "strokeWidth": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "symbol": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "text": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "title": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "weight": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "width": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "x2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y1": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "y2": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + }, + "z": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ] + } + }, + "type": "object" + }, + "frameAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The frame anchor specifies defaults for **x** and **y** based on the plot’s frame; it may be one of the four sides (*top*, *right*, *bottom*, *left*), one of the four corners (*top-left*, *top-right*, *bottom-right*,\n*bottom-left*), or the *middle* of the frame. For example, for tips distributed horizontally at the top of the frame:\n\n```js Plot.tip(data, {x: \"date\", frameAnchor: \"top\"}) ```" + }, + "lineHeight": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line height in ems; defaults to 1. The line height affects the (typically vertical) separation between adjacent baselines of text, as well as the separation between the text and its anchor point." + }, + "lineWidth": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The line width in ems (e.g., 10 for about 20 characters); defaults to infinity, disabling wrapping and clipping.\n\nIf **textOverflow** is null, lines will be wrapped at the specified length. If a line is split at a soft hyphen (\\xad), a hyphen (-) will be displayed at the end of the line. If **textOverflow** is not null, lines will be clipped according to the given strategy." + }, + "monospace": { + "anyOf": [ + { + "type": "boolean" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If true, changes the default **fontFamily** to *monospace*, and uses simplified monospaced text metrics calculations." + }, + "pathFilter": { + "anyOf": [ + { + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The image filter for the tip’s box; defaults to a drop shadow." + }, + "pointer": { + "$ref": "#/definitions/TipPointer" + }, + "pointerSize": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The size of the tip’s pointer in pixels; defaults to 12." + }, + "preferredAnchor": { + "anyOf": [ + { + "$ref": "#/definitions/FrameAnchor" + }, + { + "type": "null" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "If an explicit tip anchor is not specified, an anchor is chosen automatically such that the tip fits within the plot’s frame; if the preferred anchor fits, it is chosen." + }, + "textAnchor": { + "anyOf": [ + { + "const": "start", + "type": "string" + }, + { + "const": "middle", + "type": "string" + }, + { + "const": "end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The [text anchor][1] controls how text is aligned (typically horizontally) relative to its anchor point; it is one of *start*, *end*, or *middle*. If the frame anchor is *left*, *top-left*, or *bottom-left*, the default text anchor is *start*; if the frame anchor is *right*, *top-right*, or\n*bottom-right*, the default is *end*; otherwise it is *middle*.\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Attribute/text-anchor" + }, + "textOverflow": { + "anyOf": [ + { + "type": "null" + }, + { + "const": "clip", + "type": "string" + }, + { + "const": "ellipsis", + "type": "string" + }, + { + "const": "clip-start", + "type": "string" + }, + { + "const": "clip-end", + "type": "string" + }, + { + "const": "ellipsis-start", + "type": "string" + }, + { + "const": "ellipsis-middle", + "type": "string" + }, + { + "const": "ellipsis-end", + "type": "string" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "How truncate (or wrap) lines of text longer than the given **lineWidth**; one of:\n\n- null (default) - preserve overflowing characters (and wrap if needed)\n- *clip* or *clip-end* - remove characters from the end\n- *clip-start* - remove characters from the start\n- *ellipsis* or *ellipsis-end* - replace characters from the end with an ellipsis (…)\n- *ellipsis-start* - replace characters from the start with an ellipsis (…)\n- *ellipsis-middle* - replace characters from the middle with an ellipsis (…)\n\nIf no **title** was specified, if text requires truncation, a title containing the non-truncated text will be implicitly added." + }, + "textPadding": { + "anyOf": [ + { + "type": "number" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "The padding around the text in pixels; defaults to 8." + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "x2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending horizontal position channel specifying the tip’s anchor, typically bound to the *x* scale." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y1": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The starting vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + }, + "y2": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The ending vertical position channel specifying the tip’s anchor, typically bound to the *y* scale." + } + }, + "type": "object" + }, + { + "$ref": "#/definitions/ParamRef" + } + ], + "description": "Whether to generate a tooltip for this mark, and any tip options." + }, + "title": { + "$ref": "#/definitions/ChannelValue", + "description": "The title; a channel specifying accessible, short textual descriptions as strings (possibly with newlines). If the tip option is specified, the title will be displayed with an interactive tooltip instead of using the SVG [title element][1].\n\n[1]: https://developer.mozilla.org/en-US/docs/Web/SVG/Element/title" + }, + "x": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The horizontal position channel, typically bound to the *x* scale." + }, + "y": { + "$ref": "#/definitions/ChannelValueSpec", + "description": "The vertical position channel, typically bound to the *y* scale." + }, + "z": { + "$ref": "#/definitions/ChannelValue", + "description": "An optional ordinal channel for grouping to produce multiple (possibly overlapping) triangulations." + } + }, + "required": [ + "data", + "mark" + ], + "type": "object" + }, + "WindowTransform": { + "anyOf": [ + { + "$ref": "#/definitions/RowNumber" + }, + { + "$ref": "#/definitions/Rank" + }, + { + "$ref": "#/definitions/DenseRank" + }, + { + "$ref": "#/definitions/PercentRank" + }, + { + "$ref": "#/definitions/CumeDist" + }, + { + "$ref": "#/definitions/NTile" + }, + { + "$ref": "#/definitions/Lag" + }, + { + "$ref": "#/definitions/Lead" + }, + { + "$ref": "#/definitions/FirstValue" + }, + { + "$ref": "#/definitions/LastValue" + }, + { + "$ref": "#/definitions/NthValue" + } + ] + } + } +}